A Django app for easily adding object tools in the Django admin

Overview

Django Object Actions

Build Status

If you've ever tried making admin object tools you may have thought, "why can't this be as easy as making Django Admin Actions?" Well now they can be.

Quick-Start Guide

Install Django Object Actions:

$ pip install django-object-actions

Add django_object_actions to your INSTALLED_APPS so Django can find our templates.

In your admin.py:

from django_object_actions import DjangoObjectActions

class ArticleAdmin(DjangoObjectActions, admin.ModelAdmin):
    def publish_this(self, request, obj):
        publish_obj(obj)
    publish_this.label = "Publish"  # optional
    publish_this.short_description = "Submit this article"  # optional

    change_actions = ('publish_this', )

Usage

Defining new &tool actions is just like defining regular admin actions. The major difference is the functions for django-object-actions will take an object instance instead of a queryset (see Re-using Admin Actions below).

Tool actions are exposed by putting them in a change_actions attribute in your admin.ModelAdmin. You can also add tool actions to the main changelist views too. There, you'll get a queryset like a regular admin action:

from django_object_actions import DjangoObjectActions

class MyModelAdmin(DjangoObjectActions, admin.ModelAdmin):
    def toolfunc(self, request, obj):
        pass
    toolfunc.label = "This will be the label of the button"  # optional
    toolfunc.short_description = "This will be the tooltip of the button"  # optional

    def make_published(modeladmin, request, queryset):
        queryset.update(status='p')

    change_actions = ('toolfunc', )
    changelist_actions = ('make_published', )

Just like admin actions, you can send a message with self.message_user. Normally, you would do something to the object and return to the same url, but if you return a HttpResponse, it will follow it (hey, just like admin actions!).

If your admin modifies get_urls, change_view, or changelist_view, you'll need to take extra care because django-object-actions uses them too.

Re-using Admin Actions

If you would like a preexisting admin action to also be an object action, add the takes_instance_or_queryset decorator to convert object instances into a queryset and pass querysets:

from django_object_actions import DjangoObjectActions, takes_instance_or_queryset

class RobotAdmin(DjangoObjectActions, admin.ModelAdmin):
    # ... snip ...

    @takes_instance_or_queryset
    def tighten_lug_nuts(self, request, queryset):
        queryset.update(lugnuts=F('lugnuts') - 1)

    change_actions = ['tighten_lug_nuts']
    actions = ['tighten_lug_nuts']

Customizing Object Actions

To give the action some a helpful title tooltip, add a short_description attribute, similar to how admin actions work:

def increment_vote(self, request, obj):
    obj.votes = obj.votes + 1
    obj.save()
increment_vote.short_description = "Increment the vote count by one"

By default, Django Object Actions will guess what to label the button based on the name of the function. You can override this with a label attribute:

def increment_vote(self, request, obj):
    obj.votes = obj.votes + 1
    obj.save()
increment_vote.label = "Vote++"

If you need even more control, you can add arbitrary attributes to the buttons by adding a Django widget style attrs attribute:

def increment_vote(self, request, obj):
    obj.votes = obj.votes + 1
    obj.save()
increment_vote.attrs = {
    'class': 'addlink',
}

Programmatically Disabling Actions

You can programmatically disable registered actions by defining your own custom get_change_actions() method. In this example, certain actions only apply to certain object states (e.g. You should not be able to close an company account if the account is already closed):

def get_change_actions(self, request, object_id, form_url):
    actions = super(PollAdmin, self).get_change_actions(request, object_id, form_url)
    actions = list(actions)
    if not request.user.is_superuser:
        return []

    obj = self.model.objects.get(pk=object_id)
    if obj.question.endswith('?'):
        actions.remove('question_mark')

    return actions

The same is true for changelist actions with get_changelist_actions.

Alternate Installation

You don't have to add this to INSTALLED_APPS, all you need to to do is copy the template django_object_actions/change_form.html some place Django's template loader will find it.

If you don't intend to use the template customizations at all, don't add django_object_actions to your INSTALLED_APPS at all and use BaseDjangoObjectActions instead of DjangoObjectActions.

More Examples

Making an action that links off-site:

def external_link(self, request, obj):
    from django.http import HttpResponseRedirect
    return HttpResponseRedirect(f'https://example.com/{obj.id}')

