当模型具有通用外键时,在clean()中设置Django模型实例的属性失败

时间:2012-07-29 22:22:08

标签: django django-models django-admin

这是一个说明问题的玩具示例:

# models.py
from django.contrib.contenttypes import generic
from django.contrib.contenttypes.models import ContentType
from django.db import models

class MyRelatedModel(models.Model):
    some_field = models.IntegerField()
    some_models = generic.GenericRelation('MyModel')

class MyModel(models.Model):
    data = models.TextField()
    more_data = models.FloatField(editable=False)
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    content_object = generic.GenericForeignKey()

    def clean(self):
        super(MyModel, self).clean()
        self.more_data = 5.5

    def save(self, *args, **options):
        print self.more_data    # prints 'None'
        super(MyModel, self).save(*args, **options)

以下是admin.py:

from django.contrib import admin
from django.contrib.contenttypes import generic
from test_model_save.models import MyModel, MyRelatedModel

class MyModelInline(generic.GenericTabularInline):
    model = MyModel

class MyRelatedModelAdmin(admin.ModelAdmin):
    inlines = [MyModelInline]

admin.site.register(MyModel)
admin.site.register(MyRelatedModel, MyRelatedModelAdmin)

当我尝试在Django管理员中创建一个对象时,我收到以下错误:

IntegrityError at /admin/test_model_save/myrelatedmodel/add/
test_model_save_mymodel.more_data may not be NULL

在将通用外键添加到MyModel之前,self.more_data = 5.5中的行clean()成功设置了属性值。但是,在上面的示例中,属性值在save()之前不会保留。我不知道可能导致这种行为的原因。我做错了吗?

(使用带有Sqlite后端的Django 1.4进行测试)

编辑:问题似乎与在管理中使用内联界面有关。分别创建两个模型的对象工作正常。尝试在同一管理页面上创建两种类型的对象(使用表格内联界面)会导致上面的IntegrityError。

Edit2:如果我将MyModel中的通用外键更改为普通models.ForeignKey(MyRelatedModel),则代码可以正常工作。所以问题与使用通用外键有关。在这个阶段,这看起来像是Django中的一个错误。

1 个答案:

答案 0 :(得分:0)

您是否尝试将null=True添加到more_data字段?我怀疑管理员首先保存父模型,因此在使用clean()方法之前验证整个表单。

祝你好运!