很显然,我正在为Django中的各种抓取对象而苦苦挣扎。这是另一个。
这是针对我一直在使用的同一库应用程序(以防您遇到其他问题)。
在主页上,我显示活动用户的名称和信息(这很好)。然后,我希望显示活动用户撰写的所有评论。我基本上也可以做到这一点,除了它只显示评论而不参考他们应该描述的书。
所以...我需要能够通过其Review对象来获取Book对象。换句话说,每次我显示评论时,我都希望能够获取与之相关的书(书名和作者)。请记住,我无法由用户(使用created_by)来抓取书,因为用户可以为未添加到数据库中的书撰写评论。我希望这是有道理的,但我相信您可以看到我正在为此类问题而苦苦挣扎。
在models.py中,我像这样设置表(请注意,User表位于其他应用程序中):
class Book(models.Model):
title = models.CharField(max_length=100)
author = models.ForeignKey("Author", on_delete=models.CASCADE, related_name="books")
created_by = models.ForeignKey(User, on_delete=models.CASCADE, related_name="books_added")
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
objects = BookManager()
class Author(models.Model):
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
objects = AuthorManager()
class Review(models.Model):
rating = models.IntegerField()
comments = models.TextField()
book = models.ForeignKey("Book", on_delete=models.CASCADE, related_name="reviews")
created_by = models.ForeignKey(User, on_delete=models.CASCADE, related_name="reviews_added")
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
objects = ReviewManager()
然后在views.py中,我试图通过引用Review对象来定义变量“ book”(因为book是review中的一个字段)。像这样:
def books_home(request):
if request.method == "GET":
first_name = User.objects.get(id=request.session['uid']).first_name
last_name = User.objects.get(id=request.session['uid']).last_name
email = User.objects.get(id=request.session['uid']).email
user_id = User.objects.get(id=request.session['uid']).id
reviews = Review.objects.filter(created_by=user_id)
book = Review.objects.filter(created_by=user_id).book
context = {
'first_name' : first_name,
'email' : email,
'last_name' : last_name,
'reviews' : reviews,
'book' : book
}
return render(request, 'html_files/home.html', context=context)
请记住,在上下文中,book = Review.objects.filter(created_by=user_id).book' and
“ book”:book`之外的所有内容基本上都可以使用。
还请记住,我是Django和一般编程人员的新手。我敢肯定有更优雅的方法可以做到这一点,但是我坚持使用我所理解的方法,因此在回答时,请尽量保持与当前代码尽可能接近。 “使它工作,然后使其更好地工作。”
我相信我知道该在模板中做什么以显示上下文指示,所以这不是问题。如果有帮助的话,代码在GitHub上。
谢谢。
答案 0 :(得分:0)
评论过滤器将返回一个评论查询集,该查询集可以是Book的一个或多个实例,因此您无法访问查询集上的.book
。
您要从哪几本评论归还一本书?
相反,在模板中,使用{{ review.book }}
来访问每个评论的书。为防止每次访问书籍时都触及数据库,请使用select_related()
。
通常,数据库访问不是最佳的,您要多次访问数据库(每次.get()
)。而是访问一次,并将其存储在变量中。
此外,当您对用户进行过滤时,使用用户实例本身进行过滤,Django将处理簿记:
user = User.objects.get(id=request.session['uid'])
reviews = Review.objects.filter(created_by=user)
但是,您已经为反向外键关系定义了related_name
,为什么不使用它呢?
修改为:
def books_home(request):
if request.method == "GET":
user = User.objects.get(id=request.session['uid'])
reviews = user.reviews_added.select_related('book')
context = {
'first_name' : user.first_name,
'email' : user.email,
'last_name' : user.last_name,
'reviews' : reviews,
}
return render(request, 'html_files/home.html', context=context)
每个评论都将具有相关的书籍实例,因此在模板中:
{% for review in reviews %}
{{ review.book.title }}
{% endfor %}
有关信息,请参见Related objects reference。