简体   繁体   English

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

[英]How to model User specific information for Objects simple and efficiently?

As an example, I will use the following code, showing a 'question' similar to stack overflow, and User specific information, eg, having starred the 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()

The goal is now to create a list of all (or the last 20) questions and show a user in this overview which ones they starred. 现在的目标是创建所有(或最后20个)问题的列表,并在此概述中向用户显示他们曾打过哪些问题。

How to Handle bad Questions? 如何处理坏问题? (X) (X)

Why use Fluroid in toothpaste? 为什么在牙膏中使用Fluroid? ( ) ()

Where is Waldo? 沃尔多在哪里? (X) (X)

This is dependent on the current logged in user. 这取决于当前登录的用户。

Creating the list is straight forward, but adding in the boolean seems rather clumsy or inefficient, while in direct SQL, this could be expressed as a left outer join (just fill up non existent values with false). 创建列表很简单,但是添加布尔值似乎相当笨拙或效率低下,而在直接SQL中,这可以表示为左外部联接(只需用false填充不存在的值)。

I tried: 我试过了:

  • select related can not be used, as not all questions have starred entries 选择相关无法使用,因为并非所有问题都带有星号
  • Reversing the relationship in the template does not work due not being able to use a parameter on method calls 由于无法在方法调用中使用参数,因此无法反转模板中的关系
  • Looping the list and adding the secondary information with a .get() 循环列表并使用.get()添加辅助信息

So I wondered if there is a simple way to handle this pattern? 所以我想知道是否有一种简单的方法来处理这种模式? Edit: The answer seems to be: No , there is no simple way, but the accepted answer helped me reach a solution (thanks). 编辑: 答案似乎是:不 ,没有简单的方法,但是被接受的答案帮助我达成了解决方案(谢谢)。

Note: I rewrote the question for clarity. 注意:为了清楚起见,我重写了这个问题。 Please keep in mind I am a beginner with Django and might have missed some crucial simple thing. 请记住,我是Django的初学者,可能错过了一些关键的简单事情。

After rephrasing the question I realized it is similar to implementing a like button: Django Like Button 改写问题后,我意识到它类似于实现一个like按钮: Django Like Button

New answer based on your edited question: 根据您编辑的问题的新答案:

This "solution" is a guess. 这种“解决方案”是一种猜测。 So please try it out. 因此,请尝试一下。 It might not work exactly as written, or a valid solution might be outside of what I can think of right now. 它可能无法完全按照书面规定工作,或者有效的解决方案可能超出了我现在能想到的范围。

  1. Collect all questions 收集所有问题
  2. Reduce questions to the ones you want to show to user 将问题减少到您要向用户显示的问题
  3. Create an independent queryset that contains only starred questions of the 2. 创建一个仅包含2的已加星标问题的独立查询集。
  4. Add an artificial attribute to each question of 2. which represents the information you need to put 'X' after each question 在每个问题2中添加一个人工属性,该属性表示您需要在每个问题后加上“ X”的信息
  5. Get that changed queryset to the template 将更改后的查询集获取到模板

views.py: 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. Loop over questions 循环提问
  2. Show question 显示问题
  3. Add 'X' if artificial attribute is present and True 如果存在人工属性,则添加“ X”,并且为True

my_template.html: my_template.html:

{% for question in questions %}
    <p>{{ question }}(
        {% if question.starred %}
            X
        {% endif %}
    )</p>
{% endfor %}

I hope this approach will help you reach your goal. 我希望这种方法将帮助您实现目标。


Old answer: Based on 旧答案:基于

I wanted to show a list of all As and show the associated Bs for a user. 我想显示所有A的列表,并为用户显示相关的B。

this phrase I guess your view is user specific? 我想你这句话是针对用户的吗? Meaning that if user X visits that view, that user sees their own values and if user Y visits that view, they see their own values ones again? 就是说,如果用户X访问该视图,那么该用户将看到他们自己的值,如果用户Y访问该视图,那么他们将再次看到他们自己的值?

all_b_of_user = request.user.b_set.all().select_related('a')

select_related gets all a data in that same query, to reduce query count, thus response time. select_related在同一查询中获取所有数据,以减少查询数量,从而减少响应时间。 doc doc

If on the other hand you want to show all values of all users on some sort of overview (some user Z is allowed to see all values of X and Y) you'll need to create as many DB queries as you have Users as far as I know. 另一方面,如果您想在某种概览中显示所有用户的所有值(允许某些用户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})

This should give you a queryset of all a user's starred questions. 这应该为您提供所有用户已加星标问题的查询集。 In your view, you can do something like this: 在您看来,您可以执行以下操作:

{% for question in starred_questions %}
<ul>
<li>{{ question.question.title }}</li>
</ul>
{% endfor %}

Hope this sets you on the right path. 希望这能使您走上正确的道路。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM