My dear reader, how are you? السلام عليكم
Consistency is the foundation of virtue – Francis Bacon
This post is a continuation of Django tutorial series using an example MovieStore. I will explain how to add detailed views in our application. Further, we will define person relationships with our movie models and explain different types of relationships that may occur between different personality types such as movie writers, directors, actors and etc.
Before we start, a few useful links are as below:
- MovieStore GitHub Repository – (DirectMe)
Use the following command to clone the directory.$ git clone https://github.com/ArsalanShahid116/Django-MovieStore.git
- How to Define Django Models and Create Views – MovieStore Part 1 (DirectMe).
To fetch the GitHub project until this point, use the following command inside the cloned directory.Django-MovieStore$ git fetch origin fc62df78bb491b6c54ba261cb682a82da9cfc94a
- Creating Django Views and Design Templates – MovieStore Part 2 (DirectMe)
Fetch to this point using key: d3ea7112782236cf6c2844115cd202ce9f53f186
First of all, we will create a Django Detail view. Open view.py in moviesApp folder and add the following code:
from django.views.generic import (ListView, DetailView) from moviesApp.models import myMovie class MovieList(ListView): model = myMovie class MovieDetail(DetailView): model = myMovie
Now as we added our view so we need to create a template. In order to create a template, let us now change the location for our templates directory to a commonplace which can be used by other Django applications as well. In simple, we will create a general templates directory to add a base template for our MovieStore which can be extended and used further in other templates.
open movies/settings.py, and edit the following line shown in bold in templates.
TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(BASE_DIR, 'templates'),], 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }, ]
Create a templates directory in Django project MyMovies as follows and add a base.html as shown below
(myenv)Django-MovieStore/MyMovies$ mkdir templates (myenv)Django-MovieStore/MyMovies$ touch templates/base.html # open base.html and add the following code into it <!DOCTYPE html> <html lang="en" > <head > <meta charset="UTF-8" > <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" > <link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css" integrity="sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M" rel="stylesheet" crossorigin="anonymous" > <title > {% block title %}MyMovies{% endblock %} </title> <style> .mymdb-masthead { background-color: #EEEEEE; margin-bottom: 1em; } </style> </head > <body> <div class="mymdb-masthead"> <div class="container"> <nav class="nav"> <div class="navbar-brand">MyMDB</div> <a class="nav-link" href="{% url 'moviesApp:MovieList' %}" > Movies </a> </nav> </div> </div> <div class="container"> <div class="row"> <div class="col-sm-8 mymdb-main"> {% block main %}{% endblock %} </div> <div class="col-sm-3 offset-sm-1 mymdb-sidebar"> {% block sidebar %}{% endblock %} </div> </div> </div> </body > </html >
Once done, we now add a detail view template that extends the base template as follows.
# create a new template (myenv)Django-MovieStore/MyMovies$touch moviesApp/templates/moviesApp/mymovie_detail.html # add the following code into it {% extends 'base.html' %} {% block title %} {{ object.title }} - {{ block.super }} {% endblock %} {% block main %} <h1> {{ object }} </h1> <p class="lead"> {{ object.plot }} </p> {% endblock %} {% block sidebar %} <div> This is a side bar and can be used for movie rattings or other features </div> {% endblock %} # {% extends 'base.html' %} If a template wants to extend another template the first line must be an extends tag. Django will look for the base template (which can extend another template) and execute it first, then replace the blocks.
we now update the list view using the base template as well by updating the mymovie_list.html template.
(myenv)Django-MovieStore/MyMovies$ vi moviesApp/templates/moviesApp/mymovie_list.html # ---------------------------------- {% extends 'base.html' %} {% block title %} All Available Movies {% endblock %} {% block main %} <u1> {% for myMovie in object_list %} <li> <a href="{% url 'moviesApp:MovieDetail' pk=myMovie.id %}"> {{ myMovie }} </a> </li> {% empty %} <li> No movies yet </li> {% endfor %} </ul> {% endblock %}
We will now add relationships between two models. We will first create a new model and name it as Person model and then add a relationship between Person and myMovie model using a ForeignKey.
# open moviesApp/models.py and add the following class Person(models.Model): first_name = models.CharField( max_length=140) last_name = models.CharField( max_length=140) born = models.DateField() class Meta: ordering = ( 'last_name', 'first_name') def __str__(self): return '{}, {} ({})'.format( self.last_name, self.first_name, self.born)
We now add a new director variable into our myMovie model class that has a many-to-one relationship with Person class. Which means that a director can direct many movies but NOT the vice-versa.
# Extend the myMovie model class with the following in bold class myMovie(models.Model): title = models.CharField(max_length=140) plot = models.TextField() year = models.PositiveIntegerField() director = models.ForeignKey( to='Person', null=True, on_delete=models.SET_NULL, related_name='directed', blank=True) ... ...
We further add a new role for writers to myMovie class using a many-to-many relationship with Person class as follows
# Extend the myMovie model class with the following in bold class myMovie(models.Model): ... ... writers = models.ManyToManyField( to='Person', related_name='writing_credits', blank=True) ... ...
Apart from this Django also supports one-to-many and one-to-one relationships.
In the next post, we will continue to extend our MovieStore tutorial by adding myMovie and Person custom managers and creating a user login/registration portal.
I hope you find this tutorial useful. If you find any errors or feel any need for improvement, let me know in your comments below.
Signing off for today. Stay tuned and I will see you next week! Happy learning.