Django admin: Show a field of a model depending on the value of another field

Viewed 578

I have a model in my Django project called Category.

models.py

class Category(models.Model):
    parent_category=models.ForeignKey('self', related_name='categories', on_delete=models.CASCADE, null=True, blank=True)
    name = models.CharField(max_length=200, db_index=True)
    slug = models.SlugField(max_length=200, unique= True)
    image = models.ImageField(upload_to='categories/', blank=True)

    class Meta:
        ordering = ('name',)
        verbose_name = 'category'
        verbose_name_plural = 'categories'
    
    def __str__(self):
        return self.name

Now in admin, I want to show the image field only if the parent field is not empty, on the fly. The parent field is a dropdown. I have a tried this, but it does not work:

admin.py

@admin.register(Category)
class CategoryAdmin(admin.ModelAdmin):
   def get_fields(self, request, obj=None):
        fields = super(CategoryAdmin, self).get_fields(request, obj)
        for field in fields:
            if field == 'parent_category' and 'parent_category'== None:
                fields.remove('image')
        return fields
   prepopulated_fields = {'slug' : ('name',)}

I also tried to use jQuery.

admin.py

class Media:
        js = (
            'js/myscript.js',      
        )

myscript.js

if (!$) {
    $ = django.jQuery;
}

(function($) { 
    $(document).ready(function() {
        if ($('#parent_category').val() != "") 
        {
          $('#image').hide()
        } 
        else {
          $('#image').show()
        }
    })
})(django.jQuery);

It shows the image field regardless of the value of parent_category. Any suggestions?

Thanks

1 Answers

Use a callable instead of a field. For example, I have a model which represents distance

@admin.register(Distance)
class DistanceAdmin(admin.ModelAdmin):
    """
    Distance model admin
    """
    list_display = (
        'id',
        'name',
        'get_distance_in_km',
        'get_distance_in_miles',
    )
    readonly_fields = (
        'get_distance_in_km',
        'get_distance_in_miles',
    )
    fields = (
        'name',
        'get_distance_in_km',
        'get_distance_in_miles',
    )

    def get_distance_in_km(self, obj):
        """
        Return the distance in kilometres, nicely formatted
        """
        return obj.formatted_distance_in_km
    get_distance_in_km.short_description = _('Distance in km')
    get_distance_in_km.admin_order_field = 'distance_in_km'

    def get_distance_in_miles(self, obj):
        """
        Return the distance in miles, nicely formatted
        """
        return obj.formatted_distance_in_miles
    get_distance_in_miles.short_description = _('Distance in miles')
    get_distance_in_miles.admin_order_field = 'distance_in_miles'

In these get_ methods of the admin class, you have access to the instance. So you might have a get_image method;

    def get_image(self, obj):
        if obj.parent_category:
            return obj.image
Related