如何在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 })
关键优化点
- 外键字段适配:用
ModelChoiceField替代ChoiceField,直接绑定分类模型,自动处理主键与显示名称的映射,避免提交错误 - 用户权限控制:仅加载当前登录用户创建的分类,确保数据隔离
- 自动关联作者:在表单
save方法中自动设置author字段,无需视图层重复处理 - 完整请求处理:补充POST请求逻辑,支持单词和分类的提交保存
内容的提问来源于stack exchange,提问作者Bandos
相关产品推荐
相关产品推荐

