How to use Django Models

June 1, 2020, 11:12 a.m.

Django Bootstrap · 11 min read

How to use Django Models

A Django model is a powerful source of information and behaviors stored within a single database table.

But what exactly does that mean?

Well, the simplest way of conceptualizing a model is to consider it a blueprint for storing information.

To demonstrate this powerful built-in feature of Django, let's create a model that lists popular movies. First, we will create the model and its fields, then we will log in to the Django administration site and fill in the fields with information on different movies, and finally, we will render the code using a for loop. 

 

Create a model

env > mysite > main > models.py

from django.db import models

# Create your models here.

class Movie(models.Model):
	movie_title = models.CharField(max_length=150)
	release_year = models.IntegerField()
	director = models.CharField(max_length=100)
	movie_plot = models.TextField()
	

	def __str__(self):
		return self.movie_title

Start by opening the models.py file in the app directory folder. Add the class Movie inherits (models.Model) just below the comment. Next, we need to specify all of the information we want to list under each movie we add to our project.

First, add a field for the movie's title. This field is a CharField or character field that takes in a maximum of 150 characters of text. Next, add an IntegerField for the release year. Let's also add a field for the director's name. The last field we will add is for the movie's plot. This field is a TextField that allows paragraph text submissions.

Before we move on, let's add a function that returns the movie's title as the display name. If you forget to add this function it will list as Movie object (1), Movie object (2), and so on, making it hard to know which object corresponds to a particular movie.

Be sure to save the file. 

 

Make migrations to create the model

macOS Terminal

(env)User-Macbook:mysite user$ python3 manage.py makemigrations
Migrations for 'main':
  main\migrations\0001_initial.py
    - Create model Movie


(env)User-Macbook:mysite user$

Windows Command Prompt

(env) C:\Users\Owner\Desktop\Code\env\mysite>py manage.py makemigrations
Migrations for 'main':
  main\migrations\0001_initial.py
    - Create model Movie

(env) C:\Users\Owner\Desktop\Code\env\mysite>

To use the model in the Django admin, we need to makemigrations and create the model that maps to a single database table. 

 

Migrate the model to the database

macOS Terminal

(env)User-Macbook:mysite user$ python3 manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, main, sessions
Running migrations:
  Applying main.0001_initial... OK


(env)User-Macbook:mysite user$

Windows Command Prompt

(env) C:\Users\Owner\Desktop\Code\env\mysite>py manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, main, sessions
Running migrations:
  Applying main.0001_initial... OK

(env) C:\Users\Owner\Desktop\Code\env\mysite>

Now with the table created, we can migrate the model so all of the information uploaded to the model will be saved to the Django database, db.sqilte3

 

Register the model in the Django admin

env > mysite > main > admin.py

from django.contrib import admin
from .models import Movie

# Register your models here.

admin.site.register(Movie)

With the model successfully added to the database, we need to register it to the administration page so we can access it on the Django admin page. Import Movie from the models.py file at the top of the page then add admin.site.register(Movie) below. Save the file or the model will not appear on the admin page we will soon access.

 

Create an admin username and password

macOS Terminal

(env)User-Macbook:mysite user$ python3 manage.py createsuperuser
Username (leave blank to use 'owner'): admin
Email address:
Password: *****
Password (again): *****
Superuser created successfully.

(env)User-Macbook:mysite user$ python3 manage.py runserver

Windows Command Prompt

(env) C:\Users\Owner\Desktop\Code\env\mysite>py manage.py createsuperuser
Username (leave blank to use 'owner'): admin
Email address: 
Password: *****
Password (again): *****
Superuser created successfully.

(env) C:\Users\Owner\Desktop\Code\env\mysite>py manage.py runserver

Return to the CLI and run the command to createsuperuser in your project. Enter a username and password then press Enter to skip the optional email address field. Once the user is created, run the server again. This is the username and password needed to access the project's admin site so be sure to remember them.

 

Log in to the Django admin site

Go to http://127.0.0.1:8000/admin/ in a new tab and login to the Django administration page with the username and password just created. Upon login, you will see an interface with the model "Movies" listed below "Main", the name for your app.

