Django多表关联展示问题:如何显示活动参与者的报名详情
解决Django模板无法显示Submission模型details字段的问题
问题描述
搭建活动报名页面,参与者报名需填写个人详情,在Django视图中尝试展示参与者姓名、头衔及对应报名详情,但模板无法正确获取并显示Submission模型的details字段。
相关代码
模型代码
# Event 模型 class Event(models.Model): Event_ID = models.UUIDField(default=uuid.uuid4, unique=True, primary_key=True, editable=False) Event_Description = RichTextField(null=True, blank=True) Event_Category = models.ForeignKey(EventCategories, default=1, on_delete=models.CASCADE) Event_participants = models.ManyToManyField(User, blank=True, related_name='events') def __str__(self): return self.Event_Name # 注意:模型中未定义Event_Name字段,需补充或修改 # Submission 模型 class Submission(models.Model): participant = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, related_name="submissions") event = models.ForeignKey(Event, on_delete=models.SET_NULL, null=True) details = models.TextField(null=True, blank=False) id = models.UUIDField(default=uuid.uuid4, unique=True,primary_key=True, editable=False) def __str__(self): return str(self.event) + ' --- ' + str(self.participant)
视图代码
def single_event(request, pk): try: event = Event.objects.get(Event_ID=pk) submitted = Submission.objects.filter(event=event) submitted = list(submitted.values('participant','details')) except: return render(request, 'events/single-event.html', {"success":True,}, status=200) context = {'events':Event.objects.filter(Event_ID=pk), 'event':event, 'submitted':submitted} return render(request, 'events/single-event.html', context)
模板代码(single-event.html)
{% for event in events %} {% for user in event.Event_participants.all %} <tr> <td>{{ user.profile.title }}</td> <td>{{ user.first_name }} {{ user.last_name }}</td> <td>{{ ??????????? }}</td> <!-- 此处需显示Submission模型中的details字段 --> </tr> {% endfor %} {% endfor %}
解决方案
方案一:利用模型关联直接获取(推荐)
Submission模型已给participant字段设置related_name="submissions",可通过用户对象直接关联到对应报名记录,同时优化视图避免N+1查询。
修改视图
from django.db.models import Prefetch def single_event(request, pk): try: # 预加载参与者对应的当前活动报名记录 event = Event.objects.prefetch_related( Prefetch( 'Event_participants__submissions', queryset=Submission.objects.filter(event__Event_ID=pk), to_attr='event_submissions' ) ).get(Event_ID=pk) except Event.DoesNotExist: return render(request, 'events/single-event.html', {"success":True,}, status=200) # 无需传递events,直接使用单个event对象即可 context = {'event': event} return render(request, 'events/single-event.html', context)
修改模板
{% for user in event.Event_participants.all %} <tr> <td>{{ user.profile.title }}</td> <td>{{ user.first_name }} {{ user.last_name }}</td> <!-- 通过预加载的event_submissions获取详情,处理未提交情况 --> <td>{{ user.event_submissions.0.details|default:"未提交报名详情" }}</td> </tr> {% endfor %}
方案二:将报名记录转为字典映射
把Submission记录转为以用户ID为键的字典,模板中通过用户ID匹配详情。
修改视图
def single_event(request, pk): try: event = Event.objects.get(Event_ID=pk) submitted = Submission.objects.filter(event=event) # 构建用户ID到详情的映射字典 submission_map = {sub.participant_id: sub.details for sub in submitted} except Event.DoesNotExist: return render(request, 'events/single-event.html', {"success":True,}, status=200) context = {'event': event, 'submission_map': submission_map} return render(request, 'events/single-event.html', context)
修改模板
首先需要自定义模板过滤器,在app的templatetags目录下创建custom_filters.py:
from django import template register = template.Library() @register.filter def get_item(dictionary, key): return dictionary.get(key)
然后在模板中加载过滤器并使用:
{% load custom_filters %} {% for user in event.Event_participants.all %} <tr> <td>{{ user.profile.title }}</td> <td>{{ user.first_name }} {{ user.last_name }}</td> <td>{{ submission_map|get_item:user.id|default:"未提交报名详情" }}</td> </tr> {% endfor %}
注意事项
- 原Event模型的
__str__方法返回self.Event_Name,但模型中未定义该字段,需补充字段或修改返回值,避免报错。 - 方案一使用
Prefetch预加载数据,能有效减少数据库查询次数,提升页面性能,优先推荐。
内容的提问来源于stack exchange,提问作者1msmith1
相关产品推荐
相关产品推荐

