Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

custom html field in the django admin changelist_view

I'd like to some little customisation with the django admin -- particularly the changelist_view

class FeatureAdmin(admin.ModelAdmin):
    list_display = (
        'content_object_change_url',
        'content_object',
        'content_type',
        'active',
        'ordering',
        'is_published',
    )

    list_editable = (
       'active',
       'ordering',
    )

    list_display_links = (
        'content_object_change_url',
    )

admin.site.register(get_model('features', 'feature'), FeatureAdmin)

The idea is that the 'content_object_change_url' could be a link to another object's change_view... a convenience for the admin user to quickly navigate directly to the item.

The other case I'd have for this kind of thing is adding links to external sources, or thumbnails of image fields.

I had thought I'd heard of a 'insert html' option -- but maybe I'm getting ahead of myself.

Thank you for your help!

like image 574
Daryl Avatar asked Sep 29 '10 09:09

Daryl


People also ask

What is Fieldsets in Django admin?

Set fieldsets to control the layout of admin “add” and “change” pages. fieldsets is a list of two-tuples, in which each two-tuple represents a <fieldset> on the admin form page. (A <fieldset> is a “section” of the form.)

How do I add an admin to text in Django?

help_text = "Please use the following format: <em>YYYY-MM-DD</em>." After running makemigrations and migrate on Django and rendering the above model, let us check if something has happened to our field in Django admin Interface. You can see extra text added at the bottom of the field.


3 Answers

You can provide a custom method on the FeatureAdmin class which returns HTML for content_object_change_url:

class FeatureAdmin(admin.ModelAdmin):

    [...]

    def content_object_change_url(self, obj):
        return '<a href="%s">Click to change</a>' % obj.get_absolute_url()
    content_object_change_url.allow_tags=True

See the documentation.

like image 136
Daniel Roseman Avatar answered Oct 18 '22 10:10

Daniel Roseman


Pay attention and use format_html (See docs here) as the mark_safe util has been deprecated since version 1.10. Moreover, support for the allow_tags attribute on ModelAdmin methods will be removed since version 1.11.

from django.utils.html import format_html
from django.contrib import admin

class FeatureAdmin(admin.ModelAdmin):
    list_display = (
        'change_url',
        [...]
    )
    def change_url(self, obj):
        return format_html('<a target="_blank" href="{}">Change</a>', obj.get_absolute_url())
    change_url.short_description='URL'
like image 4
Dos Avatar answered Oct 18 '22 12:10

Dos


It took me two hours to find out why Daniel Roseman's solution doesn't work for me. Even though he is right, there's one exception: when you want to make custom calculated fields (read only) in the Admin. This wont work. The very easy solution (but hard to find) is to return your string in a special constructor: SafeText(). Maybe this is linked with Django 2 or with readonly_fields (which behave differently from classical fields)

Here's a working sample that works but doesn't without SafeText():

from django.utils.safestring import SafeText

class ModelAdminWithData(admin.ModelAdmin):

    def decrypt_bin_as_json(self, obj):
        if not obj:
            return _("Mode insert, nothing to display")
        if not obj.data:
            return _("No data in the game yet")
        total = '<br/><pre>{}</pre>'.format(
            json.dumps(json.loads(obj.data),
                       indent=4).replace(' ', '&nbsp;'))
        return SafeText(total)  # !! working solution !! <------------------

    decrypt_bin_as_json.short_description = _("Data")
    decrypt_bin_as_json.allow_tags = True

    readonly_fields = ('decrypt_bin_as_json',)

    fieldsets = (
        (_('Data dump'), {
            'classes': ('collapse',),
            'fields': ('decrypt_bin_as_json',)
        }),
    )
like image 1
Olivier Pons Avatar answered Oct 18 '22 12:10

Olivier Pons