Revisiting cadmin App

In this lesson, we will be building remaining pages of our cadmin app. Currently, our cadmin app has following pages:

  • Login page (http://127.0.0.1:8000/cadmin/login/)
  • Logout page (http://127.0.0.1:8000/cadmin/logout/)
  • Password change page (http://127.0.0.1:8000/cadmin/password-change/)
  • Password change done page (http://127.0.0.1:8000/cadmin/password-change-done/)
  • User registration page (http://127.0.0.1:8000/cadmin/register/)
  • Activate account page (http://127.0.0.1:8000/cadmin/activate/account/)
  • Post add/update page (http://127.0.0.1:8000/cadmin/post/add/ and http://127.0.0.1:8000/cadmin/post/update/<post_id>/)

In the upcoming section, we are creating the following pages:

  • Post list page – to display a paginated list of posts.
  • Tag list page – to display a paginated list of tags.
  • Tag add page.
  • Tag update page.
  • Tag delete page.
  • Category list page – to display a paginated list of categories.
  • Category add page.
  • Category update page.
  • Category delete page.
  • Account Info page – to display the details of logged in user.

In addition to that, we will also modify Post add and update page.

Let’s start by modifying Post add page.

Modifying Post Add Page

As the situation stands everytime we add or update a post we are presented with an author dropdown list, which is unnecessary. Instead of showing an author dropdown list, it would be much better if we automatically associate the post with the logged in author and only show author dropdown list to site superuser’s ( i.e users whose is_superuser attribute is True ).

Further, It will not be mandatory for the superuser to select the author while adding a post. Because we will automatically assign a special account named **staff** to the post in case the author is not selected. Okay, let’s implement this:

Open post_add.html and modify the file as follows:

TGDB/django_project/cadmin/templates/cadmin/post_add.html

Here we are rendering each form field manually. Notice that we are only displaying author list when the logged in author is superuser. So, essentially we want to make author field optional but the problem is our current state of the Post model doesn’t allow that. To view this problem login to cadmin app using a non-superuser account and try creating a new post.

After hitting the save button you will be redirected to Post add page again. So what’s going on? The problem is that the form validation failed because we have not provided any value to the author field.

But! Where are the errors?

We didn’t get any error messages because we have hidden the author dropdown field. To view the error message, comment out the if tag (line 58) in post_add.html as follows:

TGDB/django_project/cadmin/templates/cadmin/post_add.html

Hit the save button again and you will be displayed a form like this:

One way to solve this problem is to make author field optional in PostForm class. To do so, modify PostForm class in blog’s forms.py as follows:

TGDB/django_project/blog/forms.py

Here we are redefining author field as ModelChoiceField field. The ModelChoiceField will be rendered as dropdown list and will use data specified in the queryset parameter to populate the field. The required=False makes the author field optional.

Next, we need a new special Author account to assign post in case a superuser not selected any author from the dropdown list.

Create a new Author with username staff by visiting http://127.0.0.1:8000/cadmin/register/ page, then verify the account the by clicking email verification link sent to the email. Hop back to the Django shell and set the is_superuser attribute of the user we just created to True.

Instead of using Django Shell, we could have also used Django Admin for this change.

Now the only thing remain is to update our post_add() view. Open post_add() view and modify it as follows:

TGDB/django_project/cadmin/views.py

There is nothing new in the above code, except commit=False and save_m2m() method. As you already know, calling save() method on a ModelForm class saves the object into the database. When we pass commit=False to the save() method, then the save() method just returns the object instead of saving it into the database. We do this usually when we want to add some additional data to the object. In this case, we are assigning author object to the post.

A side effect of passing commit=True to save() method is that, if your model has many-to-many relation with other models, then Django will not save the data for many-to-many relation. To solve this issue Django provides a method called save_m2m() to every ModelForm class. Calling save_m2m() saves the data for many-to-many relation.

To view the fruits of our labor login to cadmin app using a superuser account (like the staff) and create a new post by visiting http://127.0.0.1:8000/cadmin/post/add/ page.

Enter the data in all the fields except author and hit “Add Post” to create a new post.

This action will cause the execution of following snippet in the post_add() view:

TGDB/django_project/cadmin/views.py

Create another post but this time select an author from the dropdown list.

This action will trigger the execution of elif block in post_add() view:

TGDB/django_project/cadmin/views.py

Finally, logout from cadmin app and login again using a non-superuser account. And create a new post again by visiting http://127.0.0.1:8000/cadmin/post/add/ page.

As you can see the logged in user is not allowed to select author. Enter some data in the fields and hit “Add Post” button. This action will execute else block in the post_add() view:

TGDB/django_project/cadmin/views.py

Modifying Post Update Page

Open cadmin’s views.py and amend post_update() view as follows:

TGDB/django_project/cadmin/views.py

Next, open post_update.html and modify the page as follows:

TGDB/django_project/cadmin/templates/cadmin/post_update.html

Now just like with Post Add page Author dropdown list will only appear in when the logged in user is a superuser.

Creating Post List Page

Open cadmin’s views.py and add post_list() view as follows:

TGDB/django_project/cadmin/views.py

The post_list() view displays a list of post in reverse chronological order (i.e latest first, oldest last). If logged in user is a superuser then it will display all the posts in the database. On the other hand, if logged in user is non-superuser it will only display posts created by himself.

Next, create post_list.html template with the following code:

TGDB/django_project/cadmin/templates/cadmin/post_list.html

We want users to show a list of post at the root URL of cadmin app i.e http://127.0.0.1:8000/cadmin/. Currently, the root URL of cadmin app points to home() view function.

TGDB/django_project/cadmin/urls.py

Update the above URL pattern as follows:

TGDB/django_project/cadmin/urls.py

Right now if you visit post list page (http://127.0.0.1:8000/cadmin/), you will get an error as follows:

This is because we haven’t yet created any URL pattern to delete post objects.

Deleting Posts

To allow deletion of post from cadmin add post_delete() view at the end of the file as follows:

TGDB/django_project/cadmin/views.py

Now open cadmin’s urls.py and add the following URL pattern to just below post_update URL pattern.

TGDB/django_project/cadmin/urls.py

To view our changes in action visit http://127.0.0.1:8000/cadmin/ and you should see a link to delete post beside Edit link as follows:

Creating Category List Page

Open views.py and add category_list() view just below post_delete() view as follows:

TGDB/django_project/cadmin/views.py

Create a new template called category_list.html with the following code:

TGDB/django_project/cadmin/templates/cadmin/category_list.html

Next, add the following URL pattern just below post_delete URL pattern as follows:

TGDB/django_project/cadmin/urls.py

Creating Category Add/Update Page

Category Add/Update page will be similar to Post Add/Update page. Here too we will display author dropdown list only to the superusers.

First open blog’s forms.py and redefine the author field in CategoryForm class as follows:

TGDB/django_project/blog/forms.py

Open cadmin’s views.py and add category_add() and category_update() view as follows:

TGDB/django_project/cadmin/views.py

Create two new templates category_add.html and category_update.html with the following code:

TGDB/django_project/cadmin/templates/cadmin/category_add.html

TGDB/django_project/cadmin/templates/cadmin/category_update.html

At last, add the following URL patterns to the end of urlpatterns list in cadmin’s urls.py as follows:

TGDB/django_project/cadmin/urls.py

Deleting Categories

In cadmin’s views.py, add the category_delete() view just after category_update() as follows:

TGDB/django_project/cadmin/views.py

Next, add the following URL pattern at the end of urlpatterns list:

TGDB/django_project/cadmin/urls.py

Creating Tag Pages

First open blog’s forms.py and redefine the author field in TagForm class as follows:

TGDB/django_project/blog/forms.py

Creating Tag List Page

In the cadmin’s views.py, add tag_list() view just after category_delete() view.

TGDB/django_project/cadmin/views.py

Create a new template named tag_list.html and add the following code to it:

TGDB/django_project/cadmin/templates/cadmin/tag_list.html

Next, add the tag_list url pattern at the end of urlpatterns list as follows:

TGDB/django_project/cadmin/urls.py

Tag Add/Update Page

In the cadmin’s views.py file add tag_add() and tag_update() views as follows:

TGDB/django_project/cadmin/views.py

Create two new templates tag_add.html and tag_update.html with the following code:

TGDB/django_project/cadmin/templates/cadmin/tag_add.html

TGDB/django_project/cadmin/templates/cadmin/tag_update.html

Next, add the following two URL patterns at the end of the urlpatterns list as follows:

TGDB/django_project/cadmin/urls.py

Deleting Tags

To delete tag add the following view to the cadmin’s views.py file.

**TGDB/django_project/cadmin/views.py**

Then, add the following URL pattern to the urls.py file as follows:

TGDB/django_project/cadmin/urls.py

Creating Account Info Page

In this section, we will create Account Info page, which will the display details of the logged in user. In views.py, add the following view at the end of the file:

TGDB/django_project/cadmin/views.py

Create a template called account_info.html and add the following code to it:

TGDB/django_project/cadmin/templates/cadmin/account_info.html

At last, open urls.py and add the following URL pattern at the end of the urlpatterns list :

TGDB/django_project/cadmin/urls.py

To view logged in user details visit http://127.0.0.1:8000/cadmin/account-info/.

Sidebar Links

We have created all the required pages for our cadmin app. The only thing remain is to add links to the pages in the sidebar. Open base_admin.html and modify the links in the sidebar as follows as follows:

TGDB/django_project/cadmin/templates/cadmin/base_admin.html

Nothing new here except request.get_host function. The request object (HttpRequest) has a method called get_host() which returns the hostname. At this point, cadmin app is fully functional, use it to create some new post, categories, and tags.

In the next lesson, we will learn how to integrate a WYSIWYG editor in Django Admin and our custom built cadmin app.

Note: To checkout this version of the repository type git checkout 36a.

Leave a Comment