在嵌套for循环中过滤(django模板)
我有两个模型,书和类型在嵌套for循环中过滤(django模板),django,templates,filter,foreign-keys,nested-loops,Django,Templates,Filter,Foreign Keys,Nested Loops,我有两个模型,书和类型 class Book(models.Model): title = models.CharField(max_length=300) author = models.CharField(max_length=100) year = models.IntegerField() genre = models.ForeignKey('Genre', on_delete=models.CASCADE) class Genre(models
class Book(models.Model):
title = models.CharField(max_length=300)
author = models.CharField(max_length=100)
year = models.IntegerField()
genre = models.ForeignKey('Genre', on_delete=models.CASCADE)
class Genre(models.Model):
title = models.CharField(max_length=20)
在我的网页上,我想显示每个流派,在每个流派中,只显示1950年或更高年份的书籍。我的模板中的代码如下所示:
{% for genre in genres %}
<h1> {{genre.title}} </h1>
{% for book in genre.book_set.all %}
{{book.title}}
{% endfor %}
{% endfor %}
def books_home(request):
books = Book.objects.filter(year__gt='1950')
genres = Genre.objects.all()
return render(request, "index.html", {"books": books, "genres": genres})
{% for key, values in books.items %}
<h1> {{key}} </h1>
{% for book in values %}
{{book}}
{% endfor %}
{% endear%}
也就是说,我正在尝试在这个阶段过滤书籍,但它没有通过模板 我建议您在视图中进行过滤,而不是模板本身。 在那里,您可以使用所有djangos特性,而不需要为模板实现自定义标记/过滤器。 然后,您还可以在以后使用select\u/prefetch\u进行查询优化(如果您得到更多查询) 例如:
类myview(…):
qs=Genre.objects.filter(图书集年期=1950)
...
另请参见中的字段查找,以便使用
gt
进行筛选。我建议您在视图中进行筛选,而不是模板本身。
在那里,您可以使用所有djangos特性,而不需要为模板实现自定义标记/过滤器。
然后,您还可以在以后使用select\u/prefetch\u进行查询优化(如果您得到更多查询)
例如:
类myview(…):
qs=Genre.objects.filter(图书集年期=1950)
...
另请参见中的字段查找,以便使用
gt
进行筛选。我知道您已将答案标记为正确,但根据我在下面的评论,它确实不是正确的答案@wfehr为您提供了一个更好的解决方案,尽管这是一个非常简短的答案,根据您的问题,我怀疑您需要更多的细节
class Book(models.Model):
title = models.CharField(max_length=300)
author = models.CharField(max_length=100)
year = models.IntegerField()
genre = models.ForeignKey('Genre', on_delete=models.CASCADE)
class Genre(models.Model):
title = models.CharField(max_length=20)
您的模型很好,但是可以通过以下方式进行改进:
在一书中
类更改:
class Book(models.Model):
...
genre = models.ForeignKey('Genre', on_delete=models.CASCADE, related_name="books")
...
通过添加此相关名称,您可以使用类型进行反向查找,例如:
myGenre.books.all()
这将为你提供所有这类书籍
无论如何,我离题了
在返回模板的View.py
中,您只需过滤查询集以获得要显示的确切信息,而不是按照您标记为正确的答案将该逻辑包含在模板中
我想目前你的观点是这样的:
render("template.html", {genres=Genre.objects.all()})
不要使用Genre.objects.all()
,而是使用Book
和反向Book
:
Book.objects.order_by('-genre').filter(year__gte=1950)
这样你只会得到你真正想要的书<代码>gte
为“大于或等于”;如果您只想在1950年之后使用,请将其更改为year\uu gt
此外,如果您只需要书的标题和类型,您可以:
Book.objects.order_by('-genre').filter(year__gte=1950).values_list("title", pk)
您只使用标题,但可以指定所需的任何模型字段
上面的解决方案并没有按类型划分,所以您需要在那里做更多的工作。您可以使用annotate
而不是值列表来完成此操作,或者只需先获取流派,然后执行以下操作:
(注意:使用annotate
会将DB调用减少到1,但根据类型的数量,这可能不是问题:
books = {}
for genre in Genre.objects.all().order_by('-title'):
books[genre.title] = Book.objects.order_by('-genre').filter(year__gte=1950, genre=genre).values_list("title")
使用order\u by('-title')
只会确保我们在流派中获得一些顺序——在本例中是按字母顺序排列的
然后,您可以返回context=books
或将其添加到当前的上下文对象中,然后使用如下内容相应地调整模板:
{% for genre in genres %}
<h1> {{genre.title}} </h1>
{% for book in genre.book_set.all %}
{{book.title}}
{% endfor %}
{% endfor %}
def books_home(request):
books = Book.objects.filter(year__gt='1950')
genres = Genre.objects.all()
return render(request, "index.html", {"books": books, "genres": genres})
{% for key, values in books.items %}
<h1> {{key}} </h1>
{% for book in values %}
{{book}}
{% endfor %}
{% endear%}
我添加这一点只是为了参考;如果你需要添加流派,或者你将拥有很多流派,使用该模型会更好。我知道你已将答案标记为正确,但根据我在下面的评论,这确实不是正确的答案。@wfehr为你提供了更好的解决方案,尽管这是一个非常简短的答案,根据你的问题,我怀疑你需要更多的细节
class Book(models.Model):
title = models.CharField(max_length=300)
author = models.CharField(max_length=100)
year = models.IntegerField()
genre = models.ForeignKey('Genre', on_delete=models.CASCADE)
class Genre(models.Model):
title = models.CharField(max_length=20)
您的模型很好,但是可以通过以下方式进行改进:
在一书中
类更改:
class Book(models.Model):
...
genre = models.ForeignKey('Genre', on_delete=models.CASCADE, related_name="books")
...
通过添加此相关名称,您可以使用类型进行反向查找,例如:
myGenre.books.all()
这将为你提供所有这类书籍
无论如何,我离题了
在返回模板的View.py
中,您只需过滤查询集以获得要显示的确切信息,而不是按照您标记为正确的答案将该逻辑包含在模板中
我想目前你的观点是这样的:
render("template.html", {genres=Genre.objects.all()})
不要使用Genre.objects.all()
,而是使用Book
和反向Book
:
Book.objects.order_by('-genre').filter(year__gte=1950)
这样你只会得到你真正想要的书。gte
是“大于或等于”;如果你只是在1950年之后想要,那么就把它改为year\ugt
此外,如果您只需要书的标题和类型,您可以:
Book.objects.order_by('-genre').filter(year__gte=1950).values_list("title", pk)
您只使用标题,但可以指定所需的任何模型字段
上面的解决方案没有按Genre
s进行拆分,因此您需要在那里做更多的工作。您可以使用annotate
而不是值列表来完成这项工作,或者您可以简单地先获取流派,然后执行以下操作:
(注意:使用annotate
会将DB调用减少到1,但根据类型的数量,这可能不是问题:
books = {}
for genre in Genre.objects.all().order_by('-title'):
books[genre.title] = Book.objects.order_by('-genre').filter(year__gte=1950, genre=genre).values_list("title")
使用order\u by('-title')
只会确保我们在流派中获得一些顺序——在本例中是按字母顺序排列的
然后,您可以返回context=books
或将其添加到当前的上下文对象中,然后使用如下内容相应地调整模板:
{% for genre in genres %}
<h1> {{genre.title}} </h1>
{% for book in genre.book_set.all %}
{{book.title}}
{% endfor %}
{% endfor %}
def books_home(request):
books = Book.objects.filter(year__gt='1950')
genres = Genre.objects.all()
return render(request, "index.html", {"books": books, "genres": genres})
{% for key, values in books.items %}
<h1> {{key}} </h1>
{% for book in values %}
{{book}}
{% endfor %}
{% endear%}
我添加这些只是为了参考;如果您需要添加流派,或者您将拥有很多流派,使用该模型会更好。好的,但是如何将嵌套for循环限制为仅过滤的书籍?我仍然必须使用向后关系语句{%forbook in genre.book\u set.all%}获取相关类型的书籍,但此语句带来了该类型的所有书籍。我无法在视图阶段过滤这些书籍…好的,但是如何将嵌套for循环限制为仅过滤书籍?我是