Django admin tips and tricks
January 23, 2019 ·
15 mins read
1. Setup up Django project
2. Change the default admin address.
3. Change the default name of the admin web page
4. Handling History/ Model Logs in Django admin panel
5. Linking Foreign Key fields for navigating properly in Django admin
6. Counting the number of fields
7. Permissions
8. Custom ordering
9. Custom Searching
You can do everything that you can think of using the admin. Some companies start off just by creating their products using the default admin interface. It provides a very good level of users and permissions handling.
In this post, we are going to discuss some tips and tricks in which you can start using the Django admin in your production effectively.
Let’s set up a simple project in Django and try to look at some of the admin related stuff.
2. Change the default admin address.
3. Change the default name of the admin web page
4. Handling History/ Model Logs in Django admin panel
5. Linking Foreign Key fields for navigating properly in Django admin
6. Counting the number of fields
7. Permissions
8. Custom ordering
9. Custom Searching
Setup up Django project
While we set up the Django project you will know how easy it is to set up a production-based system using this Python framework. All you need is a working Python environment. For this sake of the tutorial, we are going to use Python 3+. I personally am using Python 3.7+. You can use virtual environments to use any of the new Python versions and keep using the old ones as well. Here is an old post on how to install a virtual environment on your Ubuntu machine. For Mac users, you can refer to any of the posts out there. Here is one of them. Once you install the virtual environment, you can apply the following command to create the virtual environment.Setting up the virtual environment
python3 -m venv venv
source venv/bin/activate
(venv) ➜ ~Documents/soshace
python -V
Python 3.7.4
deactivate
Starting the Django project
For the purpose of this tutorial, we will be creating a simple School management system with as simple as possible execution. The first step involved is to install Django in the virtual environment. Django default setup comes with the inbuilt SQLite database, so you don’t have to worry about that as well. That is enough for the purpose of the tutorial.pip install django
requirements.txt
file so that anyone can copy your code and setup without going much in the detail. There is a command to help you with that as well.
pip freeze > requirements.txt
pip install -r requirements.txt
django-admin startproject schoolproject
cd schoolproject
manage.py
file which will include all the runnable commands for Django. Run the following command to create the default tables in the database. Django sample project also creates the default migrations which will create all the required tables for you.
These migrations include one for the user table which we will use to log in to the admin system. Run the following command to create the tables
python manage.py migrate
python manage.py createsuperuser
python manage.py runserver
8000
. The default admin page can be found on the /admin
endpoint. Use the link http://127.0.0.1:8080/admin
to land on the admin page.
Use the same credentials to log yourself in that you just set up a few seconds ago.
In a Django project, everything is handled using apps. You can create a simple app using the following command.
python manage.py startapp schoolapp
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'schoolapp'
]
Change the default admin address.
It is important to change the default admin address so that attackers have a good hard time getting to your admin page. Change the following part of the code in theschoolproject/urls.py
file.
urlpatterns = [
re_path('yourcompany/admin/', admin.site.urls),
]
yourcompany/admin/
endpoint.
Change the default name of the admin web page
You can change the default heading and other things of the admin page to make it more personal for your brand. You can do it in any of your apps. Generally, people create a defaultbase
app and do all kinds of such stuff in there.
Write this code in schoolapp/admin.py
from django.contrib import admin
admin.site.site_header = 'MY SCHOOL APP'
admin.site.index_title = 'Your Company'
Handling History/ Model Logs in Django admin panel
Django history is a simple extendible app in Django which you can use to your advantage and create awesome things with it. For example storing more accurate data about the changes made in the Django admin panel. For this, we first have to create the sample models inschoolapp/models.py
.
from django.db import models
class School(models.Model):
school_name = models.CharField(max_length=30)
address = models.CharField(max_length=30)
principle_name = models.CharField(max_length=30)
def __str__(self):
return str(self.school_name)
makemigrations
python manage.py makemigrations
python manage.py migrate
from django.contrib import admin
from schoolapp.models import School
@admin.register(School)
class SchoolAdmin(admin.ModelAdmin):
pass
from django.contrib import admin
from django.contrib.admin.options import get_content_type_for_model
from django.contrib.admin.models import LogEntry, ADDITION
from schoolapp.models import School
@admin.register(School)
class SchoolAdmin(admin.ModelAdmin):
def save_model(self, request, obj, form, change):
super().save_model(request, obj, form, change)
if change:
change_message = '{} - {} - {}'.format(obj.school_name, obj.address, obj.principle_name)
LogEntry.objects.create(
user=request.user,
content_type=get_content_type_for_model(obj),
object_id=obj.id,
action_flag=2,
change_message=change_message,
object_repr=obj.__str__()[:200]
)
save_model
for that given admin model. This will save everything in the change_message
, which is visible in the action column.
Linking Foreign Key fields for navigating properly in Django admin
One of the worst thing of default version of Django admin is that, it doesn’t link with the Foreign Keys very well for the admin panel. If you are editing some object on the admin and you want to make change to the linked Foreign key field, you will have to go back to that particular model and make the change over there. There is no easy way to help you out that can directly link between these two related fields. To figure out the problem, let’s create a new model namedclass
.
class Class(models.Model):
class_name = models.CharField(max_length=30)
school = models.ForeignKey(
School,
on_delete=models.CASCADE
)
class_teacher = models.CharField(max_length=30)
section = models.CharField(max_length=30)
def __str__(self):
return str(self.class_name)
makemigrations
and migrate
command as specified above to create the tables.
The corresponding admin code will look something like this.
@admin.register(Class)
class ClassAdmin(admin.ModelAdmin):
pass
readonly
fields, otherwise, it will load all the fields into the memory and your servers will start going out of memory. Also, you don’t want someone to change the value of such important field randomly.
@admin.register(Class)
class ClassAdmin(admin.ModelAdmin):
readonly_fields = ('school',)
readonly
, you won’t be able to click on the corresponding field. To solve this you will have to make a few changes to the Admin init
function.
...
from django.db import models
from django.urls import reverse
from django.utils.safestring import mark_safe
...
def link_function(field_name):
def return_function(obj):
obj_attr = getattr(obj, field_name)
model = type(obj_attr)
print(field_name, obj_attr, model)
return mark_safe('<a href="{}">{}</a>'.format(reverse(
'admin:{}_{}_change'.format(
model._meta.app_label,
model.__name__.lower()
), args=(obj_attr.id,)), obj_attr))
return_function.short_description = field_name
return return_function
@admin.register(Class)
class ClassAdmin(admin.ModelAdmin):
readonly_fields = ('school',)
def __init__(self, model, admin_site):
super().__init__(model, admin_site)
# get all the fields
all_fields = model._meta.get_fields()
for field in all_fields:
# Check if the field is a Foreign Key
if not (isinstance(field, models.ForeignKey)):
continue
# We have to set a new field whose value is a function.
# The function should return inners of a HTML anchor tag.
setattr(self, 'main_new', link_function(field.name))
self.readonly_fields += ('main_new',)
Counting the number of fields
Permissions
Custom ordering
Custom Searching
Please share your Feedback:
Did you enjoy reading or think it can be improved? Don’t forget to leave your thoughts in the comments section below! If you liked this article, please share it with your friends, and read a few more!