Django Model TextChoices字段如何同时支持下拉选择与自定义输入
实现步骤
1. 调整模型定义
首先要移除模型字段上的choices参数,避免模型层强制校验输入值必须属于预设枚举,预设枚举类可以保留供后续业务逻辑使用:
from django.db import models class Store(models.Model): class Size(models.TextChoices): MEDIUM = "M", "Medium" LARGE = "L", "Large" # 补充max_length限制存储长度,移除choices参数,保留默认值 shirt_size = models.CharField("Shirt Size", max_length=10, default=Size.MEDIUM)
2. 自定义Admin表单
在admin.py中自定义表单,使用HTML5原生datalist控件实现可选预设、支持手动输入的效果,不需要引入额外前端依赖:
from django.contrib import admin from django import forms from .models import Store class StoreAdminForm(forms.ModelForm): class Meta: model = Store fields = "__all__" # 给输入框绑定datalist widgets = { 'shirt_size': forms.TextInput(attrs={'list': 'size-datalist'}), } def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # 把预设尺码选项传入表单,供模板渲染使用 self.size_choices = Store.Size.choices # 可选:添加自定义校验逻辑,限制输入格式 def clean_shirt_size(self): size = self.cleaned_data.get('shirt_size', '').strip().upper() if len(size) > 10: raise forms.ValidationError("尺码长度不能超过10个字符") if not size.isalpha(): raise forms.ValidationError("尺码只能包含英文字母") return size @admin.register(Store) class StoreAdmin(admin.ModelAdmin): form = StoreAdminForm # 指定自定义的后台编辑模板 change_form_template = "admin/store_change_form.html"
3. 新增自定义Admin模板
在项目templates目录下创建admin/store_change_form.html文件,继承Django默认的后台编辑模板,注入预设尺码的datalist:
{% extends "admin/change_form.html" %} {% block content %} {{ block.super }} <!-- 预设尺码选项列表 --> <datalist id="size-datalist"> {% for value, label in adminform.form.size_choices %} <option value="{{ value }}">{{ label }}</option> {% endfor %} </datalist> {% endblock %}
注意:如果不需要额外格式校验,可以删掉表单里的
clean_shirt_size方法,输入的任意合法字符串都会正常存入数据库。
内容的提问来源于stack exchange,提问作者Jagadeesh
相关产品推荐
相关产品推荐

