[Solved]-GenericForeignKey and Admin in Django

7đź‘Ť

You’d need to quite a bit of work to get this going.

  • You’re asking that the admin dynamically display a modelform, based on what model type you chose from a drop down.
  • Django’s admin does not do that (nor do any known extensions to it).

To make this work, you’ll have to:

  1. Write a custom JavaScript event handler which captures the onchange of the model select drop down.
  2. Then calls Django’s admin and requests the inline modelform for that model.
  3. Updates the current HTML page with that model form.
  4. 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.
  5. 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.

Sound daunting? It is.

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

Name any fields that are specific to a single Media type with a prefix for that mediatype, i.e. image_size', orvideo_title`.

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);
👤Jack Shedd

2đź‘Ť

django-admin-genericfk doesn’t work with Django 1.9.

Other than that I only found the following module:

https://github.com/lexich/genericrelationview

which looks well maintained. Unfortunately, its JS code does not work well with how Django CMS sets up jQuery (noConflict jQuery), so it seems that it is not an option for me. But it should be fine if not used in Django CMS pages but the regular Django Admin.

👤Risadinha

1đź‘Ť

I realize this is pretty old, but this is still the first result when searching for this.

django-admin-genericfk does exactly what you need.

👤WhyNotHugo

Leave a comment