8

我正在使用 Django 1.7,但我的固定装置有问题。

我希望 Django 使用默认值或使用该save()方法创建未指定的值。

这是我目前的对象:

# File: uuidable.py
import uuid
from django.db import models
from django.utils.translation import ugettext_lazy as _


class Uuidable(models.Model):
    uuid = models.CharField(_('uuid'), blank=True,
                            null=False, unique=True,
                            max_length=64, default=uuid.uuid4())  # Tried here

    class Meta:
        abstract = True

    def save(self, *args, **kwargs):
        if self.pk is None:
            self.uuid = uuid.uuid4()  # Tried here also
        super().save(*args, **kwargs)

# File: timestampable.py
from django.db import models
from django.utils.translation import ugettext_lazy as _


class Timestampable(models.Model):
    created_at = models.DateTimeField(_('created at'), auto_now_add=True)
    updated_at = models.DateTimeField(_('updated at'), auto_now=True)

    class Meta:
        abstract = True

# File: post.py
from project.lib.models.timestampable import Timestampable
from project.lib.models.uuidable import Uuidable

class Post(Timestampable, Uuidable):
    title = models.CharField(_('title'), max_length=250, blank=False)
    content = models.TextField(_('content'))

    def __str__(self):
        return self.title

如您所见,当我生成一个 newPost()created_atupdated_atuuid值会自动创建在save(). 但是当我使用固定装置时,我收到以下错误:

[...]initial_data.yaml': Could not load post.Post(pk=None): UNIQUE constraint failed: post_post.uuid

如果我在我的夹具文件中指定 a uuid,那么我会得到一个错误 oncreated_at然后 on updated_at。所以我必须指定每个字段的内容,即使我希望它是“自动的”。

文档(为什么在 django管理文档中?!),我知道该save()方法没有被调用,所以这就是为什么我放入该save()方法的所有内容都不起作用的原因。但是不应该启用/使用defaultor功能吗?auto_now*

处理夹具文件时,数据按原样保存到数据库中。不调用模型定义的 save() 方法,并且任何 pre_save 或 post_save 信号都将使用 raw=True 调用,因为实例仅包含模型本地的属性。例如,您可能希望禁用访问在夹具加载期间不存在的相关字段的处理程序,否则会引发异常

有没有办法“强制” Django 自动使用defaultauto_now*功能的固定装置?我manage.py syncdb用来创建所有表等。

我在谷歌和堆栈溢出上进行了搜索,但似乎找不到正确的搜索关键字。

UPDATE-1:以下google 小组讨论说对象以raw模式保存,这意味着auto_now*不考虑功能。我仍在寻找是否有办法将某些模型功能挂钩到 Django 固定装置保存。

4

3 回答 3

7

解决方案是使用 django 信号:

import uuid
from django.db import models
from django.utils.translation import ugettext_lazy as _
from django.db.models.signals import pre_save
from django.dispatch import receiver

class Uuidable(models.Model):
    uuid = models.CharField(_('uuid'), blank=True,
                            null=False, unique=True,
                            max_length=64, default=uuid.uuid4())

    class Meta:
        abstract = True

    @receiver(pre_save)
    def set_uuid_on_save(sender, instance, *args, **kwargs):
        if instance.pk is None:
            instance.uuid = uuid.uuid4()

这样,无论您以何种方式创建模型(通过外壳、固定装置等),都会填充模型/数据。

于 2014-09-08T13:36:07.833 回答
2

在 Django 1.7 中不推荐使用自动加载初始数据夹具。一种解决方案是通过您提到的信号。我更喜欢的另一个方法是创建一个 python 脚本,您可以在其中创建所有需要的数据,并在 shell 中执行它:

python manage.py shell < create_initial_data.py
于 2014-09-08T13:44:13.490 回答
1

我认为问题出在你把default=uuid.uuid4(). 括号太多了,因为它们暗示你将结果传递uuid.uuid4()给默认参数而不是函数本身,所以你应该把default=uuid.uuid4.

于 2019-09-20T14:49:26.363 回答