Django表单问题:如何仅展示当前登录用户创建的Deck选项
解决GameForm仅显示当前用户Deck的问题
方法一:在视图中动态设置表单字段的QuerySet
直接在视图里修改表单deck字段的可选范围,确保只加载当前用户创建的Deck:
修改views.py:
from django.contrib.auth.decorators import login_required from django.shortcuts import render, HttpResponseRedirect @login_required # 确保只有登录用户能访问 def game_tracker(request): user_decks = Deck.objects.filter(user=request.user) if request.method == "POST": form = GameForm(request.POST) # 为POST请求也设置QuerySet,保证表单验证逻辑一致 form.fields['deck'].queryset = user_decks if form.is_valid(): form.save() # 保存表单数据 return HttpResponseRedirect('/track') else: form = GameForm() # 初始化表单时过滤Deck选项 form.fields['deck'].queryset = user_decks context = {'form': form} return render(request, 'gametracker_app/gametracker.html', context)
方法二:封装表单逻辑,支持传入用户参数
把过滤逻辑封装到表单类中,让表单更具复用性:
修改forms.py:
from django import forms from .models import Game, Deck class GameForm(forms.ModelForm): class Meta: model = Game exclude = {'date', 'time', } labels = { 'deck': 'What deck', 'num_players': '# of Players', 'start_pos': 'Starting position', 'mull': 'Starting hand', 'outcome': 'Outcome', 'wincon': 'Wincon', 'medium': 'Paper or Online', 'tournament': 'Tournament', } def __init__(self, *args, **kwargs): # 从参数中取出当前用户 self.user = kwargs.pop('user', None) super().__init__(*args, **kwargs) # 如果用户存在,过滤Deck选项 if self.user: self.fields['deck'].queryset = Deck.objects.filter(user=self.user)
修改views.py:
from django.contrib.auth.decorators import login_required from django.shortcuts import render, HttpResponseRedirect from .forms import GameForm @login_required def game_tracker(request): if request.method == "POST": # 实例化表单时传入当前用户 form = GameForm(request.POST, user=request.user) if form.is_valid(): form.save() return HttpResponseRedirect('/track') else: form = GameForm(user=request.user) context = {'form': form} return render(request, 'gametracker_app/gametracker.html', context)
注意事项
- 添加
@login_required装饰器可以避免未登录用户访问时出现request.user为空的错误; - 两种方法都能实现需求,方法二更符合Django的MVC设计思想,适合需要在多个视图复用该表单的场景。
内容的提问来源于stack exchange,提问作者bld-sync
相关产品推荐
相关产品推荐

