def _get_mm_case_path_info(self, direct=False): pathinfos = [] linkfield1 = _get_field(self.through, 'content_object') linkfield2 = _get_field(self.through, self.m2m_reverse_field_name()) if direct: join1infos = linkfield1.get_reverse_path_info() join2infos = linkfield2.get_path_info() else: join1infos = linkfield2.get_reverse_path_info() join2infos = linkfield1.get_path_info() pathinfos.extend(join1infos) pathinfos.extend(join2infos) return pathinfos
def _get_gfk_case_path_info(self, direct=False): pathinfos = [] from_field = self.model._meta.pk opts = self.through._meta object_id_field = _get_field(self.through, 'object_id') linkfield = _get_field(self.through, self.m2m_reverse_field_name()) if direct: join1infos = [PathInfo(self.model._meta, opts, [from_field], self.rel, True, False)] join2infos = linkfield.get_path_info() else: join1infos = linkfield.get_reverse_path_info() join2infos = [PathInfo(opts, self.model._meta, [object_id_field], self, True, False)] pathinfos.extend(join1infos) pathinfos.extend(join2infos) return pathinfos
def get_extra_restriction(self, where_class, alias, related_alias): extra_col = _get_field(self.through, 'content_type').column content_type_ids = [ ContentType.objects.get_for_model(subclass).pk for subclass in _get_subclasses(self.model) ] return ExtraJoinRestriction(related_alias, extra_col, content_type_ids)
def similar_objects(self): lookup_kwargs = self._lookup_kwargs() lookup_keys = sorted(lookup_kwargs) qs = self.through.objects.values(*six.iterkeys(lookup_kwargs)) qs = qs.annotate(n=models.Count("pk")) qs = qs.exclude(**lookup_kwargs) qs = qs.filter(tag__in=self.all()) qs = qs.order_by("-n") # TODO: This all feels like a bit of a hack. items = {} if len(lookup_keys) == 1: # Can we do this without a second query by using a select_related() # somehow? f = _get_field(self.through, lookup_keys[0]) objs = f.rel.to._default_manager.filter(**{"%s__in" % f.rel.field_name: [r["content_object"] for r in qs]}) for obj in objs: items[(getattr(obj, f.rel.field_name),)] = obj else: preload = {} for result in qs: preload.setdefault(result["content_type"], set()) preload[result["content_type"]].add(result["object_id"]) for ct, obj_ids in preload.items(): ct = ContentType.objects.get_for_id(ct) for obj in ct.model_class()._default_manager.filter(pk__in=obj_ids): items[(ct.pk, obj.pk)] = obj results = [] for result in qs: obj = items[tuple(result[k] for k in lookup_keys)] obj.similar_tags = result["n"] results.append(obj) return results
def _get_subclasses(model): subclasses = [model] if VERSION < (1, 8): all_fields = (_get_field(model, f) for f in model._meta.get_all_field_names()) else: all_fields = model._meta.get_fields() for field in all_fields: # Django 1.8 + if not RelatedObject and isinstance(field, OneToOneRel) and getattr(field.field.rel, "parent_link", None): subclasses.extend(_get_subclasses(field.related_model)) # < Django 1.8 if RelatedObject and isinstance(field, RelatedObject) and getattr(field.field.rel, "parent_link", None): subclasses.extend(_get_subclasses(field.model)) return subclasses
def _get_subclasses(model): subclasses = [model] if VERSION < (1, 8): all_fields = (_get_field(model, f) for f in model._meta.get_all_field_names()) else: all_fields = model._meta.get_fields() for field in all_fields: # Django 1.8 + if (not RelatedObject and isinstance(field, OneToOneRel) and getattr(field.field.rel, "parent_link", None)): subclasses.extend(_get_subclasses(field.related_model)) # < Django 1.8 if (RelatedObject and isinstance(field, RelatedObject) and getattr(field.field.rel, "parent_link", None)): subclasses.extend(_get_subclasses(field.model)) return subclasses
def similar_objects(self): lookup_kwargs = self._lookup_kwargs() lookup_keys = sorted(lookup_kwargs) qs = self.through.objects.values(*six.iterkeys(lookup_kwargs)) qs = qs.annotate(n=models.Count('pk')) qs = qs.exclude(**lookup_kwargs) qs = qs.filter(tag__in=self.all()) qs = qs.order_by('-n') # TODO: This all feels like a bit of a hack. items = {} if len(lookup_keys) == 1: # Can we do this without a second query by using a select_related() # somehow? f = _get_field(self.through, lookup_keys[0]) remote_field = _remote_field(f) rel_model = _related_model(_remote_field(f)) objs = rel_model._default_manager.filter(**{ "%s__in" % remote_field.field_name: [r["content_object"] for r in qs] }) for obj in objs: items[(getattr(obj, remote_field.field_name),)] = obj else: preload = {} for result in qs: preload.setdefault(result['content_type'], set()) preload[result["content_type"]].add(result["object_id"]) for ct, obj_ids in preload.items(): ct = ContentType.objects.get_for_id(ct) model_class = ct.model_class() if model_class is None: # obsolete content type. Skip it. continue for obj in model_class._default_manager.filter(pk__in=obj_ids): items[(ct.pk, obj.pk)] = obj results = [] for result in qs: res_items = tuple(result[k] for k in lookup_keys) if res_items not in items: continue obj = items[res_items] obj.similar_tags = result["n"] results.append(obj) return results
def similar_objects(self): lookup_kwargs = self._lookup_kwargs() lookup_keys = sorted(lookup_kwargs) qs = self.through.objects.values(*six.iterkeys(lookup_kwargs)) qs = qs.annotate(n=models.Count('pk')) qs = qs.exclude(**lookup_kwargs) qs = qs.filter(tag__in=self.all()) qs = qs.order_by('-n') # TODO: This all feels like a bit of a hack. items = {} if len(lookup_keys) == 1: # Can we do this without a second query by using a select_related() # somehow? f = _get_field(self.through, lookup_keys[0]) remote_field = _remote_field(f) rel_model = _related_model(_remote_field(f)) objs = rel_model._default_manager.filter( **{ "%s__in" % remote_field.field_name: [r["content_object"] for r in qs] }) for obj in objs: items[(getattr(obj, remote_field.field_name), )] = obj else: preload = {} for result in qs: preload.setdefault(result['content_type'], set()) preload[result["content_type"]].add(result["object_id"]) for ct, obj_ids in preload.items(): ct = ContentType.objects.get_for_id(ct) for obj in ct.model_class()._default_manager.filter( pk__in=obj_ids): items[(ct.pk, obj.pk)] = obj results = [] for result in qs: obj = items[tuple(result[k] for k in lookup_keys)] obj.similar_tags = result["n"] results.append(obj) return results
def get_extra_join_sql(self, connection, qn, lhs_alias, rhs_alias): model_name = _model_name(self.through) if rhs_alias == "%s_%s" % (self.through._meta.app_label, model_name): alias_to_join = rhs_alias else: alias_to_join = lhs_alias extra_col = _get_field(self.through, "content_type").column content_type_ids = [ContentType.objects.get_for_model(subclass).pk for subclass in _get_subclasses(self.model)] if len(content_type_ids) == 1: content_type_id = content_type_ids[0] extra_where = " AND %s.%s = %%s" % (qn(alias_to_join), qn(extra_col)) params = [content_type_id] else: extra_where = " AND %s.%s IN (%s)" % ( qn(alias_to_join), qn(extra_col), ",".join(["%s"] * len(content_type_ids)), ) params = content_type_ids return extra_where, params
def get_extra_join_sql(self, connection, qn, lhs_alias, rhs_alias): model_name = _model_name(self.through) if rhs_alias == '%s_%s' % (self.through._meta.app_label, model_name): alias_to_join = rhs_alias else: alias_to_join = lhs_alias extra_col = _get_field(self.through, 'content_type').column content_type_ids = [ContentType.objects.get_for_model(subclass).pk for subclass in _get_subclasses(self.model)] if len(content_type_ids) == 1: content_type_id = content_type_ids[0] extra_where = " AND %s.%s = %%s" % (qn(alias_to_join), qn(extra_col)) params = [content_type_id] else: extra_where = " AND %s.%s IN (%s)" % (qn(alias_to_join), qn(extra_col), ','.join(['%s'] * len(content_type_ids))) params = content_type_ids return extra_where, params
def tag_relname(cls): return _get_field(cls, 'tag').rel.related_name
def m2m_reverse_field_name(self): return _get_field(self.through, 'tag').name
def tag_model(cls): return _get_field(cls, 'tag').rel.to
def tag_relname(cls): field = _get_field(cls, 'tag') return field.remote_field.related_name if VERSION >= ( 1, 9) else field.rel.related_name
def tag_model(cls): field = _get_field(cls, 'tag') return field.remote_field.model if VERSION >= (1, 9) else field.rel.to
def related_fields(self): return [(_get_field(self.through, 'object_id'), self.model._meta.pk)]
def m2m_reverse_name(self): return _get_field(self.through, "tag").column
def tag_relname(cls): field = _get_field(cls, 'tag') return field.remote_field.related_name if VERSION >= (1, 9) else field.rel.related_name
def get_extra_restriction(self, where_class, alias, related_alias): extra_col = _get_field(self.through, 'content_type').column content_type_ids = [ContentType.objects.get_for_model(subclass).pk for subclass in _get_subclasses(self.model)] return ExtraJoinRestriction(related_alias, extra_col, content_type_ids)