在管理通用内联表单中创建新的通用相关对象的问题

时间:2009-06-02 15:44:04

标签: django django-admin django-forms

我对admin通用内联表单有一些奇怪的问题。我有两个模型,主要项目和视频与 ManyToMany关系通过VideoLink,因为我需要能够将不同数量的视频链接到项目和许多项目到视频:

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')

我没有在这里展示视频模型,但这对我的问题并不重要。

我需要的是以两种方式定义链接​​到主对象(Project)的新相关对象(VideoLink):

  • 选择管理内联表单中的视频(这非常有用!)
  • 在假冒video_url字段中定义新视频的网址,创建新的视频对象,并在主(项目)和新(视频)对象之间创建新的VideoLink对象。

对于第二种情况,我需要设置中间功能。它将处理新视频的网址(如http://www.youtube.com/watch?v=WIXVzeB0DUo),创建新的视频对象并与youtube.com同步。我认为最好的方法 - 把它放到AdminVideoLink的表单 clean method 中,我是对的吗?

所以,我写了这段代码:

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]

但是每次表单保存后,我都会在管理内联表单中看到错误:在视频对象附近选择 - “字段是必需的”(我的翻译)。但我在我的干净方法中设置了这个字段。我检查一下:self.cleaned_data ['video']包含刚刚创建的新视频对象 和同步。

另一个非常奇怪的问题:我在 clean方法中找不到父实例(主Project对象)。如果我使用简单的ManyToMany对象(没有泛型关系和generic.GenericTabularInline表单)做同样的事情,我会在我的内联表单中看到视频和项目字段,但在通用情况下我没有它。

我检查了相关的post,但未找到答案。

1 个答案:

答案 0 :(得分:0)

解决这个问题非常简单,只需将 required = False 添加到内联表单中:

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

    ....

有了它,我可以在创建和同步新的Video对象后手动填充视频字段。