Skip to main content

django-admin-easy

Collection of admin fields, decorators and mixin to help to create computed or custom fields more friendly and easy way

Join the chat at https://gitter.im/ebertti/django-admin-easy https://img.shields.io/badge/django-1.8%201.9%201.10%201.11%202.0%202.1%202.2%203.0-brightgreen.svg https://img.shields.io/pypi/v/django-admin-easy.svg?style=flat https://img.shields.io/pypi/pyversions/django-admin-easy.svg?maxAge=2592000 https://img.shields.io/pypi/format/django-admin-easy.svg?maxAge=2592000 https://img.shields.io/pypi/status/django-admin-easy.svg?maxAge=2592000 https://img.shields.io/travis/ebertti/django-admin-easy/master.svg?maxAge=2592000 https://img.shields.io/requires/github/ebertti/django-admin-easy.svg?maxAge=2592000 https://img.shields.io/coveralls/ebertti/django-admin-easy/master.svg?maxAge=2592000

Installation

  1. Requirements: Django > 1.8 and Python > 3.5

  2. pip install django-admin-easy==0.6

  • For Django < 1.8 or Python 2.x

    pip install django-admin-easy==0.4.1

How it Works

When you want to display a field on Django Admin, and this field doesn’t exist in your Model or you need to compute some information, like a Image or Link, you will need to create a method on your ModelAdminClass like this:

from django.contrib import admin

class YourAdmin(admin.ModelAdmin):
    fields = ('sum_method', 'some_img', 'is_true')

    def sum_method(self, obj):
        sum_result = obj.field1 + obj.field2 + obj.field3
        return '<b>%s</b>' % sum_result
    sum_method.short_description = 'Sum'
    sum_method.admin_order_field = 'field1'
    sum_method.allow_tags = True

    def some_img(self, obj):
        return '<img scr="%s">' % obj.image
    some_img.short_description = 'image'
    some_img.admin_order_field = 'id'
    some_img.allow_tags = True

    def is_true(self, obj):
        return obj.value > 0
    is_true.short_description = 'Positive'
    is_true.admin_order_field = 'value'
    is_true.boolean = True

It takes too much lines! =D

With django-admin-easy you can easily create this field with less lines:

from django.contrib import admin
import easy

class YourAdmin(admin.ModelAdmin):
    fields = ('sum_method', 'some_img', 'is_true')

    sum_method = easy.SimpleAdminField(lambda obj: '<b>%s</b>' % (obj.field1 + obj.field2 + obj.field3), 'Sum', 'field1', True)
    some_img = easy.ImageAdminField('image', 'id')
    is_true = easy.BooleanAdminField('Positive', 'value')

If you still prefer using a custom method, you can use our decorators, like this:

from django.contrib import admin
import easy

class YourAdmin(admin.ModelAdmin):
    fields = ('sum_method', 'some_img', 'is_true')

    @easy.smart(short_description='Sum', admin_order_field='field1', allow_tags=True )
    def sum_method(self, obj):
        sum_result = obj.field1 + obj.field2 + obj.field3
        return '<b>%s</b>' % sum_result

    @easy.short(desc='image', order='id', tags=True)
    def some_img(self, obj):
        return '<img scr="%s">' % obj.image

    @easy.short(desc='Positive', order='value', bool=True)
    def is_true(self, obj):
        return obj.value > 0

Another Decorators

In all of this extra decorators, you can use short or smart arguments to complement field information.

  • Allow HTML tags

@easy.with_tags()
def some_field_with_html(self, obj):
    return '<b>{}</b>'.format(obj.value)
# output some as: mark_safe("<b>something</b>")

if value is 5, will display:

5 and not <b>5</b> on admin page.

  • Cached field

If you, for some reason, need to cache a custom field on admin

@easy.cache(10)# in secondd, default is 60
def some_field_with_html(self, obj):
    return obj.related.some_hard_word()

If you change something on your model, or some related object, you can clean this cache using this easy way:

import easy
# wherever you want
easy.cache_clear(my_model_instance)

# or
class MyModel(models.Model):
    # ... fields

    def save(*args, **kwargs):
        easy.cache_clear(self)
        super(MyModel, self).save(*args, **kwargs)
  • Django template filter

Can be used with all template filters on your project.

# builtin template filter like {{ value|title }}
@easy.filter('title')
def some_field_with_html(self, obj):
    return 'ezequiel bertti'
# output: "Ezequiel Bertti"

# like {% load i10n %} and {{ value|localize }}
@easy.filter('localize', 'l10n')
def some_field_with_html(self, obj):
    return 10000
# output: "10.000"

