我正在使用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
如您所见,当我生成新的Post()
时,会在created_at
上自动创建updated_at
,uuid
和save()
值。但是当我使用灯具时,我收到以下错误:
[...]initial_data.yaml': Could not load post.Post(pk=None): UNIQUE constraint failed: post_post.uuid
如果我在fixture文件中指定了uuid
,那么我会在created_at
然后在updated_at
上收到错误消息。所以我必须指定每个字段的内容,即使我希望它是“自动的”。
来自documentation(为什么这是django admin docs?!),我知道save()
方法没有被调用,所以这就是为什么我放了进入save()
方法不起作用。但是,default
或auto_now*
功能不应该启用/使用吗?
处理夹具文件时,数据将按原样保存到数据库中。未调用模型定义的save()方法,并且将使用raw = True调用任何pre_save或post_save信号,因为实例仅包含模型本地的属性。例如,您可能希望禁用访问夹具加载期间不存在的相关字段的处理程序,否则会引发异常
有没有办法“强迫”Django自动使用default
或auto_now*
功能用于灯具?我正在使用manage.py syncdb
创建所有表格等。
我搜索了谷歌和堆栈溢出但似乎找不到合适的搜索关键字。
UPDATE-1 :以下google group discussion表示对象以raw
模式保存,这意味着不会考虑auto_now*
个功能。我仍然在寻找是否有办法将一些模型函数挂钩到Django夹具保存。
答案 0 :(得分:5)
解决方案是使用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()
这样,模型/数据就会以你创建模型的方式填充(通过shell,fixture,等等)。
答案 1 :(得分:1)
Automatically loading initial data fixtures is deprecated in Django 1.7。一种解决方案是通过您提到的信号。 我更喜欢的另一个是创建一个python脚本,在其中创建所有需要的数据,并在shell中执行它:
python manage.py shell < create_initial_data.py
答案 2 :(得分:0)
我认为问题出在您放default=uuid.uuid4()
时。括号太多了,因为它们暗示您将uuid.uuid4()
的结果传递给默认参数,而不是函数本身,因此应将default=uuid.uuid4
传递给