我有一个反复出现的问题,我似乎无法充分解决。我的网站类似于工作网站,人们可以在那里发布工作(和详细信息),其他人可以为他们添加书签。显然,每个作业都可以被多个观看者加入书签。
所以这是model.py:
class Job(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
title = models.CharField(max_length=150)
description = models.CharField(max_length=5000)
class Bookmark(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
job = models.ForeignKey(Job, on_delete=models.CASCADE)
我的目的是在主页中显示所有作业,这意味着来自多个用户的多个作业。其他用户可以单击一个小书签图标来为其添加书签,或者取消对其进行书签。像这样:
这是view.py:
def index(request):
context = {}
populateContext(request, context)
jobs = Job.objects.all().order_by('-id')
context = {'jobs': jobs}
return render(request, 'templates/index.html', context)
我觉得很简单,这是我的意图。以下是模板的外观:
{% for job in jobs %}
<div>
{{ job.title }}<br>
{{ job.description }}<br>
by {{ job.user.username }}
</div>
{% endfor %}
我的问题是,如何显示特定于每个用户的书签状态?这是我目前的解决方案:
{% for job in jobs %}
<div>
{{ job.title }}<br>
{{ job.description }}<br>
by {{ job.user.username }}<br>
{% for watch in job.bookmark_set.all %}
{% if watch.user_id = request.user.id %}
You have bookmarked this! <a>Unbookmark!</a>
{% endif %}
{% endfor %}
<a>Bookmark</a>
</div>
{% endfor %}
“Unbookmark!”顺便说一句,链接将定位在“书签”链接上。上述解决方案以这种方式工作,因为书签表将包含特定作业的零个或多个书签,但在多个用户下。我会在view.py中通过过滤登录用户所做的作业来处理这个问题。但我不能专门过滤哪个工作,因为index.html将全部显示它们。例如,我可以吐出来......:
bookmarked = Bookmark.objects.all().filter(user_id=request.user.id)
...这将列出登录用户所做的不同作业的所有书签。我仍然需要在模板中对其进行过滤,以便每个项目都与每个书签匹配,我理解这是不可能的。
无论如何,我认为这是非常低效的。所以我想知道是否有更简单的方法来处理这个问题?最好是以这种方式工作:
{% for job in jobs %}
<div>
{{ job.title }}<br>
{{ job.description }}<br>
by {{ job.user.username }}<br>
{% if job.id = bookmark.job.id %}
You have bookmarked this! <a>Unbookmark!</a>
{% else %}
<a>Bookmark</a>
{% endif %}
</div>
{% endfor %}
谢谢!
答案 0 :(得分:4)
您可以使用conditional expressions使用此信息为jobs
添加注释。在视图中:
from django.db.models import Case, IntegerField, Sum, When
jobs = Job.objects.annotate(
is_bookmarked=Sum(Case(
When(bookmark__user=request.user, then=1),
default=0, output_field=IntegerField()
))).order_by('-id')
每个job
现在都有is_bookmarked
属性,该属性为1
(用户为作业添加了书签)或0
。在您的模板中:
{% for job in jobs %}
<div>
{% if job.is_bookmarked %}
You have bookmarked this! <a>Unbookmark!</a>
{% else %}
<a>Bookmark</a>
{% endif %}
</div>
{% endfor %}
为了完整起见,你想到的另一种方法也会起作用(虽然效率低于上面的方法)。在视图中:
jobs = Job.objects.all().order_by('-id')
# Get a list of all Job IDs bookmarked by this user
user_bookmarks = Bookmark.objects.filter(user_id=request.user.id)\
.values_list('job__id', flat=True)
在模板中:
{% for job in jobs %}
<div>
{% if job.id in user_bookmarks %}
You have bookmarked this! <a>Unbookmark!</a>
{% else %}
<a>Bookmark</a>
{% endif %}
</div>
{% endfor %}
这两种方法都采用了几乎相同的逻辑 - 不同之处在于第一种方法在数据库级别执行此操作通常更有效。