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

如何让Django下拉表单仅展示当前用户所属条目而非全部用户的条目?

解决方案

核心原因

Django ModelForm的外键字段默认会加载对应模型的全量数据作为下拉选项,你没有手动修改该字段的查询集,所以所有用户的Workout都会展示在下拉菜单中。

1. 修改 forms.py 代码

给RoutineForm增加初始化方法,接收当前登录用户参数,过滤workout字段的可选范围:

class RoutineForm(forms.ModelForm):
    """creates a form for a routine"""
    class Meta:
        model = Routine
        fields = ['workout']
        labels = {'workout': 'Workout'}
    
    def __init__(self, *args, **kwargs):
        # 取出传入的当前用户参数
        user = kwargs.pop('user', None)
        super().__init__(*args, **kwargs)
        if user:
            # 仅保留当前用户创建的Workout作为可选选项
            self.fields['workout'].queryset = Workout.objects.filter(owner=user).order_by('text')

2. 修改 views.py 代码

实例化表单时传入当前登录用户,同时补全Routine实例的所有者绑定逻辑:

from django.shortcuts import render, redirect
from django.http import HttpResponseRedirect, Http404
from django.urls import reverse
from django.contrib.auth.decorators import login_required

@login_required
def routine(request):
    """display a dropdown of all workouts for a user"""
    if request.method != 'POST':
        # GET请求实例化表单时传入当前用户
        form = RoutineForm(user=request.user)
    else:
        # POST请求实例化表单也需要传入用户,保证校验逻辑正常
        form = RoutineForm(data=request.POST, user=request.user)
        if form.is_valid():
            new_routine = form.save(commit=False)
            # 给新生成的Routine绑定当前用户为所有者
            new_routine.owner = request.user
            new_routine.save()
            return redirect('index')
    # 原代码中workouts变量未定义,不需要的话可以直接删除
    context = {'form':form}
    return render(request, 'routine_workouts_app/routine.html', context)

额外说明

上述修改同时自带安全校验:即使用户恶意修改前端提交不属于自己的Workout ID,表单在校验时会匹配你设置的过滤后的查询集,不符合的ID会直接校验失败,不会产生越权数据。

内容的提问来源于stack exchange,提问作者Kyle F.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 14:12:00