You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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)

问题分析与修复方案

核心问题

  1. 用户实例获取冗余且错误:request.user已经是当前登录的User对象,无需再用User.objects.get(username=request.user)查询,而且username字段接收的是字符串,直接传User对象会导致查询错误。
  2. 表单初始化错误:ModelForm不需要接收User作为第一个参数,正确的做法是通过instance参数传入用户对应的TrackPref实例,这样表单才能加载现有数据并更新指定对象。
  3. 表单字段冗余:手动定义的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 07:45:12