0

我对管理通用内联表单有奇怪的问题。我有两个模型,主项目和通过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')

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

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

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

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

所以,我写了这段代码:

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]

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

还有一个很奇怪的问题:我在这个干净的方法中找不到父实例(主项目对象)。如果我使用简单的 ManyToMany 对象(没有通用关系和 generic.GenericTabularInline 表单)做同样的事情,我会在我的内联表单中看到 video 和 project 字段,但在一般情况下我没有。

我检查了相关帖子,但没有找到答案。

4

1 回答 1

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 对象后手动填充视频字段。

于 2009-06-03T14:56:32.923 回答