Comments 3
Если же, нас интересуют такие блоги, в которых есть одновременно и записи от 2008 года, и записи, содержащие Lennon в своем заголовке, то нужно писать
Blog.objects.filter(entry__headline__contains="Lennon").filter(entry__pub_date__year=2008)
Мне всё-таки формулировка кажется непонятной. В оригинале - так:
"query selecting any blogs with merely some entry with “Lennon” in its headline and some entry from 2008".
Т.е.:
filter(a, b)
— совпадение на одном связанном объекте.filter(a).filter(b)
— совпадения могут быть на разных связанных объектах.
На мой взгляд, переводить документацию, не очень понимая, как это работает, плохая идея.
Например:
def get_tags(blog_id):
qs = Tag.objects.filter(entry__is_hidden=False)
if blog_id is not None:
qs = qs.filter(entry__blog_id=blog_id)
return qs.distinct()
это:
def get_tags(blog): # blog is instance of Blog
# You can do: Blog(pk=blog_id) if you have only id, but this is strange
qs = blog.tags if blog.pk else blog.tags.all().model.objects
return qs.visible()
Важно, что во втором примере нет ссылки на класс тегов, не надо импортировать класс, в функции скрыта имплементации, как блог ищет теги, и как теги становятся видимыми.
Ну и, конечно же, это должен быть метод класса Blog. Это же OOP-Django, а не FB-FastAPI парадигма.
При наличии хорошей django-tagging, в принципе непонятно, о чем речь, и зачем велосипедить.
Кстати, если начали работать с Q - стоит почитать документацию про конкатенацию Q:
class TagQueryset(queryset):
def get_tags_mixed_fixed(self):
blog = self._hints.get('instance')
conditions = Q(entry__is_hidden=False)
if blog is not None:
conditions +=.Q(entry__blog=blog)
return self.filter(conditions).distinct()
class Tag(models.Model):
objects = TagQueryset.as_manager()
....
tags_from_blog = blog.tags.get_tags_mixed_fixed()
И я бы написал в Django так:
class TagQueryset(queryset):
def get_tags(self):
qs = self if self._hints.get('instance') else self.model.objects
return qs.visible().distinct()
def visible(self):
return self.filter(entry__is_hidden=False)
class Tag(models.Model):
objects = TagQueryset.as_manager()
...
class Blog(models.Model):
def get_tags(self):
return self.tags.get_tags()
В любом случае @damirych, поздравляю с первой статьей! Вышло отлично!
Некоторые неочевидные особенности Django ORM (filter и exclude)