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

如何在Django ModelForm中获取当前用户的分类选项?

问题解决:单词表单仅显示当前用户的分类选项

核心问题分析

原代码存在两个关键问题:

  • 使用ChoiceField处理外键关联,仅传递分类名称而非主键,导致表单提交后无法正确关联分类
  • 未在分类表单中自动关联当前用户,且视图缺少POST请求处理逻辑

以下是修正后的完整代码:

forms.py

from django import forms
from .models import ModelWords, ModelCatsWords
from django.conf import settings

class WordsForm(forms.ModelForm):
    # 改用ModelChoiceField适配外键,默认空查询集
    cat = forms.ModelChoiceField(
        queryset=ModelCatsWords.objects.none(),
        required=False,
        label="选择分类"
    )

    def __init__(self, *args, **kwargs):
        # 取出request对象
        self.request = kwargs.pop('request', None)
        super().__init__(*args, **kwargs)
        
        # 仅加载当前登录用户的分类
        if self.request and self.request.user.is_authenticated:
            self.fields['cat'].queryset = ModelCatsWords.objects.filter(author=self.request.user)
        
        # 设置输入框占位符
        for visible in self.visible_fields():
            visible.field.widget.attrs['placeholder'] = visible.field.label

    def save(self, commit=True):
        instance = super().save(commit=False)
        # 自动设置单词作者为当前用户
        instance.author = self.request.user
        if commit:
            instance.save()
        return instance

    class Meta:
        model = ModelWords
        fields = ['your_language_name', 'eng_name', 'cat']
        labels = {
            'your_language_name': '本国语言单词',
            'eng_name': '英文单词',
            'cat': '分类'
        }

class ModelCatsWordsForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        self.request = kwargs.pop('request', None)
        super().__init__(*args, **kwargs)
        self.fields['name'].widget.attrs['placeholder'] = '分类名称'

    def save(self, commit=True):
        instance = super().save(commit=False)
        # 自动设置分类作者为当前用户
        instance.author = self.request.user
        if commit:
            instance.save()
        return instance

    class Meta:
        model = ModelCatsWords
        fields = ['name']
        labels = {
            'name': '分类名称'
        }

views.py

from django.shortcuts import render, redirect
from django.views import View
from .forms import WordsForm, ModelCatsWordsForm

class WordsFormView(View):
    def get(self, request):
        # 初始化表单时传入request
        form_for_word = WordsForm(request=request)
        form_for_categorie = ModelCatsWordsForm(request=request)
        return render(request, 'app/appendwords.html', context={
            'form': form_for_word,
            'form_for_categorie': form_for_categorie
        })

    def post(self, request):
        # 处理单词提交(需在模板表单中添加name="word_submit"的按钮)
        if 'word_submit' in request.POST:
            form = WordsForm(request.POST, request=request)
            if form.is_valid():
                form.save()
                return redirect(request.path)  # 提交后刷新页面
        
        # 处理分类提交(需在模板表单中添加name="cat_submit"的按钮)
        elif 'cat_submit' in request.POST:
            cat_form = ModelCatsWordsForm(request.POST, request=request)
            if cat_form.is_valid():
                cat_form.save()
                return redirect(request.path)
        
        # 表单无效时返回原页面
        form_for_word = WordsForm(request=request)
        form_for_categorie = ModelCatsWordsForm(request=request)
        return render(request, 'app/appendwords.html', context={
            'form': form_for_word,
            'form_for_categorie': form_for_categorie
        })

关键优化点

  1. 外键字段适配:用ModelChoiceField替代ChoiceField,直接绑定分类模型,自动处理主键与显示名称的映射,避免提交错误
  2. 用户权限控制:仅加载当前登录用户创建的分类,确保数据隔离
  3. 自动关联作者:在表单save方法中自动设置author字段,无需视图层重复处理
  4. 完整请求处理:补充POST请求逻辑,支持单词和分类的提交保存

内容的提问来源于stack exchange,提问作者Bandos

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 11:36:00