# like {{ value|date:'y-m-d' }}
@easy.filter('date', 'default', 'y-m-d')
def some_field_with_html(self, obj):
    return datetime(2016, 06, 28)
# output: "16-06-28"
  • Django utils functions

Tested with:

@easy.utils('html.escape')
@easy.utils('html.conditional_escape')
@easy.utils('html.strip_tags')
@easy.utils('safestring.mark_safe')
@easy.utils('safestring.mark_for_escaping')
@easy.utils('text.slugify')
@easy.utils('translation.gettext')
@easy.utils('translation.ugettext')
@easy.utils('translation.gettext_lazy')
@easy.utils('translation.ugettext_lazy')
@easy.utils('translation.gettext_noop')
@easy.utils('translation.ugettext_noop')
def your_method(self, obj):
    return obj.value

More Examples

from django.contrib import admin
import easy

class YourAdmin(admin.ModelAdmin):
    list_fields = ('id', 'custom1', 'custom2', 'custom3' ... 'customN')

    actions = ('simples_action',)

    @easy.action('My Little Simple Magic Action')
    def simple_action(self, request, queryset):
        return queryset.update(magic=True)

    # actoin only for user that has change permission on this model
    @easy.action('Another Simple Magic Action', 'change')
    def simple_action(self, request, queryset):
        return queryset.update(magic=True)


    # render a value of field, method, property or your model or related model
    simple1 = easy.SimpleAdminField('model_field')
    simple2 = easy.SimpleAdminField('method_of_model')
    simple3 = easy.SimpleAdminField('related.attribute_or_method')
    simple4 = easy.SimpleAdminField('related_set.count', 'count')
    simple5 = easy.SimpleAdminField(lambda x: x.method(), 'show', 'order_by')

    # render boolean fields
    bool1 = easy.BooleanAdminField(lambda x: x.value > 10, 'high')

    # render with string format fields
    format1 = easy.FormatAdminField('{o.model_field} - {o.date_field:Y%-%m}', 'column name')

    # render foreignkey with link to change_form in admin
    fk1 = easy.ForeignKeyAdminField('related')

    # render foreignkey with link to change_form in admin and related_id content as text
    fk2 = easy.ForeignKeyAdminField('related', 'related_id')

    # render foreignkey_id, like raw_id_fields, with link to change_form in admin and related_id content as text
    # without extra queries or select_related to prevent extra n-1 queries
    raw1 = easy.RawIdAdminField('related')

    # render template
    template1 = easy.TemplateAdminField('test.html', 'shorty description', 'order_field')

    # render to change_list of another model with a filter on query
    link1 = easy.LinkChangeListAdminField('app_label', 'model_name', 'attribute_to_text',
                                          {'field_name':'dynamic_value_model'})

    link2 = easy.LinkChangeListAdminField('app_label', 'model_name', 'attribute_to_text',
                                          {'field_name':'dynamic_value_model'},
                                          {'another_field': 'static_value'})

    # display image of some model
    image1 = easy.ImageAdminField('image', {'image_attrs':'attr_value'})

    # use django template filter on a field
    filter1 = easy.FilterAdminField('model_field', 'upper')
    filter2 = easy.FilterAdminField('date_field', 'date', 'django', 'y-m-d')
    filter3 = easy.FilterAdminField('float_field', 'localize', 'l18n')

    @easy.smart(short_description='Field Description 12', admin_order_field='model_field')
    def custom12(self, obj):
        return obj.something_cool()

    @easy.short(desc='Field Description 1', order='model_field', tags=True)
    def decorator1(self, obj):
        return '<b>' + obj.model_field + '</b>'

    @easy.short(desc='Field Description 2', order='model_field', bool=True)
    def decorator2(self, obj):
        return obj.model_field > 10

If you want to use on admin form to show some information, don’t forget to add your custom field on readonly_fields attribute of your admin class

from django.contrib import admin
import easy

class YourAdmin(admin.ModelAdmin):
    fields = ('custom1', 'custom2', 'custom3' ... 'customN')
    readonly_fields = ('custom1', 'custom2', 'custom3' ... 'customN')

    custom1 = easy.ForeignKeyAdminField('related')
    # ...

Another way to use is directly on list_fields declaration:

from django.contrib import admin
import easy

class YourAdmin(admin.ModelAdmin):
    list_fields = (
        easy.TemplateAdminField('test.html', 'shorty description', 'order_field'),
        easy.ImageAdminField('image', {'image_attrs':'attr_value'}),
        # ...
    )

    # ...

Mixin

To help you to create a custom view on django admin, we create de MixinEasyView for your Admin Classes

from django.contrib import admin
import easy

class MyModelAdmin(easy.MixinEasyView, admin.ModelAdmin):
    # ...

    def easy_view_jump(self, request, pk=None):
        # do something here
        return HttpResponse('something')

