Django:可选外键条目的反向查找并包含在数据集中

huangapple go评论75阅读模式
英文:

Django: Reverse lookup of optional foreignkey-entry and inclusion in dataset

问题

我想创建一个数据库条目列表,以及另一个表中的相关条目(但不一定存在)。

具体情境是事件列表,用户应该能够看到自己是否已经表明参与(因此在数据库中有一个应该显示的条目)或者没有(这将给他提供一个参与表单的链接)。

我的模型(最小化):

class Event(models.Model):
    title = models.CharField(max_length=200)
    # ...

class Event_Participation(models.Model):
    EVENT_PARTICIPATION_CHOICES = [
        ("Y", "Yes"),
        ("N", "No"),
         # 几个其他选项
    ]
    event = models.ForeignKey(Event, on_delete=models.CASCADE)
    participation = models.CharField(max_length=1, choices=EVENT_PARTICIPATION_CHOICES)
    user = models.CharField(max_length=10)  # 原本是另一个外键

理想情况下,我正在寻找一个表达式,类似于 Event.appendIfExists(Event_Participation)...

对于模板渲染,我能够查询数据,但这似乎不够优雅,我不知道如何在模板内部合并信息:

def event_list(request):
    e_all = Event.objects.all()  # 通常会进行筛选
    part_list = {}
    for e in e_all:
        if e.event_participation_set.filter(user=request.user.id).exists():
            p = e.event_participation_set.get(user=request.user.id).participation
        else:
            p = "X"
        part_list[e.id] = p
    context = {"part_list": part_list, "full_event_list": e_all}
    return render(request, "event_list.html", context)

在模板中的基于索引的变量对于 part_list 不起作用,我也不能扩展查询以使我只使用一个字典,就像这样:

{% for event in full_event_list %}
    <li> {{ event.title }}
       {# Participation: {% if event.participation %} {{ event.participation }} {% else %} LINK {%endif%}
    </li>
{% endfor %}

由于这似乎是一个非常常见的应用程序,我可能错过了一些非常明显的东西...

英文:

I would like to compose list of database entries, and corresponding (but not necessarily existing) related entries in another table.

The concrete context is a list of events, in which the user should be able to see, whether he already stated his participation (thus has an entry in the database which should be displayed) or not (which would give him a link to a participation form)

My models (minimal):

class Event(models.Model):
    title = models.CharField(max_length = 200)
    #...

class Event_Participation(models.Model):
    EVENT_PARTICIPATION_CHOICES = [
        (&quot;Y&quot;, &quot;Yes&quot;),
        (&quot;N&quot;, &quot;No&quot;),
         # few other options
    ]
    event = models.ForeignKey(Event, on_delete=models.CASCADE)
    participation = models.CharField(max_length=1, choices= EVENT_PARTICIPATION_CHOICES)
    user = models.CharField(max_length=10) #originally another foreign key

Ideally, I'm searching for one expression like Event.appendIfExists(Event_Participation)...

For template rendering, I was able to query the data, but this doesn't seem elegant and I don't know, how to merge the information inside the template:

def event_list(request):
    e_all = Event.objects.all() #normally filtered
    part_list = {}
    for e in e_all:
        if e.event_participation_set.get(user_id = request.user.id) :
            p = e.event_participation_set.get(user_id = request.user.id).participation
        else:
            p = &quot;X&quot;
        part_list[e.id]= p
        context = {&quot;part_list&quot;:part_list,&quot;full_event_list&quot;:e_all}
        return render(request, &quot;event_list.html&quot;, context)

An index-based variable in the template did not work for part_list, and I was not able to extend the queries in a way, which allowed me to use only one dict like this:

{% for event in full_event_list %}
        &lt;li&gt; {{ event.title }}
           {# Participation: {% if event.participation %} {{ event.participation }} {% else %} LINK {%endif%}
        &lt;/li&gt;
    {% endfor %}

Since this seems like a very common application, I am probably missing something very obvious...

答案1

得分: 0

We could use select_related or prefetch_related methods to perform database joins and reduce the number of queries.

We want Event objects along with their related Event_Participation objects for the current user.

from django.db.models import Prefetch

def event_list(request):
    participations = Event_Participation.objects.filter(user_id=request.user.id)
    events = Event.objects.all().prefetch_related(
        Prefetch('event_participation_set', queryset=participations, to_attr='user_participations')
    )

    return render(request, "event_list.html", {'events': events})

then in our template we can access the related Event_Participation objects for each event

{% for event in events %}
    <li>
        {{ event.title }}
        {% for participation in event.user_participations %}
            Participation: {{ participation.participation }}
        {% empty %}
            LINK
        {% endfor %}
    </li>
{% endfor %}
英文:

We could use select_related or prefetch_related methods to perform database joins and reduce the number of queries.

We want Event objects along with their related Event_Participation objects for the current user.

from django.db.models import Prefetch

def event_list(request):
    participations = Event_Participation.objects.filter(user_id=request.user.id)
    events = Event.objects.all().prefetch_related(
        Prefetch(&#39;event_participation_set&#39;, queryset=participations, to_attr=&#39;user_participations&#39;)
    )

    return render(request, &quot;event_list.html&quot;, {&#39;events&#39;: events})

then in our template we can access the related Event_Participation objects for each event

{% for event in events %}
    &lt;li&gt;
        {{ event.title }}
        {% for participation in event.user_participations %}
            Participation: {{ participation.participation }}
        {% empty %}
            LINK
        {% endfor %}
    &lt;/li&gt;
{% endfor %}

huangapple
  • 本文由 发表于 2023年6月15日 06:20:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/76477930.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定