mirror of https://github.com/django/django.git
parent
17c3997f68
commit
52015b963d
|
@ -580,17 +580,20 @@ def create_many_related_manager(superclass, rel):
|
||||||
)
|
)
|
||||||
do_not_call_in_templates = True
|
do_not_call_in_templates = True
|
||||||
|
|
||||||
def _build_clear_filters(self, qs):
|
def _build_remove_filters(self, removed_vals):
|
||||||
filters = Q(**{
|
filters = Q(**{self.source_field_name: self.related_val})
|
||||||
self.source_field_name: self.related_val,
|
# No need to add a subquery condition if removed_vals is a QuerySet without
|
||||||
'%s__in' % self.target_field_name: qs
|
# filters.
|
||||||
})
|
removed_vals_filters = (not isinstance(removed_vals, QuerySet) or
|
||||||
|
removed_vals._has_filters())
|
||||||
|
if removed_vals_filters:
|
||||||
|
filters &= Q(**{'%s__in' % self.target_field_name: removed_vals})
|
||||||
if self.symmetrical:
|
if self.symmetrical:
|
||||||
filters |= Q(**{
|
symmetrical_filters = Q(**{self.target_field_name: self.related_val})
|
||||||
self.target_field_name: self.related_val,
|
if removed_vals_filters:
|
||||||
'%s__in' % self.source_field_name: qs
|
symmetrical_filters &= Q(
|
||||||
})
|
**{'%s__in' % self.source_field_name: removed_vals})
|
||||||
|
filters |= symmetrical_filters
|
||||||
return filters
|
return filters
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
|
@ -654,7 +657,7 @@ def create_many_related_manager(superclass, rel):
|
||||||
signals.m2m_changed.send(sender=self.through, action="pre_clear",
|
signals.m2m_changed.send(sender=self.through, action="pre_clear",
|
||||||
instance=self.instance, reverse=self.reverse,
|
instance=self.instance, reverse=self.reverse,
|
||||||
model=self.model, pk_set=None, using=db)
|
model=self.model, pk_set=None, using=db)
|
||||||
filters = self._build_clear_filters(self.using(db))
|
filters = self._build_remove_filters(super(ManyRelatedManager, self).get_queryset().using(db))
|
||||||
self.through._default_manager.using(db).filter(filters).delete()
|
self.through._default_manager.using(db).filter(filters).delete()
|
||||||
|
|
||||||
signals.m2m_changed.send(sender=self.through, action="post_clear",
|
signals.m2m_changed.send(sender=self.through, action="post_clear",
|
||||||
|
@ -763,10 +766,13 @@ def create_many_related_manager(superclass, rel):
|
||||||
signals.m2m_changed.send(sender=self.through, action="pre_remove",
|
signals.m2m_changed.send(sender=self.through, action="pre_remove",
|
||||||
instance=self.instance, reverse=self.reverse,
|
instance=self.instance, reverse=self.reverse,
|
||||||
model=self.model, pk_set=old_ids, using=db)
|
model=self.model, pk_set=old_ids, using=db)
|
||||||
|
target_model_qs = super(ManyRelatedManager, self).get_queryset()
|
||||||
old_vals_qs = self.using(db).filter(**{
|
if target_model_qs._has_filters():
|
||||||
'%s__in' % self.target_field.related_field.attname: old_ids})
|
old_vals = target_model_qs.using(db).filter(**{
|
||||||
filters = self._build_clear_filters(old_vals_qs)
|
'%s__in' % self.target_field.related_field.attname: old_ids})
|
||||||
|
else:
|
||||||
|
old_vals = old_ids
|
||||||
|
filters = self._build_remove_filters(old_vals)
|
||||||
self.through._default_manager.using(db).filter(filters).delete()
|
self.through._default_manager.using(db).filter(filters).delete()
|
||||||
|
|
||||||
signals.m2m_changed.send(sender=self.through, action="post_remove",
|
signals.m2m_changed.send(sender=self.through, action="post_remove",
|
||||||
|
|
|
@ -1026,6 +1026,14 @@ class QuerySet(object):
|
||||||
# If we have a new hint for an existing key, overwrite with the new value.
|
# If we have a new hint for an existing key, overwrite with the new value.
|
||||||
self._hints.update(hints)
|
self._hints.update(hints)
|
||||||
|
|
||||||
|
def _has_filters(self):
|
||||||
|
"""
|
||||||
|
Checks if this QuerySet has any filtering going on. Note that this
|
||||||
|
isn't equivalent for checking if all objects are present in results,
|
||||||
|
for example qs[1:]._has_filters() -> True.
|
||||||
|
"""
|
||||||
|
return self.query.has_filters()
|
||||||
|
|
||||||
|
|
||||||
class InstanceCheckMeta(type):
|
class InstanceCheckMeta(type):
|
||||||
def __instancecheck__(self, instance):
|
def __instancecheck__(self, instance):
|
||||||
|
|
|
@ -430,6 +430,9 @@ class Query(object):
|
||||||
|
|
||||||
return number
|
return number
|
||||||
|
|
||||||
|
def has_filters(self):
|
||||||
|
return self.where or self.having
|
||||||
|
|
||||||
def has_results(self, using):
|
def has_results(self, using):
|
||||||
q = self.clone()
|
q = self.clone()
|
||||||
if not q.distinct:
|
if not q.distinct:
|
||||||
|
|
Loading…
Reference in New Issue