Package: django-object-actions
Django Object ActionsIf 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 GuideInstall Django Object Actions:$pipinstalldjango-object-actionsAdddjango_object_actionsto yourINSTALLED_APPSso Django can find
our templates.In your admin.py:fromdjango_object_actionsimportDjangoObjectActions,actionclassArticleAdmin(DjangoObjectActions,admin.ModelAdmin):@action(label="Publish",description="Submit this article")# optionaldefpublish_this(self,request,obj):publish_obj(obj)change_actions=('publish_this',)changelist_actions=('...',)UsageDefining new &tool actionsis just like defining regularadmin actions. The
major difference is the functions fordjango-object-actionswill take an
object instance instead of a queryset (seeRe-using Admin Actionsbelow).Tool actionsare exposed by putting them in achange_actionsattribute in
youradmin.ModelAdmin. You can also addtool actionsto the main changelist
views too. There, you'll get a queryset like a regularadmin action:fromdjango_object_actionsimportDjangoObjectActionsclassMyModelAdmin(DjangoObjectActions,admin.ModelAdmin):@action(label="This will be the label of the button",# optionaldescription="This will be the tooltip of the button"# optional)deftoolfunc(self,request,obj):passdefmake_published(modeladmin,request,queryset):queryset.update(status='p')change_actions=('toolfunc',)changelist_actions=('make_published',)Just like admin actions, you can send a message withself.message_user.
Normally, you would do something to the object and return to the same url, but
if you return aHttpResponse, it will follow it (hey, just likeadmin
actions!).If your admin modifiesget_urls,change_view, orchangelist_view,
you'll need to take extra care becausedjango-object-actionsuses them too.Re-using Admin ActionsIf you would like a preexisting admin action to also be anobject action, add
thetakes_instance_or_querysetdecorator to convert object instances into a
queryset and pass querysets:fromdjango_object_actionsimportDjangoObjectActions,takes_instance_or_querysetclassRobotAdmin(DjangoObjectActions,admin.ModelAdmin):# ... snip ...@takes_instance_or_querysetdeftighten_lug_nuts(self,request,queryset):queryset.update(lugnuts=F('lugnuts')-1)change_actions=['tighten_lug_nuts']actions=['tighten_lug_nuts']CustomizingObject ActionsTo give the action some a helpful title tooltip, you can use theactiondecorator
and set the description argument.@action(description="Increment the vote count by one")defincrement_vote(self,request,obj):obj.votes=obj.votes+1obj.save()Alternatively, you can also add ashort_descriptionattribute,
similar to how admin actions work:defincrement_vote(self,request,obj):obj.votes=obj.votes+1obj.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 alabelattribute:@action(label="Vote++")defincrement_vote(self,request,obj):obj.votes=obj.votes+1obj.save()ordefincrement_vote(self,request,obj):obj.votes=obj.votes+1obj.save()increment_vote.label="Vote++"If you need even more control, you can add arbitrary attributes to the buttons
by adding a Django widget styleattrsattribute:@action(attrs={'class':'addlink'})defincrement_vote(self,request,obj):obj.votes=obj.votes+1obj.save()ordefincrement_vote(self,request,obj):obj.votes=obj.votes+1obj.save()increment_vote.attrs={'class':'addlink',}Programmatically Disabling ActionsYou can programmatically disable registered actions by defining your own
customget_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):defget_change_actions(self,request,object_id,form_url):actions=super(PollAdmin,self).get_change_actions(request,object_id,form_url)actions=list(actions)ifnotrequest.user.is_superuser:return[]obj=self.model.objects.get(pk=object_id)ifobj.question.endswith('?'):actions.remove('question_mark')returnactionsThe same is true for changelist actions withget_changelist_actions.Alternate InstallationYou don't have to add this toINSTALLED_APPS, all you need to to do
is copy the templatedjango_object_actions/change_form.htmlsome place
Django's template loaderwill find
it.If you don't intend to use the template customizations at all, don't
adddjango_object_actionsto yourINSTALLED_APPSat all and useBaseDjangoObjectActionsinstead ofDjangoObjectActions.More ExamplesMaking an action that links off-site:defexternal_link(self,request,obj):fromdjango.httpimportHttpResponseRedirectreturnHttpResponseRedirect(f'https://example.com/{obj.id}')Limitationsdjango-object-actionsexpects functions to be methods of the model
admin. While Django gives you a lot more options for their admin
actions.If you provide your own customchange_form.html, you'll also need
to manually copy in the relevant bits ofour change form.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 compatibilitySeeci.ymlfor which Python and Django versions this supports.Demo Admin & Docker imagesYou can try the demo admin against several versions of Django with these Docker
images:https://hub.docker.com/r/crccheck/django-object-actions/tagsThis runs the example Django project in./example_projectbased on the "polls"
tutorial.admin.pydemos what you can do with this app.DevelopmentGetting started:# get a copy of the codegitclonegit@github.com:crccheck/django-object-actions.gitcddjango-object-actions# Install requirementsmakeinstall
maketest# run test suitemakequickstart# runs 'make resetdb' and some extra stepsVarious helpers are available as make commands. Typemake helpand
view theMakefileto see what other things you can do.Some commands assume you are in the virtualenv. If you see
"ModuleNotFoundError"s, try runningpoetry shellfirst.Similar PackagesIf you want an actions menu for each row of your changelist, check outDjango
Admin Row Actions.Django Object Actions is very similar todjango-object-tools, but does
not require messing with your urls.py, does not do anything special with
permissions, and uses the same patterns as makingadmin actions.