Login in to Django Admin

 

Add a movie to the Movie model

Now let's add a movie to the model. Click on "Movies" then on the "Add movie" button in the top right corner. You will then be brought to a page that displays, yes you guessed it, the fields we added to the model in models.py. 

Add a movie to the Movie model

 

 

Render the model in the template

env > mysite > main > views.py

from django.shortcuts import render
from .models import Movie

# Create your views here.
def movies(request):
	movies = Movie.objects.all() #queryset containing all movies we just created
	return render(request=request, template_name="main/movies.html", context={'movies':movies})

It's time to render the model in a template. To do this, go to the view function of the template you want to render movies, in this case, it's movies.html, and add a queryset to the function. Then in the return render, set movies as the context returned when the template displays. 

 

Connect a path to the view

env > mysite > main > urls.py

from django.urls import path
from . import views

app_name = "main"   


urlpatterns = [
    path("", views.movies, name="movies"),
]

If you don't have a URL path that connects to the views.py function, make sure to add one to main > urls.py so the view renders in the browser. 

 

Add the model to the template

env > mysite > main > templates > main > movies.html

<!DOCTYPE html>
<html>
  <head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Movies</title>
    <!--Bootstrap CSS-->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
  </head>
  <body>


    <div class="container p-4">
      <div class="row">
        {% for m in movies %}
        <div class="col-lg-4 col-md-6 col-sm-12 pb-4">
          <div class="card h-100 p-4">
            <h4>{{m.movie_title}}</h4>
            <p class="text-muted">{{m.release_year}} | {{m.director}}</p>
            <p>{{m.movie_plot}}</p>
          </div>
        </div>
        {% endfor %}
      </div>
    </div>


    <!-- Optional Javascript -->
    <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
  </body>
</html>

Next, go to the template specified in views.py so we can add the model to the template. We are using Bootstrap to help render the template but we will use Django Template Language (DTL) to render the model. First, create a for loop written {% for m in movies %} with movies being the context we passed in the views function and m being the shorthand reference to movies within the loop.

Now, we can call on all of the fields we specified earlier in the models.py to render all of the information we added in the Django admin. Add {{m.movie_title}}, {{m.release_year}}{{m.director}}, and {{m.movie_plot}} directly within the HTML elements, as if they were regular text. After all of the fields are added, close the for loop with the tag {% endfor %}.

Note: Keep in mind that any HTML elements placed in the for loop must have an opening and closing tag or they will not render correctly.

 

View the page in the browser

Once the model is added to the template, run the server and go to the URL that renders the template containing the model. The movie you added to the admin should appear as if it were hardcoded in the template.

First model

 

Add more movies

Add as many movies as you'd like to the Django admin. Then when you reload the HTML template page in the browser, all of the new model objects will appear in the same format as the first. If you ever want to delete a model object, go to the admin, click on the object, and find the "Delete" button at the bottom of the edit page.

Multiple models

 


 

More Django model fields

We just covered some of the basic Django model fields but there are many more fields easily implemented in models.py. For example:

  • use models.DateField() to add a publication date
  • use models.BooleanField() to add a checkbox
  • use models.SlugField() or models.URLField() to add a URL link
  • use models.DecimalField() to add numbers with decimal places

These are only some commonly used fields but there are several more model fields explained in the documentation.

 

Add an image upload field

env > mysite > main > models.py

from django.db import models

# Create your models here.

class Movie(models.Model):
	movie_title = models.CharField(max_length=150)
	release_year = models.IntegerField()
	director = models.CharField(max_length=100)
	movie_poster = models.ImageField(upload_to='images/', null=True)
	movie_plot = models.TextField()
	

	def __str__(self):
		return self.movie_title

Django offers a field for uploading images to a model, it just requires a little more configuration to the project. First, add a new field to the model called ImageField that specifies the upload will go to a folder named 'images/'. We will also add null=True so the file is not required.

 

Configure settings.py

env > mysite > mysite > settings.py

...

MEDIA_URL = '/media/'

MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

In settings.py, we need to specify a media uploads folder for the images upload to the movie_poster model field. The media folder will hold all of the images uploaded in the Django admin by a user instead of having to add the images directly to the project's static image folder.

 

