如何简单有效地为对象建模用户特定信息?
How to model User specific information for Objects simple and efficiently?
作为示例,我将使用以下代码,显示类似于堆栈溢出的 'question' 和用户特定信息,例如已加星标 post。
class Question(models.Model):
title = models.CharField(max_length=200)
body = models.CharField(max_length=2000)
class Star(models.Model):
owner = models.ForeignKey(User, on_delete=models.CASCADE)
question = models.ForeignKey(Question, on_delete=models.CASCADE)
starred = models.BooleanField()
现在的目标是创建所有(或最后 20 个)问题的列表,并在此概览中向用户显示他们加星标的问题。
How to Handle bad Questions? (X)
Why use Fluroid in toothpaste? ( )
Where is Waldo? (X)
这取决于当前登录的用户。
创建列表很简单,但添加布尔值似乎相当笨拙或效率低下,而在直接 SQL 中,这可以表示为左外连接(只需用 false 填充不存在的值).
我试过了:
- select 相关不能使用,因为并非所有问题都有星号
- 由于无法在方法调用中使用参数,因此无法在模板中反转关系
- 循环列表并使用 .get() 添加次要信息
所以我想知道是否有一种简单的方法来处理这种模式?
编辑:答案似乎是:否,没有简单的方法,但接受的答案帮助我找到了解决方案(谢谢)。
注意:为了清楚起见,我重写了问题。请记住,我是 Django 的初学者,可能错过了一些重要的简单事情。
改写问题后,我意识到它类似于实现一个赞按钮:Django Like Button
基于您编辑的问题的新答案:
这个"solution"是一个猜测。所以请尝试一下。它可能无法完全按照写的那样工作,或者有效的解决方案可能超出了我现在的想法。
- 收集所有问题
- 将问题减少到您想向用户显示的问题
- 创建一个独立的查询集,仅包含 2.
中加星标的问题
- 为2.的每个问题添加一个人工属性,代表你需要在每个问题后'X'放置的信息
- 将更改后的查询集获取到模板
views.py:
questions = Question.objects.all()
# limit your results now
# I assume 'questions' going forward was reduced to the number of results you want to show
starred_questions = questions.filter(star_set__owner=request.user, star_set__starred=True)
for question in questions:
question.starred = question in starred_questions
# get 'questions' to your view now
- 循环问题
- 显示问题
- 如果人工属性存在且为 True
,则添加 'X'
my_template.html:
{% for question in questions %}
<p>{{ question }}(
{% if question.starred %}
X
{% endif %}
)</p>
{% endfor %}
我希望这种方法能帮助您实现目标。
旧答案:
基于
I wanted to show a list of all As and show the associated Bs for a user.
这句话我猜你的观点是用户特定的?这意味着如果用户 X 访问该视图,该用户会看到他们自己的值,如果用户 Y 访问该视图,他们会再次看到他们自己的值吗?
all_b_of_user = request.user.b_set.all().select_related('a')
select_related
获取同一查询中的所有数据,以减少查询次数,从而减少响应时间。 doc
另一方面,如果您想在某种概览中显示所有用户的所有值(允许某些用户 Z 查看 X 和 Y 的所有值),您需要创建尽可能多的数据库查询据我所知你有用户。
from django.views import View
from django.contrib.auth.mixins import LoginRequiredMixin
from .models import Question, Star
class StarredQuestionsView(LoginrequiredMixin, View):
def get(self, request):
starred_questions = Star.objects.filter(owner=request.user).filter(starred=True)
return render(request, "app/list-of-starred-questions.html", {'starred_questions': starred_questions})
这应该会为您提供所有用户已加星标的问题的查询集。在您看来,您可以这样做:
{% for question in starred_questions %}
<ul>
<li>{{ question.question.title }}</li>
</ul>
{% endfor %}
希望这能让您走上正确的道路。
作为示例,我将使用以下代码,显示类似于堆栈溢出的 'question' 和用户特定信息,例如已加星标 post。
class Question(models.Model):
title = models.CharField(max_length=200)
body = models.CharField(max_length=2000)
class Star(models.Model):
owner = models.ForeignKey(User, on_delete=models.CASCADE)
question = models.ForeignKey(Question, on_delete=models.CASCADE)
starred = models.BooleanField()
现在的目标是创建所有(或最后 20 个)问题的列表,并在此概览中向用户显示他们加星标的问题。
How to Handle bad Questions? (X)
Why use Fluroid in toothpaste? ( )
Where is Waldo? (X)
这取决于当前登录的用户。
创建列表很简单,但添加布尔值似乎相当笨拙或效率低下,而在直接 SQL 中,这可以表示为左外连接(只需用 false 填充不存在的值).
我试过了:
- select 相关不能使用,因为并非所有问题都有星号
- 由于无法在方法调用中使用参数,因此无法在模板中反转关系
- 循环列表并使用 .get() 添加次要信息
所以我想知道是否有一种简单的方法来处理这种模式? 编辑:答案似乎是:否,没有简单的方法,但接受的答案帮助我找到了解决方案(谢谢)。
注意:为了清楚起见,我重写了问题。请记住,我是 Django 的初学者,可能错过了一些重要的简单事情。
改写问题后,我意识到它类似于实现一个赞按钮:Django Like Button
基于您编辑的问题的新答案:
这个"solution"是一个猜测。所以请尝试一下。它可能无法完全按照写的那样工作,或者有效的解决方案可能超出了我现在的想法。
- 收集所有问题
- 将问题减少到您想向用户显示的问题
- 创建一个独立的查询集,仅包含 2. 中加星标的问题
- 为2.的每个问题添加一个人工属性,代表你需要在每个问题后'X'放置的信息
- 将更改后的查询集获取到模板
views.py:
questions = Question.objects.all()
# limit your results now
# I assume 'questions' going forward was reduced to the number of results you want to show
starred_questions = questions.filter(star_set__owner=request.user, star_set__starred=True)
for question in questions:
question.starred = question in starred_questions
# get 'questions' to your view now
- 循环问题
- 显示问题
- 如果人工属性存在且为 True ,则添加 'X'
my_template.html:
{% for question in questions %}
<p>{{ question }}(
{% if question.starred %}
X
{% endif %}
)</p>
{% endfor %}
我希望这种方法能帮助您实现目标。
旧答案: 基于
I wanted to show a list of all As and show the associated Bs for a user.
这句话我猜你的观点是用户特定的?这意味着如果用户 X 访问该视图,该用户会看到他们自己的值,如果用户 Y 访问该视图,他们会再次看到他们自己的值吗?
all_b_of_user = request.user.b_set.all().select_related('a')
select_related
获取同一查询中的所有数据,以减少查询次数,从而减少响应时间。 doc
另一方面,如果您想在某种概览中显示所有用户的所有值(允许某些用户 Z 查看 X 和 Y 的所有值),您需要创建尽可能多的数据库查询据我所知你有用户。
from django.views import View
from django.contrib.auth.mixins import LoginRequiredMixin
from .models import Question, Star
class StarredQuestionsView(LoginrequiredMixin, View):
def get(self, request):
starred_questions = Star.objects.filter(owner=request.user).filter(starred=True)
return render(request, "app/list-of-starred-questions.html", {'starred_questions': starred_questions})
这应该会为您提供所有用户已加星标的问题的查询集。在您看来,您可以这样做:
{% for question in starred_questions %}
<ul>
<li>{{ question.question.title }}</li>
</ul>
{% endfor %}
希望这能让您走上正确的道路。