Django中的GenericForeignKey和Admin

时间:2012-12-17 01:23:02

标签: django django-models django-admin

假设我有一个Post对象,可以包含图像,视频和其他媒体类型。我可以使用GenericForeignKey将它们链接在一起。类似的东西:

class Post(models.Model):
  title = models.CharField(...)
  text = models.TextField(...)

class AudioMedia(models.Model):
  ...

class VideoMedia(models.Model):
  ...

class ImageMedia(models.Model):
  ...

class MediaObject(models.Model):
  post = models.ForeignKey(Post)
  order = models.IntegerField()

  content_type_media = models.ForeignKey(
    ContentType, limit_choices_to={
      'model__in': (
        'audiomedia',
        'imagemedia',
        'videomedia')
  })

  object_id_media = models.PositiveIntegerField()
  obj = generic.GenericForeignKey('content_type_media', 'object_id_media')

现在我可以轻松创建管理界面,例如:

class MediaObjectAdminInLine(admin.StackedInline):
  model = MediaObject
  ct_field = "content_type_media"
  ct_fk_field = "object_id_media"
  extra = 0

class PostAdmin(admin.ModelAdmin):
  inlines = [MediaObjectAdminInLine]

现在问题:)在admin /中,我可以轻松创建一个新帖子。到帖子,我可以轻松添加更多MediaObject。在面板中,我有一个下拉菜单来选择类型(音频,视频,...),但我必须手动输入我想要与Post链接的对象的ID。 / p>

我尝试了各种扩展程序,包括grappelli。有些提供查找要链接的对象ID的功能。我希望能够在这里添加添加对象,例如,添加一个AudioMedia,一个VideoMedia,一个ImageMedia,具体取决于我从下拉列表中选择的内容。

有什么建议吗?

3 个答案:

答案 0 :(得分:5)

你需要做很多工作才能实现这一目标。

  • 您要求管理员根据您从下拉列表中选择的模型类型动态显示模型。
  • Django的管理员不这样做(也没有任何已知的扩展)。

要完成这项工作,您必须:

  1. 编写一个自定义JavaScript事件处理程序,用于捕获模型选择下拉列表的onchange。
  2. 然后调用Django的管理员并请求该模型的内联模型。
  3. 使用该模型表单更新当前的HTML页面。
  4. 然后你需要截取父模型的modelform的save()方法来确定它正在处理哪个子模型,并正确地将它保存到数据库中。
  5. 然后,您需要弄清楚如何让父模型的模型形式正确显示依赖于子模型的相应子模型的模型形式。
  6. 声音令人生畏?它是。

    这是一种更简单的方法:

    只需拥有一个“媒体”模型。您将在模型上有一些仅对您的某种类型有效的字段(尽管有很多交叉)。

    为具有该媒体类型前缀的单个媒体类型指定任何特定字段,即image_size', or video_title`。

    将JavaScript处理程序附加到ModelAdmin,该处理程序根据媒体类型的下拉列表选择性地显示和隐藏字段。像这样:

    class MediaAdmin(admin.ModelAdmin):
        class Meta:
            js = ["js/media-types.js",]
    
        // media-type.js
    (function($) {
        $(document).ready(function(){
            $('.module[id^=module] .row').hide();
            $('.module[id^=module] .row.module').show();
            $('.module[id^=module] .row.module select').each(function(){
                if ($(this).val() != '') 
                {
                    var group = $(this).parent().parent().parent().parent();
                    var field = $(this).parent().parent().parent();
                    var mtype = $(this).val().toLowerCase();
                    if (mtype != '') 
                    {               
                        $('.row', group).not(field).slideUp('fast');
                        $('.row[class*="'+mtype+'"]', group).slideDown('fast');
                        $('.row[class*="all"]', group).slideDown('fast');
                    }
                    else
                    {
                        $('.row', group).not(field).slideUp('fast');
                    }
                }
            });
            $('.module[id^=module] .row.module select').change(function(){
                var group = $(this).parent().parent().parent().parent();
                var field = $(this).parent().parent().parent();
                var mtype = $(this).val().toLowerCase();
                if (mtype != '') 
                {
                    $('.row', group).not(field).slideUp('fast');
                    $('.row[class*="'+mtype+'"]', group).slideDown('fast');
                    $('.row[class*="all"]', group).slideDown('fast');
                }
                else
                {
                    $('.row', group).not(field).slideUp('fast');
                }
            });
        });
    })(django.jQuery);
    

答案 1 :(得分:1)

django-admin-genericfk不能与Django 1.9合作。

除此之外,我只找到了以下模块:

https://github.com/lexich/genericrelationview

看起来维护得很好。不幸的是,它的JS代码不能很好地与Django CMS如何设置jQuery(noConflict jQuery),因此它似乎不适合我。但是如果不在Django CMS页面中使用它,那应该没问题,但是常规的Django Admin。

答案 2 :(得分:0)

我意识到这已经很久了,但这仍然是搜索时的第一个结果。

django-admin-genericfk完全符合您的需要。