Django中的GenericForeignKey和Admin [英] GenericForeignKey and Admin in Django
问题描述
假设我有一个Post对象,其中可以包含图片,视频和其他媒体类型。我可以使用 GenericForeignKey
将它们链接在一起。像这样的东西:
Let's say I have a Post object that can contain Images, Videos, and other media types. I can use a GenericForeignKey
to link them together. Something like:
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')
现在我可以轻松创建管理界面,例如:
Now I can easily create an admin interface, like:
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。
Now the question :) In admin/, I can easily create a new Post. To the post, I can easily add more MediaObject. In the panel, I have a drop down menu to chose the type (audio, video, ...), but I have to manually enter the ID of the object I want to link with Post.
我尝试了各种扩展,包括grappelli。有些提供了查找对象ID以便在此处链接的功能。我希望能够在这里添加对象,例如,根据我从下拉菜单中选择的内容来添加AudioMedia,VideoMedia,ImageMedia。
I have tried various extensions, including grappelli. Some provide the ability to lookup the ID of objects to link here. I want the ability to add objects here, eg, add an AudioMedia, a VideoMedia, an ImageMedia, depending on what I pick from the dropdown.
有什么建议吗?
推荐答案
您需要做大量的工作才能做到这一点。
You'd need to quite a bit of work to get this going.
- 您要问管理员根据您从下拉菜单中选择的模型类型动态显示模型形式。
- Django的管理员不会执行此操作(也不执行任何已知的扩展)。
要实现此目的,您需要要:
To make this work, you'll have to:
- 编写一个自定义JavaScript事件处理程序,该处理程序捕获模型选择下拉列表的onchange。
- 然后调用Django的管理员并请求该模型的内联模型形式。
- 用该模型形式更新当前HTML页面。
- 然后您我需要拦截父模型的modelform的save()方法来确定它正在处理哪个子模型,以及正确地将其保存到数据库中。
- 然后,您需要弄清如何获取父模型的模型表,以正确显示取决于子模型的子模型的模型表。
- Write a custom JavaScript event handler which captures the onchange of the model select drop down.
- Then calls Django's admin and requests the inline modelform for that model.
- Updates the current HTML page with that model form.
- Then you'll need to intercept the parent model's modelform's save() method to figure out which child modelform it's dealing with, and correctly save it to the database.
- Then you'll need to sort out how to get the parent model's modelform to correctly display the appropriate child model's modelform dependent on the model of the child.
听起来令人生畏?
这是一种更简单的方法:
Here's an easier way:
只有一个媒体模型。在模型上,您将有几个仅对您的一种类型有效的字段(尽管有很多交叉)。
Just have a single "Media" model. You'll have a few fields on the model that are only valid for one of your types (though there's plenty of crossover).
命名任何特定于a的字段具有该媒体类型前缀的单个媒体类型,即 image_size'或
video_title`。
Name any fields that are specific to a single Media type with a prefix for that mediatype, i.e. image_size', or
video_title`.
附加JavaScript处理程序到您的ModelAdmin,后者根据媒体类型的下拉菜单有选择地显示和隐藏字段。像这样的东西:
Attach a JavaScript handler to your ModelAdmin which selectively shows and hides fields based on a dropdown for the media type. Something like this:
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中的GenericForeignKey和Admin的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!