Reputation: 129
So, I want to add an extra button in my Fun
model's changelist_view which when pressed, performs a function and redirects me to a new page. I don't want to have this function for every app nor do I want for every model, only the Fun
model. And I will be using Django Admin to view this changelist, just a side note.
Can anyone suggest anything? Thanks.
Upvotes: 2
Views: 2980
Reputation: 1
You can add extra buttons to Change List page only for a particular admin(model) in a particular app, then redirect to Change List(Current) page.
For example, there is Person
model as shown below:
# "app1/models.py"
from django.db import models
class Person(models.Model):
first_name = models.CharField(max_length=20)
last_name = models.CharField(max_length=20)
And, there is Person
admin as shown below:
# "app1/admin.py"
from django.contrib import admin
from .models import Person
@admin.register(Person)
class PersonAdmin(admin.ModelAdmin):
list_display = ('first_name', 'last_name')
list_editable = ('first_name', 'last_name')
list_display_links = None
ordering = ('id',)
And, this below is Person Change List
page:
Now, copy pagination.html from django/contrib/admin/templates/admin/pagination.html
in your virtual environment to templates/admin/app1/person/
to add extra buttons to Change List page only for Person
admin in app1
as shown below. *To add extra buttons to Change List page for all admins in all apps, copy pagination.html
to templates/admin/
and for all admins in app1
, copy pagination.html
to templates/admin/app1/
and you can see the original pagination.html:
Django Project
|-core
| └-settings.py
|-app1
| |-models.py
| └-admin.py
|-app2
└-templates
└-admin
|-app1
| |-person
| | └-pagination.html # Here
| |-animal
| └-fruits
└-app2
Then, add <input ... value="{% translate 'Lowercase' %}">
and <input ... value="{% translate 'Uppercase' %}">
after <input ... value="{% translate 'Save' %}">
in pagination.html
as shown below:
# "templates/admin/app1/person/pagination.html"
# ...
{% if cl.formset and cl.result_count %}
<input
type="submit"
name="_save"
class="default"
value="{% translate 'Save' %}"
>
{# ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ Here ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ #}
<input
type="submit"
name="_lowercase"
style="background-color:yellowgreen;margin-right:5px;"
class="default"
value="{% translate 'Lowercase' %}"
>
<input
type="submit"
name="_uppercase"
style="background-color:yellowgreen;margin-right:5px;"
class="default"
value="{% translate 'Uppercase' %}"
>
{# ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ Here ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ #}
{% endif %}
</p>
Then, override changelist_view() in Person
admin as shown below. *You can see the original changelist_view():
# "app1/admin.py"
from django.contrib import admin
from .models import Person
from django.shortcuts import redirect
from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_protect
csrf_protect_m = method_decorator(csrf_protect)
@admin.register(Person)
class PersonAdmin(admin.ModelAdmin):
list_display = ('first_name', 'last_name')
list_editable = ('first_name', 'last_name')
list_display_links = None
ordering = ('id',)
@csrf_protect_m # Here
def changelist_view(self, request, extra_context=None):
to = '/' + '/'.join(request.build_absolute_uri().split('/')[3:])
if "_uppercase" in request.POST:
for obj in self.get_queryset(request):
obj.first_name = obj.first_name.upper()
obj.last_name = obj.last_name.upper()
obj.save()
return redirect(to)
if "_lowercase" in request.POST:
for obj in self.get_queryset(request):
obj.first_name = obj.first_name.lower()
obj.last_name = obj.last_name.lower()
obj.save()
return redirect(to)
return super().changelist_view(request, extra_context)
Then, you can make all first and last names uppercase or lowercase, then save by clicking on Uppercase
or Lowercase
buttons respectively then, redirect to Change List(Current) page as shown below:
Upvotes: 1
Reputation: 3920
Codes in fun/admins.py
from django.contrib import admin
from .models import Fun
@admin.register(Fun)
class FunAdmin(admin.ModelAdmin):
change_list_template = 'fun/admin_changelist.html'
and for the fun/admin_changelist.html template:
{% extends "admin/change_list.html" %}
{% load i18n admin_static admin_list %}
{% block result_list %}
<a href="{% url 'your-url-name here' %}">The custom button</a>
{% if action_form and actions_on_top and cl.full_result_count %}{% admin_actions %}{% endif %}
{% result_list cl %}
{% if action_form and actions_on_bottom and cl.full_result_count %}{% admin_actions %}{% endif %}
{% endblock %}
Overriding the admin templates is perfectly fine, but replacing them (completely) is not recommended; So we will just override the part that we need (here I assume your button will be located in the top of the list, so I only override the result_list
block)
Then you should have url with name="your-url-name here"
that is connected to a view.
Check the docs for more details
Upvotes: 2