views:

257

answers:

1

I have strange problem with admin generic inline forms. I have two models, main Project and Video with ManyToMany relation trough VideoLink, becouse I need to be able linking different number of Video to Project and many project to Video:

class VideoLink(models.Model):
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    content_object = generic.GenericForeignKey('content_type', 'object_id')
    video = models.ForeignKey(Video)

class Project(models.Model):
    name = models.CharField(max_length=50)
    image_set = generic.GenericRelation('Image')

I didn't show Video model here, but it's not important for my question.

All what I need is to define new related object (VideoLink) linked to main object (Project) in 2 ways:

  • select Video inside admin inline forms (this works very well!)
  • define URL of new video in fake video_url field, create new Video object and create new VideoLink object between main (Project) and new (Video) objects.

For second case, I need to set middle functionality. It will process url of new video (like http://www.youtube.com/watch?v=WIXVzeB0DUo), create new Video object and syncronize it with youtube.com. I think the best way - put this into the AdminVideoLink's form clean method, am I right?

So, I wrote this code:

class VideoForm(forms.ModelForm):

    # new field for absolute video urls
    video_url = forms.CharField()

    def clean(self):
        cleaned_data = self.cleaned_data
        if not cleaned_data.get('id') and not cleaned_data.get('video') and cleaned_data.get('video_url'):
            ... some extra functionality:
            1) get id from video_url
            2) create new Video object with id
            3) define cleaned_data['video'] = <Video object>
             ....  

        return cleaned_data

class VideoInline(generic.GenericTabularInline):
    model = VideoLink
    form = VideoForm

class ProjectAdmin(admin.ModelAdmin):
    inlines = [VideoInline]

But every time after form saving, I see error inside admin inline form: near select with video objects - "field is required" (my translation). But I set this field inside my clean method. I check it: self.cleaned_data['video'] contains my new Video object just created and syncronized.

And another very strange problem: I can't find the parent instance (main Project object) inside this clean method. If I do same things with simple ManyToMany objects (without generic relation and generic.GenericTabularInline forms), I see both, video and project fields inside my inline form, but in generic case I haven't it.

I checked related post, but didn't find answer.

A: 

Solve this problem very simple, just add required=False to the inline form:

class VideoForm(forms.ModelForm):

    video_url = forms.CharField(required=False, widget=AdminVideoPreviewWidget())

    def __init__(self, *args, **kwargs):
        super(VideoForm, self).__init__(*args, **kwargs)
        self.fields['video'].required = False

    ....

With it I can fill video field manually after creating and syncronizing new Video object.

ramusus