Django实现用户查看并更新个人追踪偏好表单问题求助
游戏追踪应用偏好表单问题解决
问题描述
我正在开发一款游戏追踪应用,想要实现一个表单,让用户查看并更新自己的追踪功能开关状态。按理说这操作不难,但我始终没法让表单加载用户现有的数据,也完成不了更新操作,求帮忙,提前谢过。
现有代码
views.py
@login_required(login_url='my-login') def track_pref(request): user = User.objects.get(username=request.user) print(user) if request.method == "POST": print('first if') form = UpdateTrackPrefForm(request.user, request.POST) if form.is_valid(): print('Form Valid') obj = form.save(commit=False) obj.user = user obj.save() return HttpResponseRedirect('/view-games') else: print("else statement") form = UpdateTrackPrefForm() context = {'form': form, 'user': user, } return render(request, 'gametracker_app/track-preference.html', context=context)
forms.py
class UpdateTrackPrefForm(forms.ModelForm): track_cedh = forms.BooleanField(required=False) track_wincon = forms.BooleanField(required=False) track_tournament = forms.BooleanField(required=False) track_medium = forms.BooleanField(required=False) class Meta: model = TrackPref fields = {'track_cedh', 'track_wincon', 'track_tournament', 'track_medium', }
models.py
class TrackPref(models.Model): track_cedh = models.BooleanField(default=True) track_wincon = models.BooleanField(default=True) track_tournament = models.BooleanField(default=True) track_medium = models.BooleanField(default=True) track_note = models.BooleanField(default=True) user = models.ForeignKey(User, max_length=100, on_delete=models.CASCADE, null=True) def __str__(self): return str(self.user)
HTML模板
<div class="container shadow-md p-5 form-layout"> <h1 class="">Update Tracking</h1> <form action="" method="POST" autocomplete="off"> {% csrf_token %} {{ user }} <br> {{ form.track_cedh|as_crispy_field }} {{ form.track_wincon|as_crispy_field }} {{ form.track_tournament|as_crispy_field }} {{ form.track_medium|as_crispy_field }} <br> <br> <input class="btn btn-primary" type="submit" name="" value="Submit"> <br> </form> </div>
尝试修改后的问题
我尝试在track_pref视图里传入user,结果报错:argument of type 'User' is not iterable,修改后的视图代码如下:
@login_required(login_url='my-login') def track_pref(request): user = User.objects.get(username=request.user) print(user) if request.method == "POST": print('first if') form = UpdateTrackPrefForm(request.user, request.POST) if form.is_valid(): print('Form Valid') obj = form.save(commit=False) obj.user = user obj.save() return HttpResponseRedirect('/view-games') else: print("else statement") form = UpdateTrackPrefForm(request.user)
问题分析与修复方案
核心问题
- 用户实例获取冗余且错误:
request.user已经是当前登录的User对象,无需再用User.objects.get(username=request.user)查询,而且username字段接收的是字符串,直接传User对象会导致查询错误。 - 表单初始化错误:ModelForm不需要接收User作为第一个参数,正确的做法是通过
instance参数传入用户对应的TrackPref实例,这样表单才能加载现有数据并更新指定对象。 - 表单字段冗余:手动定义的BooleanField和Model中重复,ModelForm会自动生成对应字段,可删除冗余定义。
修改后的代码
views.py
from django.contrib.auth.decorators import login_required from django.shortcuts import render, redirect from .models import TrackPref from .forms import UpdateTrackPrefForm @login_required(login_url='my-login') def track_pref(request): # 获取当前用户的TrackPref实例,不存在则自动创建 track_pref, _ = TrackPref.objects.get_or_create(user=request.user) if request.method == "POST": # 传入instance参数,确保更新现有对象而非创建新对象 form = UpdateTrackPrefForm(request.POST, instance=track_pref) if form.is_valid(): form.save() return redirect('view-games') # 建议使用URL反向解析,避免硬编码 else: # 传入instance让表单自动填充用户现有偏好数据 form = UpdateTrackPrefForm(instance=track_pref) context = {'form': form} return render(request, 'gametracker_app/track-preference.html', context)
forms.py
from django import forms from .models import TrackPref class UpdateTrackPrefForm(forms.ModelForm): class Meta: model = TrackPref fields = [ 'track_cedh', 'track_wincon', 'track_tournament', 'track_medium', ] # 可选:自定义字段标签,提升页面可读性 labels = { 'track_cedh': '追踪CEDH模式', 'track_wincon': '追踪获胜条件', 'track_tournament': '追踪锦标赛', 'track_medium': '追踪游戏媒介', }
models.py(优化)
外键字段不需要max_length=100(该参数仅适用于字符型字段),可删除:
from django.contrib.auth.models import User from django.db import models class TrackPref(models.Model): track_cedh = models.BooleanField(default=True) track_wincon = models.BooleanField(default=True) track_tournament = models.BooleanField(default=True) track_medium = models.BooleanField(default=True) track_note = models.BooleanField(default=True) user = models.ForeignKey(User, on_delete=models.CASCADE, null=True) def __str__(self): return str(self.user)
效果说明
修改完成后,表单会自动加载用户当前的追踪偏好设置,提交表单后系统会正确更新该用户的TrackPref数据,不会创建新的实例。另外,建议将HttpResponseRedirect('/view-games')替换为redirect('view-games'),需要提前在urls.py中给对应视图设置name='view-games'。
内容的提问来源于stack exchange,提问作者bld-sync
相关产品推荐
相关产品推荐

