When subclassing a model field, __init__'s arguments are not processed

I have a subclass of models.ForeignKey, the only purpose of which is to use a custom widget:

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

The problem is, when I try to use this field, any parameters to __init__ are ignored. For instance, if I try this model:

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

...despite the fact I specified verbose_name, the label on a generated form will be "Image" and trying to specify empty value will raise an error even though I use blank=True

Answers


Well, the problem is with your formfield method. If you look at the implementation used in the default ForeignKey for example, you'll see it calls super. I'd recommend something like this:

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

The problem is, form fields don't extract any information from model fields. Form fields can be used completely independently from models, they don't have to be necessarily backed by a model field. That means all settings, like whether the field is required or not, its label etc. have to be passed as parameters to their constructors. It is the responsibility of the model field to create an appropriate instance of a form field, all settings included. The default implementation of django.db.models.fields.Field.formfield takes care of that which is why you usually want to call the parent's method.

As for the blank issue, try also setting null=True, otherwise even though the form will accept a blank value, the database will reject it. Also, note that modifying the value of null after syncdb has been run requires a database migration.


Need Your Help

Automating unit tests (junit) for Eclipse Plugin development

java testing junit eclipse-pde eclipse-3.4

I am developing Eclipse plugins, and I need to be able to automate the building and execution of the test suite for each plugin. (Using Junit)

Detect another host with the same MAC address

networking ethernet

How can I detect if another host is using the same MAC address as the current host, e.g. because the other host is spoofing?