Django:实现ModelChoiceField支持选择或新增数据库值
解决Django ModelChoiceField支持新增条目的问题
问题根源是ModelChoiceField默认会验证输入值是否存在于指定的queryset中,因此输入数据库不存在的内容会触发验证错误。我们需要重写字段的验证逻辑,实现"存在则复用,不存在则创建"的效果。
1. 修改表单(Form)
重写clean_category方法,替代默认的验证逻辑,处理输入的分类值:
class RssForm(forms.Form): name = forms.CharField() feed = forms.URLField() category = forms.ModelChoiceField( queryset=FeedCategory.objects.all(), to_field_name='category', widget=forms.TextInput(), required=False # 对应模型中category字段的null=True设置 ) def clean_category(self): category_name = self.cleaned_data.get('category') if not category_name: return None # 去除首尾空白,避免创建无效分类 cleaned_name = category_name.strip() # 原子操作获取或创建分类,避免重复条目(利用category字段的unique约束) category_obj, _ = FeedCategory.objects.get_or_create(category=cleaned_name) return category_obj
2. 简化视图(Views)
经过表单处理后,cleaned_data['category']已经是有效的FeedCategory对象,直接创建RssFeed条目即可:
class RssCreateView(FormView): template_name = 'dashboard/rss_feed_form.html' form_class = RssForm success_url = '/dashboard/' def form_valid(self, form): RssFeed.objects.create(**form.cleaned_data) return super().form_valid(form)
额外说明
- 若不允许空分类,可将表单中
category字段的required设为True,并去掉clean_category中返回None的逻辑。 get_or_create是原子操作,可避免并发请求下创建重复分类的问题。
内容的提问来源于stack exchange,提问作者ntf
相关产品推荐
相关产品推荐

