Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在嵌套for循环中过滤(django模板)_Django_Templates_Filter_Foreign Keys_Nested Loops - Fatal编程技术网

在嵌套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循环限制为仅过滤书籍?我是