GenericForeignKey and Admin in Django



假设我有一个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。

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

有什么建议吗?

要做到这一点,您需要做大量的工作。

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

要做到这一点,你必须:

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

听起来令人生畏?是的。

这里有一个更简单的方法:

只有一个"媒体"模型。你会在模型上有几个字段只对你的一种类型有效(尽管有很多交叉)。

将特定于单个媒体类型的任何字段命名为该媒体类型的前缀,即image_size', orvideo_title`。

在ModelAdmin中附加一个JavaScript处理程序,该处理程序根据媒体类型的下拉列表选择性地显示和隐藏字段。类似这样的东西:

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

django admin genericfk不适用于django 1.9。

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

https://github.com/lexich/genericrelationview

看起来保养得很好。不幸的是,它的JS代码不能很好地与Django CMS设置jQuery(noConflict jQuery)的方式配合使用,所以它似乎不是我的一个选择。但如果不在Django的CMS页面中使用,而是在常规的Django Admin中使用,它应该没问题。

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

django-admingenericfk正是您所需要的。

最新更新