Limitations

  1. django-object-actions expects functions to be methods of the model admin. While Django gives you a lot more options for their admin actions.
  2. If you provide your own custom change_form.html, you'll also need to manually copy in the relevant bits of our change form .
  3. Security. This has been written with the assumption that everyone in the Django admin belongs there. Permissions should be enforced in your own actions irregardless of what this provides. Better default security is planned for the future.

Python and Django compatibility

See tox.ini for which Python and Django versions this supports.

Demo Admin & Docker images

You can try the demo admin against several versions of Django with these Docker images: https://hub.docker.com/r/crccheck/django-object-actions/tags

This runs the example Django project in ./example_project based on the "polls" tutorial. admin.py demos what you can do with this app.

Development

Getting started (with virtualenvwrapper):

# get a copy of the code
git clone [email protected]:crccheck/django-object-actions.git
cd django-object-actions
# set up your virtualenv (with virtualenvwrapper)
mkvirtualenv django-object-actions
# Install requirements
make install
# Hack your path so that we can reference packages starting from the root
add2virtualenv .
make test  # run test suite
make quickstart  # runs 'make resetdb' and some extra steps

This will install whatever the latest stable version of Django is. You can also install a specific version of Django and pip install -r requirements.txt.

Various helpers are available as make commands. Type make help and view the Makefile to see what other things you can do.

Similar Packages

If you want an actions menu for each row of your changelist, check out Django Admin Row Actions.

Django Object Actions is very similar to django-object-tools, but does not require messing with your urls.py, does not do anything special with permissions, and uses the same patterns as making admin actions.

