字段验证后改变模型



我正在实现一个标签系统。目前,模型是这样的:

class Tag(models.Model):
label = models.CharField(max_length=MAX_TAG_LENGTH)

class TagManager(models.Model):
tags = models.ManyToManyField(Tag, related_name="referrers")
def associate_tag(self, tag_label: str):
. . .

我有一个自定义字段,它将逗号截断输入,因此用户可以将标签作为逗号分隔的列表输入:

class TagsField(forms.CharField):
def to_python(self, value):
if not value:
return []
return [tag.strip() for tag in value.split(',')]

最后,我有了使用它们的模型和表单:

class Thing(models.Model):
tags = models.OneToOneField(TagManager, on_delete=models.SET_NULL, null=True)
class ThingForm(forms.ModelForm):
tags = TagsField(widget=forms.TextInput(attrs={"placeholder": "Tags", "required": False}))
class Meta:
model = Thing
fields = ["tags"]
<标题>

我的问题是,如果我填充和验证表单:

form = ThingForm(data={"tags": ["One", "Two"]})
form.is_valid()

我得到错误:

{'tags': ["“["One", "Two"]” value must be an integer."]}

我猜这是因为它试图将字符串化列表放在OneToOneField中,这是行不通的。

我真正需要做的是在验证字段之后,我需要迭代to_python的结果,并在每个验证的标记字符串上调用thing_instance.tags.associate_tag

有"钩子"吗?方法能让我干净利落地完成这个吗?我已经通读了文档和Form源代码,但找不到任何明显的候选。

当我写这篇文章时,我意识到这是我需要的clean_*方法。我并不觉得这是"清洁"。

解决方案是增加一个clean_tags方法ThingForm类:

def clean_tags(self):
tags = self.cleaned_data["tags"]
for tag in tags:
self.instance.tags.associate_tag(tag)
return self.instance.tags.pk

它关联清洗过的标签,然后返回它们被添加到的TagManager的PK。

相关内容

  • 没有找到相关文章

最新更新