【问题标题】:How correctly override ModelForm's save() method for a model with ManyToManyField如何正确覆盖具有 ManyToManyField 的模型的 ModelForm 的 save() 方法
【发布时间】:2010-10-19 19:30:11
【问题描述】:

考虑一下我已经定义了以下模型:

class Tag(models.Model):
  name = models.CharField(max_length=20)

class Entry(models.Model):
  title = models.CharField(max_length=100)
  date = models.DateField()
  tags = models.ManyToManyField(Tag)

以及以下模型形式:

class EntryForm(forms.ModelForm):
  tags =  CharField(max_length=100, label='Tags', required=False)
  class Meta:
    model = Entry

基本上我有一个带有标签的条目。标签不一定已经创建。我需要收到填写好的报名表并用标签保存。

如果条目中没有 ManyToMany 关系,我可以轻松做到这一点。但是有了它,我首先需要保存标签,然后将保存的标签添加到条目中,然后保存条目。这意味着我必须重写 EntryForm 的 save() 方法。

我已经看到this 的问题,但看起来不同。在我的情况下,我只需要保存标签,其余的应该可以使用 ModelForm 的默认 save()。

我提出了一个简化的例子。实际上,我在条目中有更多字段。 你对用 django 方式编写 EntryForm 的 save() 方法有什么建议?

【问题讨论】:

    标签: django django-models django-forms


    【解决方案1】:

    我认为你可以在保存标签后调用 super 。也许您需要在创建条目后附加到条目。

    def save(self, commit=True):
        # do custom stuff
        tags =[]
        for t in self.cleaned_data['tags'].split(','):
             tags.append(Tag.objects.get_or_create(name=t))
        # save entry
        e = super(EntryForm, self).save(commit=commit)
    
        for t in tags:
            e.tags.add(t)
    

    【讨论】:

    • 谢谢。但是一个问题。如何防止在 super(EntryForm, self).save() 中初始保存标签字段?
    • 好问题。您也可以手动保存条目。如果你得到实例,Entry.objects.get(id=instance.id) 然后更新字段,否则Entry.objects.create(title=...,date=...)。然后添加标签。工作量太小,使用表单的保存可能不值得。
    • 更正一点:get_or_create 返回一个元组 - (tag, created),所以我们只需要取第一部分
    【解决方案2】:

    这里最好和正确的选择是将 clean_tags 方法添加到表单中,而不是覆盖模型中的 save()。

    def clean_tags(self):
        tags = self.cleaned_data.get('tags', None)
    
        clean_tags = []
    
    
        tags = [tag.strip() for tag in tags.split(',') if tags]
    
        for tag in tags:
            t, created = Tag.objects.get_or_create(title=tag)
            t.count = F('count') + 1
            t.user.add(self.cleaned_data['user'])
            t.save()
            clean_tags.append(t)
    
        return clean_tags
    

    【讨论】:

    • 是的,这绝对是一个更好的解决方案。
    猜你喜欢
    • 2021-11-21
    • 2011-09-28
    • 1970-01-01
    • 2018-10-12
    • 2011-05-28
    • 2018-02-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多