如何简单有效地为对象建模用户特定信息?

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 填充不存在的值).

我试过了:

所以我想知道是否有一种简单的方法来处理这种模式? 编辑:答案似乎是:否,没有简单的方法,但接受的答案帮助我找到了解决方案(谢谢)。

注意:为了清楚起见,我重写了问题。请记住,我是 Django 的初学者,可能错过了一些重要的简单事情。

改写问题后,我意识到它类似于实现一个赞按钮:Django Like Button

基于您编辑的问题的新答案:

这个"solution"是一个猜测。所以请尝试一下。它可能无法完全按照写的那样工作,或者有效的解决方案可能超出了我现在的想法。

  1. 收集所有问题
  2. 将问题减少到您想向用户显示的问题
  3. 创建一个独立的查询集,仅包含 2.
  4. 中加星标的问题
  5. 为2.的每个问题添加一个人工属性,代表你需要在每个问题后'X'放置的信息
  6. 将更改后的查询集获取到模板

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
  1. 循环问题
  2. 显示问题
  3. 如果人工属性存在且为 True
  4. ,则添加 '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 %}

希望这能让您走上正确的道路。