Issues
  • Fix broken import on Django 1.6

    Fix broken import on Django 1.6

    django.conf.urls.defaults is no longer a valid module to import from in Django 1.6. Thanks in advance!

    opened by dlo 14
  • Fix changelist action link

    Fix changelist action link

    Currently change list action buttons have no href attribute set.

    Screen Shot 2019-05-17 at 12 07 48

    This little change fixes that.

    opened by mvbrn 10
  • 404 on Django 1.7.1

    404 on Django 1.7.1

    I have implemented the DOA library exactly as indicated in the example, and am getting a 404 with the following detail:

    (model) object with primary key u'0b637de8-ae8a-4fe6-8558-369e9eed2c34/tools/mark_reject' does not exist.

    As you can see, i'm using a UUID as my primary key. Might this be a factor? How would you recommend me debugging it? I've gone into the source code and I'm afraid I'm not skilled enough to follow what's happening...

    Thanks! Would love for this to work, it would be a lifesaver...

    bug 
    opened by dbinetti 9
  • Get rid of Django 2.0 DeprecationWarning

    Get rid of Django 2.0 DeprecationWarning

    Get rid of Django 2.0 DeprecationWarning and add 1.11 tox env. It also fixes faker dependency addressed in #76

    opened by coagulant 6
  • use django.urls.re_path when available

    use django.urls.re_path when available

    Use django.urls.re_path() when available, instead of the deprecated django.conf.urls.url().

    • re_path() is available since Django 2.0.
    • url() will be removed in Django 4.0.
    opened by mathiasertl 6
  • Button URL

    Button URL

    Hi guys, Quick question and sorry if it's a bit noobish...

    But how do I set the button's url?

    For example I want the button to be brought to admin/print/schedule.html

    Thanks, Ara

    opened by asivaneswaran 6
  • Allow POST requests

    Allow POST requests

    Need POST requests for using intermediate forms

    opened by jimfunk 5
  • update individual item for instance case

    update individual item for instance case

    The docs have

        @takes_instance_or_queryset
        def tighten_lug_nuts(self, request, queryset):
            queryset.update(lugnuts=F('lugnuts') - 1)
    

    but this updates all values since queryset seems to ignore the _result_cache (as proven by the test in my first commit). I'm not sure filter(pk=...) is the right way to implement this behavior, but @takes_instance_or_queryset seems dangerous as it is now.

    opened by AlexRiina 5
  • Documented example of a custom get_object_actions() method

    Documented example of a custom get_object_actions() method

    Includes note about that context['original'] is not available when creating / adding new objects (and object actions can't be applied in that case anyways).

    opened by maestrofjp 5
  • Use a template tag for tidier templates

    Use a template tag for tidier templates

    If a user wants to use multiple admin extensions that all want to override the change form template they will need to incorporate all the template changes in their own change_form.html

    It's therefore a good idea to keep each template customization as clean and simple as possible.

    Sorry - I haven't updated the docs to mention this enhancement. If it's a blocker let me know.

    opened by andybak 5
  • Ability to place action buttons within fields

    Ability to place action buttons within fields

    Hi, let me start by expressing my gratitude for your efforts into this nice project !

    When actions are related to a certain field, it makes sense to have their button rendered within that field. See for instance: Reset_password_example ("Mot de passe" meaning "Password" in French).

    I've managed to make the "Reset password" button appear in the password field by dedicating the help_text to it:

    class UserChangeForm(admin_forms.UserChangeForm):
        class Meta(admin_forms.UserChangeForm.Meta):
            model = User
    
        def __init__(self, **kwargs):
            super().__init__(**kwargs)
            password = self.fields.get('password')
            if password:
                password.help_text = \
                    """<ul class="object-tools"><li class="objectaction-item" data-tool-name="reset_password">
                    <a href="/admin/users/guest/3/actions/reset_password/" title="" class="">Reset password</a>
                    </li></ul>
                    """
    

    Very hacky, but it hopefully provides you with a useful starting point for implementing this feature, would you consider it.

    Cheers

    opened by ngirard 0
  • Add the ability to add a confirm dialog

    Add the ability to add a confirm dialog

    For some actions it would be nice to have a way of requiring the user answer a confirm dialog. Would a PR for something like this be accepted?

    opened by danlamanna 5
  • Add label/description decorator for

    Add label/description decorator for "cleaner" code

    Perhaps it's something that only irks me, but I find that this syntax quickly becomes readable after the function goes beyond a few lines:

       def publish_this(self, request, obj):
           publish_obj(obj)
       publish_this.label = "Publish"  # optional
       publish_this.short_description = "Submit this article"  # optional
    

    I'm currently using this little decorator to take care of the labels and description which works great:

    def create_action(label=None, short_description=None):
    
        def _create_action(function):
            if label:
                function.label = label
    
            if short_description:
                function.short_description = short_description
    
            return function
    
        return _create_action
    

    Usage is like this:

        @create_action('Publish', 'Submit this article')
        def publish_this(self, request, obj):
            publish_obj(obj)
    
    opened by WoLpH 8
  • separate url name for changelist_actions

    separate url name for changelist_actions

    For me "Dupe name is fine. https://code.djangoproject.com/ticket/14259" is not working. When I click on the button/link from change list in admin function does not run

    opened by predatell 4
  • typing support

    typing support

    Hi! How to make library friends with mypy? For example if I use code from readme

    class MyModelAdmin(DjangoObjectActions, admin.ModelAdmin):
        def toolfunc(self, request: HttpRequest, obj: MyModel) -> None:
            pass
        toolfunc.label = "This will be the label of the button"
        toolfunc.short_description = "This will be the tooltip of the button"
    

    I catch this error from mypy:

    "Callable[[MyModelAdmin, HttpRequest, MyModel], None]" has no attribute "label"
    "Callable[[MyModelAdmin, HttpRequest, MyModel], None]" has no attribute "short_description"
    

    For example for django admin short_description and etc. I use django-admin-display. How do you look at adding something like this to your project?

    opened by prokoptsev 3
  • Switch to Flit for packaging

    Switch to Flit for packaging

    https://flit.readthedocs.io/en/latest/index.html

    opened by crccheck 5
  • Incompatibility with django-reversion

    Incompatibility with django-reversion

    Whenever this ModelAdmin mixin is enabled (depending on the order) either the action buttons for this project or the buttons for django-reversion don't show up.

    I think creating a custom change_list.html template might do the trick, but is there an easy/official way to take care of this?

    opened by WoLpH 2
  • Filtered querset for changelist_actions

    Filtered querset for changelist_actions

    The queryset passed to changelist_actions includes all objects, even if the admin view has an active filter/search. Is there a way to receive a queryset identical to the filtered list that the admin view is currently using?

    help wanted to do 
    opened by NadavK 1
  • Research Django 2.1's change_form_object_tools.htm

    Research Django 2.1's change_form_object_tools.htm

    https://docs.djangoproject.com/en/dev/releases/2.1/

    The admin change list and change form object tools can now be overridden per app, per model, or globally with change_list_object_tools.html and change_form_object_tools.html templates.

    https://github.com/django/django/blob/master/django/contrib/admin/templates/admin/change_form_object_tools.html

    opened by crccheck 0
Releases(v3.0.1)
  • v3.0.1(Aug 9, 2020)

  • v3.0.0(Aug 8, 2020)

  • v2.0.0(Aug 8, 2020)

  • v1.1.2(Aug 8, 2020)

  • v1.1.0(May 4, 2019)

    Added

    • [4191afd691] - feat: Make default labels prettier (#93)

    Fixed

    • [fb908697a6] - Return to preserved filters on change_list after object action (#88)
    Source code(tar.gz)
    Source code(zip)
  • v1.0.0(Mar 9, 2018)

    I didn't get around to everything I listed in #44 as a release blocker for 1.0, but with Django going 2.0 and dropping backwards compatibility, I decided this library needs some more stability. In the future look for more removals as support for older versions of Django keep getting dropped.

    https://github.com/crccheck/django-object-actions/compare/v0.10.0...v1.0.0

    Added

    • [430be02e59] - Add support for Django 2.0 (#85)

    Changed

    • [a7b183f3c1] - Cleanup random Django version support docs (#86)
    • [81af3e7cd5] - Add a redirect example to the README (#82)
    Source code(tar.gz)
    Source code(zip)
  • v0.10.0(May 10, 2017)

  • v0.8.2(May 10, 2017)

  • v0.8.1(May 10, 2017)

  • v0.8.0(May 10, 2017)

    • Renames objectactions to change_actions
    • Removes get_object_actions (see below)
    • Adds changelist_actions for creating action tools in the change list view too
    • Adds get_change_actions and get_changelist_actions

    Breaking changes

    • Deleted get_object_actions(request, context, **kwargs). If you used this before, use get_change_actions(request, object_id, form_url) instead. To get at the original object, instead of context['original'], you can use self.model.get(pk=object_id), self.get_object(request, object_id), etc. This isn't as convenient as it used to be, but now it uses the officially documented way to add extra context to admin views. https://docs.djangoproject.com/en/dev/ref/contrib/admin/#other-methods

    • Renamed objectactions. In your admin, instead of defining your actions in the objectactions attribute, use change_actions.

    Source code(tar.gz)
    Source code(zip)
  • v0.9.0(Dec 4, 2016)

    • Add support for all primary key formats (#75)
    • Add support for Django 1.10 (#74)
    • Documentation tweaks (#71 #70)

    Removed

    • Remove support for Django 1.6 (#73)

    https://github.com/crccheck/django-object-actions/compare/v0.8.2...v0.9.0

    Source code(tar.gz)
    Source code(zip)
  • v0.7.0(Jan 14, 2016)

    Changes:

    • Fixed deprecation warning RemovedInDjango110Warning: django.conf.urls.patterns() is deprecated and will be removed in Django 1.10. #46
    • Fixed an issue in 0.6.0 where unnamed admin urls break things #49
    • you can now return HttpStreamingResponse from a tool now #50

    https://github.com/crccheck/django-object-actions/compare/v0.6.0...v0.7.0

    Source code(tar.gz)
    Source code(zip)
  • v0.6.0(Dec 7, 2015)

    Changes:

    • Add Django 1.8 and 1.9
    • Remove Django 1.4
    • Fixes #40 Where .update did not work for queryset-ish querysets at the cost of a db hit

    Known issues:

    • #45 Error urls don't have a name

    Full changes

    Source code(tar.gz)
    Source code(zip)
  • v0.5.1(Nov 28, 2014)

  • v0.5.0(Jul 1, 2014)

  • v0.3.0(Feb 13, 2014)

  • v0.4.0(Feb 13, 2014)

Owner
Chris Chang
Tell a little about yourself
Chris Chang
An improved django-admin-tools dashboard for Django projects

django-fluent-dashboard The fluent_dashboard module offers a custom admin dashboard, built on top of django-admin-tools (docs). The django-admin-tools

django-fluent 301 Nov 30, 2021
Jet Bridge (Universal) for Jet Admin – API-based Admin Panel Framework for your application

Jet Bridge for Jet Admin – Admin panel framework for your application Description About Jet Admin: https://about.jetadmin.io Live Demo: https://app.je

Jet Admin 1.1k Nov 25, 2021
aiohttp admin is generator for admin interface based on aiohttp

aiohttp admin is generator for admin interface based on aiohttp

Mykhailo Havelia 8 Nov 24, 2021
📱 An extension for Django admin that makes interface mobile-friendly. Merged into Django 2.0

Django Flat Responsive django-flat-responsive is included as part of Django from version 2.0! ?? Use this app if your project is powered by an older D

elky 249 Nov 12, 2021
Disable dark mode in Django admin user interface in Django 3.2.x.

Django Non Dark Admin Disable or enable dark mode user interface in Django admin panel (Django==3.2). Installation For install this app run in termina

Artem Galichkin 1 Oct 23, 2021
Modern responsive template for the Django admin interface with improved functionality. We are proud to announce completely new Jet. Please check out Live Demo

Django JET Modern template for Django admin interface with improved functionality Attention! NEW JET We are proud to announce completely new Jet. Plea

Geex Arts 3.2k Dec 1, 2021
Drop-in replacement of Django admin comes with lots of goodies, fully extensible with plugin support, pretty UI based on Twitter Bootstrap.

Xadmin Drop-in replacement of Django admin comes with lots of goodies, fully extensible with plugin support, pretty UI based on Twitter Bootstrap. Liv

差沙 4.6k Nov 24, 2021
A jazzy skin for the Django Admin-Interface (official repository).

Django Grappelli A jazzy skin for the Django admin interface. Grappelli is a grid-based alternative/extension to the Django administration interface.

Patrick Kranzlmueller 3.1k Nov 25, 2021
A Django admin theme using Twitter Bootstrap. It doesn't need any kind of modification on your side, just add it to the installed apps.

django-admin-bootstrapped A Django admin theme using Bootstrap. It doesn't need any kind of modification on your side, just add it to the installed ap

null 1.6k Nov 18, 2021
django's default admin interface made customizable. popup windows replaced by modals. :mage: :zap:

django-admin-interface django-admin-interface is a modern responsive flat admin interface customizable by the admin itself. Features Beautiful default

Fabio Caccamo 976 Dec 1, 2021
Extendable, adaptable rewrite of django.contrib.admin

django-admin2 One of the most useful parts of django.contrib.admin is the ability to configure various views that touch and alter data. django-admin2

Jazzband 1.1k Nov 26, 2021
Modern theme for Django admin interface

Django Suit Modern theme for Django admin interface. Django Suit is alternative theme/skin/extension for Django administration interface. Project home

Kaspars Sprogis 2.1k Nov 22, 2021
Django application and library for importing and exporting data with admin integration.

django-import-export django-import-export is a Django application and library for importing and exporting data with included admin integration. Featur

null 2.3k Dec 1, 2021
:honey_pot: A fake Django admin login screen page.

django-admin-honeypot django-admin-honeypot is a fake Django admin login screen to log and notify admins of attempted unauthorized access. This app wa

Derek Payton 819 Nov 25, 2021
"Log in as user" for the Django admin.

django-loginas About "Login as user" for the Django admin. loginas supports Python 3 only, as of version 0.4. If you're on 2, use 0.3.6. Installing dj

Stavros Korokithakis 290 Nov 22, 2021
Visually distinguish environments in Django Admin

django-admin-env-notice Visually distinguish environments in Django Admin. Based on great advice from post: 5 ways to make Django Admin safer by hakib

Yuri Shikanov 233 Nov 15, 2021
A new style for Django admin

Djamin Djamin a new and clean styles for Django admin based in Google projects styles. Quick start Install djamin: pip install -e git://github.com/her

Herson Leite 234 Oct 20, 2021
Responsive Theme for Django Admin With Sidebar Menu

Responsive Django Admin If you're looking for a version compatible with Django 1.8 just install 0.3.7.1. Features Responsive Sidebar Menu Easy install

Douglas Miranda 812 Nov 18, 2021
A Django admin theme using Twitter Bootstrap. It doesn't need any kind of modification on your side, just add it to the installed apps.

django-admin-bootstrapped A Django admin theme using Bootstrap. It doesn't need any kind of modification on your side, just add it to the installed ap

null 1.6k Nov 18, 2021