【问题标题】:Cannot modify a model field on save()无法在 save() 上修改模型字段
【发布时间】:2017-12-10 12:55:53
【问题描述】:

我是 Django 的初学者,并且是第一次询问 :)

我正在关注一个关于为字符串生成 slug 的简单教程(假设是从标题生成的博客文章的 slug)。 也许我正在遵循一个过时的指南,也许我错过了一个基本的东西,我不知道。

  • Django 2.0

  • Python 3.6

我正在尝试做一个非常简单的任务,即 slugifying 一个简单的字符串,所以:

  1. 用户以简单的形式输入字符串
  2. 点击“保存”时,标题会通过 slugify 并创建 蛞蝓
  3. 保存。

models.py

from django.db import models    

class Testmodel(models.Model):
    title = models.CharField(max_length=220)
    slug = models.SlugField(unique=True, null=True)

    def __str__(self):
        return self.title

views.py

from django.views.generic.edit import CreateView    

class TestCreate(CreateView):
    model = Testmodel
    fields = '__all__'

forms.py

from django.forms import ModelForm
from .models import Testmodel

class TestCreateForm(ModelForm):
    class Meta:
        model = Testmodel
        fields = '__all__'

如果我手动输入 slug,直到这里一切正常。为了自动完成,我尝试过:

  1. 用我的 ModelForm 类覆盖 save() 方法。
  2. 在 CreateView 中覆盖 form_valid() 方法
  3. 覆盖模型本身内的save() 方法。
  4. 尝试将 pre_save 信号连接到模型。

在所有这 4 次尝试中,我得到了相同的结果:

  • 使用 slug 字段生成表单时,我什么也做不了,因为它是必需的。
  • 在生成没有 slug 字段的表单时,点击保存时没有任何反应。

我发现躲避这个问题的唯一方法是将 slug 字段也设置为blank = True。不过,我不确定它有多安全?

谢谢!

【问题讨论】:

    标签: python django django-models django-forms


    【解决方案1】:

    欢迎来到 StackOverflow。你写了一个奇妙的构造问题(干杯!)

    使用 slug 字段生成表单时,我什么也做不了,因为它是必需的。

    好的,首先我们排除 slug,因为我们希望它自动生成。

    你可以这样做

    class TestCreateForm(ModelForm):
        class Meta:
            model = Testmodel
            exclude = ['slug']
    

    现在您将获得一个没有 slug 字段的表单。

    当生成没有 slug 字段的表单时,当我点击保存时没有任何反应。

    现在我们覆盖模型本身的 save() 函数,因为 slug 是模型的一部分。

    def save(self, *args, **kwargs):
        self.slug = slugify(self.title)
        super().save(*args, **kwargs)
    

    但这会在每次保存模型时生成 slug。

    我们可以更进一步,确保仅在“创建”模型而不是每次“更新”时设置 slug

    def save(self, *args, **kwargs):
        if not self.id:
            self.slug = slugify(self.title)
        super().save(*args, **kwargs)
    

    【讨论】:

    • 嗯,首先这一切都很好。非常感谢!我只是想确定我明白了 - 你的建议是在 ModelForm 的 Meta 类上使用 exclude,但是当 CreateView 时我还必须说明这些字段(在 fields = ['title', 'additional_field'] 下 - 我找不到exclude 选项。这是否意味着如果我有一个包含 20 个字段的表单,我必须手动定义要“排除”哪些字段?
    • @Pumi 乐于助人!不客气 :) 如果你再次卡在某个地方,请告诉我^_^
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-08-01
    • 2020-07-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-26
    • 1970-01-01
    相关资源
    最近更新 更多