To call this view, you can use this reverse:

from django.core.urlresolvers import reverse

# to do something with one object of a model
reverse('admin:myapp_mymodel_easy', args=(obj.pk, 'jump'))

# or to do something with a model
reverse('admin:myapp_mymodel_easy', args=('jump',))

Or one HTML template

#<!-- to do something with one object of a model -->
{% url 'admin:myapp_mymodel_easy' obj.pk 'jump' %}

#<!-- or to do something with a model -->
{% url 'admin:myapp_mymodel_easy' 'jump' %}

Utilities

  • Response for admin actions

    Return for the change list and show some message for the user keeping or not the filters.

from django.contrib import admin
from django.contrib import messages
import easy

class YourAdmin(admin.ModelAdmin):
    # ...
    actions = ('simples_action',)

    def simples_action(self, request, queryset):

        success = queryset.do_something()
        if success:
            return easy.action_response(request, 'Some success message for user', keep_querystring=False)
        else:
            return easy.action_response(request, 'Some error for user', messages.ERROR)

        # or just redirect to changelist with filters
        return easy.action_response()

So easy, no?

Screenshot

Using example of poll of django tutorial

https://raw.githubusercontent.com/ebertti/django-admin-easy/master/screenshot/more.png https://raw.githubusercontent.com/ebertti/django-admin-easy/master/screenshot/related.png

Please help us

This project is still under development. Feedback and suggestions are very welcome and I encourage you to use the Issues list on Github to provide that feedback.

https://img.shields.io/github/issues/ebertti/django-admin-easy.svg https://img.shields.io/waffle/label/ebertti/django-admin-easy/in%20progress.svg?maxAge=2592000 https://img.shields.io/github/forks/ebertti/django-admin-easy.svg https://img.shields.io/github/stars/ebertti/django-admin-easy.svg

Authors

The django-admin-easy was originally created by Ezequiel Bertti @ebertti October 2014.

Changelog

  • 0.6

    • Add RawIdAdminField

  • 0.5.1

    • Add permission on action decorator

  • 0.4.1

    • Django 2.0

  • 0.4

    • Django 1.11

    • Create module utils with action_response

  • 0.3.2

    • Add params_static to LinkChangeListAdminField

  • 0.3.1

    • Add FormatAdminField

  • 0.3

    • Add import from __future__ on all files

    • Django 1.10

    • More decorators

    • More admin fields

  • 0.2.2

    • Add MixinEasyView

  • 0.2.1

Metadata

Release files for django-admin-easy 0.6

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for django-admin-easy 0.6
File Size Uploaded
django-admin-easy-0.6.tar.gz 17.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for django-admin-easy 0.6
File Interpreter ABI Platform
django_admin_easy-0.6-py3-none-any.whl Python 3 none any Details

Total release size: 31.7 kB

Release files / django-admin-easy-0.6.tar.gz

Download URL django-admin-easy-0.6.tar.gz
Size 17.1 kB
Tags Source
SHA-256 checksum
How to use checksums
6d9734312bd2e173b1369c4948441576d9a671fb890bb23892f8f204d75a82b2
BLAKE2b-256 checksum
How to use checksums
3b8f0ffeb49e9b60491ad4a84e06eb82249baa5090ee90396917d3272fe0d1fd
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/1.11.0 pkginfo/1.4.2 requests/2.22.0 setuptools/40.2.0 requests-toolbelt/0.8.0 tqdm/4.26.0 CPython/3.6.3

Release files / django_admin_easy-0.6-py3-none-any.whl

Download URL django_admin_easy-0.6-py3-none-any.whl
Size 14.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
41186c209f9eb09ad0f1fec9332f2963d5441e15177763fe714632286e910528
BLAKE2b-256 checksum
How to use checksums
a9f113a4668922082f017983c939c4e6e1e86f77169686f0bb090d2ff2691d16
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/1.11.0 pkginfo/1.4.2 requests/2.22.0 setuptools/40.2.0 requests-toolbelt/0.8.0 tqdm/4.26.0 CPython/3.6.3

Release history Release notifications | RSS feed

0.8.0

2 release files

0.7.0

2 release files

0.6.1

2 release files

This release

0.6 This release

2 release files

0.5.1

2 release files

0.5

2 release files

0.4.1

2 release files

0.4

1 release file

0.3.2

1 release file

0.3.1

1 release file

0.3

1 release file

0.2.2.1

1 release file

0.2.2

1 release file

0.2.1

1 release file

0.2

1 release file

0.1.6

1 release file

0.1.5

1 release file

0.1.1

1 release file

0.1

1 release file

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page