子类化模型字段时,不处理__init __的参数

时间:2012-04-12 15:42:49

标签: django django-models

我有一个models.ForeignKey的子类,其唯一目的是使用自定义小部件:

from django.db import models
from .models import Images

class GAEImageField(models.ForeignKey):
    def __init__(self, **kwargs):
        super(GAEImageField, self).__init__(Images, **kwargs)

    def formfield(self, *args, **kwargs):
        field = forms.ModelChoiceField(self, widget=ImageUploadWidget, *args, **kwargs)
        field.queryset = Images.objects.all()
        return field

问题是,当我尝试使用此字段时,忽略__init__的所有参数。例如,如果我尝试这个模型:

class SomethingWithImage(models.Model):
    name = models.CharField('Awesome name', max_length=64)
    image = GAEImageField(verbose_name='Awesome image', blank=True)

...尽管事实上我指定了verbose_name,但生成的表单上的标签将是“Image”并且尝试指定空值会引发错误,即使我使用blank = True

1 个答案:

答案 0 :(得分:1)

嗯,问题出在你的formfield方法上。例如,如果您查看默认ForeignKey中使用的实现,您会看到它调用super。我推荐这样的东西:

def formfield(self, **kwargs):
    defaults = {
        'widget': ImageUploadWidget,
    }
    defaults.update(kwargs)
    return super(GAEImageField, self).formfield(**defaults)

问题是,表单字段不会从模型字段中提取任何信息。表单字段可以完全独立于模型使用,它们不必必须由模型字段支持。这意味着所有设置,例如字段是否需要,其标签等必须作为参数传递给它们的构造函数。模型字段负责创建表单字段的适当实例,包括所有设置。 django.db.models.fields.Field.formfield的默认实现负责处理您通常想要调用父方法的原因。

对于blank问题,请尝试设置null=True,否则即使表单接受空值,数据库也会拒绝它。另请注意,在null运行后修改syncdb的值需要进行数据库迁移。