Add the media folder to the URLs

env > mysite > mysite > urls.py

from django.contrib import admin
from django.urls import path, include
from django.conf import settings #add this
from django.conf.urls.static import static #add this

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include ('main.urls')),
]

if settings.DEBUG: #add this
    urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

Now in the mysite > urls.py add the code above to create a URL path to the media images uploaded to your project. This configuration is only for development, hence the if statement for debugging. In deployment, you will need to configure your static and media files for production.

 

Install Pillow

macOS Terminal

(env)User-Macbook:mysite user$ pip install Pillow

Windows Command Prompt

(env) C:\Users\Owner\Desktop\Code\env\mysite>pip install Pillow

For the media upload to work correct, install Pillow in your activated virtual environment.

 

Make migrations again

macOS Terminal

(env)User-Macbook:mysite user$ python3 manage.py makemigrations
Migrations for 'main':
  main\migrations\0002_auto_20200601_1806.py
    - Add field movie_poster to movie

(env)User-Macbook:mysite user$ python3 manage.py migrate

Windows Command Prompt

(env) C:\Users\Owner\Desktop\code\env\mysite>py manage.py makemigrations
Migrations for 'main':
  main\migrations\0002_auto_20200601_1806.py
    - Add field movie_poster to movie

(env) C:\Users\Owner\Desktop\code\env\mysite>py manage.py migrate

Because we added a new field to the model, we need to run migrations again to push the updates to the database. First, run makemigrations then run migrate. Run the server again once the migrations are made. 

 

Upload an image to a model

Log back into the admin site and click on one of the existing models. You will see a new field with a "Choose File" button. Click on the button and add the movie poster to the model object. Be sure to click "Save" or the update will not work.

Upload an image

 

 

Add the image to the template

env > mysite > main > templates > main > movies.html

<!DOCTYPE html>
<html>
  <head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Movies</title>
    <!--Bootstrap CSS-->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
  </head>
  <body>


    <div class="container p-4">
      <div class="row">
        {% for m in movies %}
        <div class="col-lg-4 col-md-6 col-sm-12 pb-4">
          <div class="card h-100 p-4">
            <img src="{{ m.movie_poster.url }}" class="card-img-top" alt="{{ m.movie_title}}">
            <h4>{{m.movie_title}}</h4>
            <p class="text-muted">{{m.release_year}} | {{m.director}}</p>
            <p>{{m.movie_plot}}</p>
          </div>
        </div>
        {% endfor %}
      </div>
    </div>


    <!-- Optional Javascript -->
    <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
  </body>
</html>

Next, we need to add the image field to the template. To do this you need an image HTML element with the src="{{ m.movie_poster.url }}" and an alt="{{m.title}}". The class attribute is a custom Bootstrap class. Save the file.

 

View the images in the browser

When you refresh the browser tab again, the images you uploaded will display.

Images in browser

 

OPTIONAL: Resize the images

<!DOCTYPE html>
<html>
  <head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Movies</title>
    <!--Bootstrap CSS-->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
  </head>
  <body>


    <div class="container p-4">
      <div class="row">
        {% for m in movies %}
        <div class="col-lg-4 col-md-6 col-sm-12 pb-4">
          <div class="card h-100 p-4">
            <img src="{{ m.movie_poster.url }}" class="card-img-top" alt="{{ m.movie_title}}" style="width: auto; height: 350px; object-fit: contain;">
            <br>
            <h4>{{m.movie_title}}</h4>
            <p class="text-muted">{{m.release_year}} | {{m.director}}</p>
            <p>{{m.movie_plot}}</p>
          </div>
        </div>
        {% endfor %}
      </div>
    </div>


    <!-- Optional Javascript -->
    <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
  </body>
</html>

If you want all of the cards and images to display at the same height add the following style attributes to the image element: style="width: auto; height: 350px; object-fit: contain;".These attributes work together to specify the image height while scaling down the image to fit with its parent element.

When you reload the page, the images will appear at the same height.

Scaled down images


0
Subscribe now

Subscribe to stay current on our latest articles and promos





Post a Comment
Join the community

0 Comments