15š
Messing with the admin forms can be complicated but iāve commonly found that adding links, buttons, or extra info is easy and helpful. (Like a list of links to related objects witout making an inline, esp for things that are more viewed than edited).
From Django docs
Because of the modular design of the admin templates, it is usually
neither necessary nor advisable to
replace an entire template. It is
almost always better to override only
the section of the template which you
need to change.
This will add a list over the top of the form.
Place in templates/admin/[your_app]/[template_to_override]
:
{% extends "admin/change_form.html" %}
{% block form_top %}
{% for item in original.items %}
{{ item }}
{% endfor %}
{% endblock %}
11š
Django1.10:
1) Override admin/submit_line.html
:
{% load i18n admin_urls %}
<div class="submit-row">
{% if extra_buttons %}
{% for button in extra_buttons %}
{{ button }}
{% endfor %}
{% endif %}
{% if show_save %}<input type="submit" value="{% trans 'Save' %}" class="default" name="_save" />{% endif %}
{% if show_delete_link %}
{% url opts|admin_urlname:'delete' original.pk|admin_urlquote as delete_url %}
<p class="deletelink-box"><a href="{% add_preserved_filters delete_url %}" class="deletelink">{% trans "Delete" %}</a></p>
{% endif %}
{% if show_save_as_new %}<input type="submit" value="{% trans 'Save as new' %}" name="_saveasnew" />{% endif %}
{% if show_save_and_add_another %}<input type="submit" value="{% trans 'Save and add another' %}" name="_addanother" />{% endif %}
{% if show_save_and_continue %}<input type="submit" value="{% trans 'Save and continue editing' %}" name="_continue" />{% endif %}
</div>
This assumes, of course, that button
ās string representation is an appropriate browser input
or button
element, and is marked safe with django.utils.safestring.mark_safe
. Alternatively, you could use the safe
template filter or access the attributes of button
directly to construct the <input>
. In my opinion, itās better to isolate such things to the python level.
2) Override MyModelAdmin.change_view
:
def change_view(self, request, object_id, form_url='', extra_context=None):
extra_context = extra_context or self.extra_context()
return super(PollAdmin, self).change_view(
request, object_id, form_url, extra_context=extra_context,
)
This method enables you to add buttons to any ModelAdmin
easily. Alternatively to step (1), you could extend admin/change_form.html
and override block submit_row
. This would be slightly more verbose due to extra tags required in the template.
If you want the extra action available across all of your models (or a specific subset) then subclass ModelAdmin
with the desired functionality (an example would be to add archiving to your models. You could even add an override for deleteāand the other default buttonsāso that the mode is archived instead of deleted; this would require some template modifications)
- [Django]-How to server HTTP/2 Protocol with django
- [Django]-How do I install psycopg2 for Python 3.x?
- [Django]-Django edit user profile
2š
You can also use django-admin-tools, which allows you to easily customize the admin front page like a dashboard. Using a LinkList, you can point to some view method and check if the user is authenticated. It goes like thies:
# dashboard.py (read more about how to create one on django-admin-tools docs)
class CustomIndexDashboard(Dashboard):
"""
Custom index dashboard for captr.
"""
def init_with_context(self, context):
self.children.append(modules.LinkList(
_('Tasks'),
children=[
['Your task name', '/task']
]
))
# urls.py (mapping uri to your view function)
urlpatterns += patterns('yourapp.views',
(r'^task$', 'task'),
)
# views.py
def task(request):
if request.user.is_authenticated():
update_definitions_task.delay() # do your thing here. in my case I'm using django-celery for messaging
return redirect('/admin')
- [Django]-Django {% if forloop.first %} question
- [Django]-FileUploadParser doesn't get the file name
- [Django]-Suddenly when running tests I get "TypeError: 'NoneType' object is not iterable
1š
You might consider adding a custom admin action for this kind of object (similar to the built in ādeleteā), if appropriate. Some benefits include: āpure Djangoā, not having to mess with templates, and being able to act on multiple objects at once.
Djangoās admin lets you write and register āactionsā ā simple
functions that get called with a list of objects selected on the
change list page. If you look at any change list in the admin, youāll
see this feature in action; Django ships with a ādelete selected
objectsā action available to all models.
https://docs.djangoproject.com/en/dev/ref/contrib/admin/actions/
I got the idea from this article on how to add a custom action button, which is another answer all together. I was able to get by with the simpler built-in actions though.
https://medium.com/@hakibenita/how-to-add-custom-action-buttons-to-django-admin-8d266f5b0d41
- [Django]-What is the difference render() and redirect() in Django?
- [Django]-ForeignKey to abstract class (generic relations)
- [Django]-The QuerySet value for an exact lookup must be limited to one result using slicing. Filter error
-31š
Donāt mess with the admin pages.
-
Create an āapplicationā for this. Yes, your function is just a āroutineā. Thatās okay. Many smaller applications are a good thing.
-
This application has nothing new in
models.py
. No new model. Zero lines of code. -
This application has a useful URL in
urls.py
. Something that can be used to display this admin page. One URL. Not many lines of code (less than a dozen.) -
This application has one view function in
views.py
. On āGETā, this view function presents the form. On āPOSTā, this view function does the āroutineā. This is the āheartā of your application. The GET ā of course ā simply returns the template for display. The POST does the real work, and returns a final status or something.
This view function is protected with a decorator so that only an admin can execute it.
See http://docs.djangoproject.com/en/1.2/topics/auth/#django.contrib.auth.decorators.user_passes_test. You want to write a test for being an admin. lambda u: u.is_staff
is probably it.
-
This application has one template, presented by the GET and POST. That template has your form with your button. The one you canāt add to admin easily.
-
The
tests.py
is a test case with two users, one who is an admin and one who is not an admin.
No messing with built-in admin pages.
- [Django]-How to specify an IP address with Django test client?
- [Django]-Why is factory_boy superior to using the ORM directly in tests?
- [Django]-Django Multiple Authentication Backend for one project