使用Django-select2动态创建标签报错:Field 'id'期望数字却获字符串
问题原因
使用ModelSelect2TagWidget时,默认不会自动创建新标签。当用户输入未存在的标签文本提交表单时,系统会错误地将该文本当作Tag模型的id(数字类型)去查询,因此抛出Field 'id' expected a number but got 'xxx'的异常。
解决方案
你需要在自定义的VersionTagWidget中重写create_option方法,实现输入不存在的标签时自动创建新实例的逻辑,同时指定创建标签时使用的字段。
步骤1:确保Tag模型的名称字段唯一(推荐)
为避免重复创建相同名称的标签,给Tag模型的nom字段添加唯一约束:
class Tag(models.Model): nom = models.CharField(max_length=100, unique=True) # 其他字段...
步骤2:修改自定义Widget
重写create_option方法,利用get_or_create实现自动创建标签:
class VersionTagWidget(s2forms.ModelSelect2TagWidget): search_fields = [ "nom__icontains", ] # 指定创建标签时使用的字段(对应Tag模型的nom字段) create_field = "nom" def create_option(self, data): # 根据用户输入的文本,获取或创建Tag实例,返回其主键 tag, _ = Tag.objects.get_or_create(nom=data["text"]) return tag.pk
步骤3:完善表单配置
确保表单中tags字段的查询集和Widget配置正确(如果之前未显式指定,可补充如下):
class VersionEditViewForm(forms.ModelForm): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # 你的其他初始化逻辑... tags = forms.ModelMultipleChoiceField( queryset=Tag.objects.all(), widget=VersionTagWidget, blank=True, required=False ) class Meta: model = Version fields = ["tags", ...] # 替换为你需要的其他字段
修改后,用户输入不存在的标签提交表单时,系统会自动创建对应的Tag实例并关联到Version的tags字段,不会再出现类型错误。
内容的提问来源于stack exchange,提问作者Lokkook
相关产品推荐
相关产品推荐

