Django is the most used Python web development framework. Its built-in features and extensive amount of 3rd party packages have made it one of the most loved web frameworks all around the world. It is fast, reliable, and has a lot of built-in features. For instance, a hole authentication system, that lets you focus on the main features of your app. Also, you can install external packages to accomplish even more complex tasks, like Django-allauth, which allows you to register users with their social accounts. But let’s expose some facts. Django is such a huge framework that sometimes is challenging to get started with it. So today you are going to build from scratch a totally functional Django application. By the end of this tutorial, you will:
Have written a URL shortener app Understand the Django MVT pattern Have learned the workflow of creating a project
Pre-requirements
All of the following requirements are optional and will help you to follow along with the tutorial. But if you don’t have experience with any of these, don’t worry. The most important step is the first.
Basic understanding of UNIX commands (ls, cd, rm, touch) Basic understanding of Python classes and functions Python installed on your computer (Maybe obvious but I had to include it) It would be great if you already have built something with Django
All the working code will be available on this Github repo. Now that you have crystal clear the previous concepts, let’s get into the matter.
Project statement
In this tutorial, you are going to build a URL shortener. Basically, a URL shortener is a service that takes a long URL and turns it into a compact one. For example, if you want to share a tweet and want to include a link to your website, but you are facing the characters limit, you could use an URL shortener. Let’s see it with a graphic.
As you can see, the URL shortener gets a long URL and returns a short one. That’s exactly what you are going to build today. With this project, you will practice the usage of the MVT pattern, learn the basics of database design with Django models, and learn how to show information to the user through views, URLs, and templates.
Structure of a Django project
Basically, a Django website is built upon a single project and multiple separated apps. Each one of these apps has specific functionality and it’s able to work by itself. Let’s imagine a complex web application like Stackoverflow. Its functionality is based on two main aspects.
Users management: Sign-in, Log out, Reputation, Permissions Forum: Questions, answers, tags, Filters
So following the Django website structure, the project would be named StackOverflow which has two main apps. The users’ app and the forum app. Each of these apps has self-contained functionality. That means that both contain all the code that they need to work properly. That includes models (database structure), views (requests and responses), specific URL patterns, and of course, templates and static files (images, CSS, JavaScript). This means that any Django app could be reused since they are able to work by themself. Shortening, a project refers to a set of configurations and apps that is meant to build a Web Application. On the other hand, a Django app is a part of a project, which is self-contained (has everything it needs to work), and its purpose is to perform a specific operation.
Set Up a Django project
In this section, you are going to set up a Django project. For that purpose, you are going to use different tools like a Virtual environment to organize Python dependencies and the most important Django scripts. Django-admin and manage.py
Virtual environment
I always recommend working with virtual environments when building apps with Django. It is the most efficient way to maintain a specific set of dependencies. But its main purpose is to isolate the development packages from the global ones. So let’s create a virtual environment with python the built-in form command. Note: This method requires Python 3.6 or newer versions to work. This command uses the python -m or python –mod command. Fundamentally it runs a module or library, as a script. According to the meaning of this command, venv is the library that we’re running, and .venv refers to the name of the virtual environment we want to create. So in plain language, this command means. Now, it’s time to activate the virtual environment we just created, with the following command. To assert that you have zero packages installed in the new venv, you run. If you activated the virtual environment correctly, you won’t get any output. That’s because we haven’t installed anything yet.
Let’s get into Django
In order to create our URL shortener application, we are going to start by installing the Django package. Django is a third-party package, therefore we need to install it with Pip (Pip Installs Packages). Note: Remember that $ is nothing but your shell symbol. To check if the installation went correctly, we check again the installed packages of our venv. Don’t worry if the versions you get are different from mine. If Django stills on version 3.x you can continue without any problem.
Starting a Django project
Once you have installed Django, it’s time to create the structure of the URL shortener website. Do you remember what is a Django project? Let’s create one by running the following command. Explaining all about this command, django-admin is a command-line utility that performs all the needed tasks to create a Django project. The “startproject” part is the command ran by the Django-admin utility, and config is the name of the project we’re going to create. Is important to emphasize that config can be any name you want. The reason I use config as the name of this project is just because of convenience. It’s nice to switch between projects and still have the same naming convention. So don’t be afraid of using other project names whenever you want. As you may notice now you have a config/ folder and inside, there are many files. Later we will see the file structure of the project. For now, let’s enter the project directory and run the local server. The most important file you will be using is the manage.py script. It has the same functionality as django-admin, but the main advantage of using it is that lets you manage the settings when running the project. Now let’s see if everything is working properly.
Creating the Url shortener app
It’s time to create the main app of the project. You are going to use the manage.py file to accomplish this task. This creates a Django app, with the name urlshortener. If you run the tree command, you’ll get something like this. Let’s clarify the different files created until this moment. “config” is the name of our project and it is named like that just for the convention. Inside of config, you get settings.py, it is the file where you set all the settings of your project. urls.py is the URLs’ overall configuration inside the project. It defines the URL paths of all the applications inside of the project. Don’t worry too much about the asgi.py and wsgi.py files. These are files that let you configure your application in deployment. The manage.py is the python script that lets you run all the available commands of Django-admin. Taking a look inside urlshortener which is the name of the app you just created, you may notice there is a weird folder called “migrations/” and some other files that are crucial to the logic of any app. apps.py is where the app configuration lives. Usually, you don’t mess around with it, except you are doing pretty advance stuff. admin.py is where you register your models to make them visible inside the Django admin panel. models.py is the most important one. Inside this module, you must define the models, which (vaguely saying) are the way the data is stored. You’ll hear more about models later. migrations/ is the folder where Django migrations are stored. We will take an in-depth look later. tests.py is the file where the tests are stored. We won’t cover testing in this tutorial. views.py is the file that stores views. Basically, it defines how the user will interact with all the aspects of your app.
Installing a Django app
Before continuing, open the settings.py file and modify the INSTALLED_APPS variable by adding the urlshortener app. This is a routine process when you create an app. So every time you do it, don’t forget to install it on the project settings.
Understanding the MVT pattern
The Model, View, Template pattern is the software design pattern that Django developers use to create web applications.
It is based on 3 main concepts. Model (data), View (User interaction with data), Template (How the users see the data). Models are Python classes, which define all the fields and behavior of the data you are willing to store. Normally each model refers to a unique table on the database Views in their simplest expression, are callables that take a request from the user and generate a response. Between that process occurs the business logic. I know that “business logic” is a pretty obscure concept, so let me explain exactly what it is. Business logic is the way data is created, stored, and deleted, that’s all. Finally, templates are text documents (Usually Html) that are shown to the users. Its purpose is to present data as clean as possible. Django incorporates a mini-language called Django template language (DTL) which lets you incorporate some of the power of python in text documents.
Create the Shortener model
Once you’ve had a quick grasp of the MVT pattern, let’s get into creating the Django URL shortener from scratch. First of all, let’s define the shortener model inside of the models.py file. I know. It is a pretty huge class, with a lot of weird stuff going on, but don’t despair. I’ll go step by step on each important thing.
Model explanation
First of all, we import the models module. This module contains all of the functionality we need to create a Django model. Taking a look at the “Shortener” model, the first thing to note is that it extends models.Model. In fact, any model in any Django app must be a subclass of the models.Model class. Then we define all the fields the model will have on the database. The “created” field is the date and time the shortened link is created, therefore we use DateTimeField to create this kind of functionality. We use the argument auto_now_add=True because we want the field to only be altered when the instance is created. The second field times_followed refers to the times the shortened URL has been used. It is a PositiveIntegerField and we specify a default of zero. That means that every time an instance has created the times_followed field, Django will fill out that field with 0. On the other hand, long_url refers to the URL the user inputs. It is an URLField, because we only want the user to enter characters of the form: http://yoursite.com. The last field is short_url, and it has interesting details. We specify that it only can be 15 characters long, it must be unique, which means that there can’t be repeated elements in that field. Finally, we indicate that it can be left blank, which means that when working with forms users won’t need to write their own shorten code. The Meta inner class, tell us how the class must behave, and we set that the ordering (calling Shortener.objects.all()) of the shortener objects will be discriminated by the most recent ones. The str method tells how the model must be printed. So if we have an object with long_url = “https://geekflare.com/” and shortened part “123456”, and we print it. Now it’s time to look up a way to save the short link in a random way.
Creating shortening functionality
We are going to create 2 custom functions. The first will generate a random code and the second will prevent getting repeated random codes from the Shortener model. To do this, create a file utils.py inside the “urlshortener” app. Inside of this file, we are going to use the choose function from the random built-in module. This facilitates the task of choosing random characters to create the code. As you can see this function returns a random string of the length specified on the settings file or 7 by default. You are using the function getattr to get a variable from the settings module, but without throwing an error if the variable isn’t specified. Let’s do some math. If we have 7 places where there can be up to 62 available characters for each place, the possible permutations are:
So based on these quick calculations, the shortened part can be filled out up to 2.5 trillion different codes. So we can forget about getting out of random shortened URLs. Although there can exist such a lot of permutation, there is a small probability of getting repeated shortened parts. This is a problem since we set up the shortened_url field to be unique. That’s why the following function is so useful. Let’s see what’s happening here. The function takes as an argument a “Shortener” model instance. First, the function generates a random code using the create_random_code. Then it gets the model class and checks if there is any other object that has the same short_url. If it does it runs itself one more time, but if everything is fine it returns the random_code. Later you will interact with the shell, in order to take a look at this function closely. After creating the utility function, let’s use it to create random codes in the shortener model.
Modifying the save method
At the end of the “Shortener” class, you are going to modify the model save method. The save method is called every time an object is saved to the database, so we will see how to use it here. The save method is being overwritten, which means you are introducing new functionality to a pre-existing parent method. It is basically telling Django that each time a “Shortener” object is saved and the short_url isn’t specified, it must be filled with a random code.
Running migrations
Now it’s time to make and run the migrations of the Shortener model. To do that run the following commands in the root project folder. For now, you don’t have to worry about what migrations are. Just have in mind that when running these two commands Django creates a db.sqlite database file, based on the models you’ve defined. Let’s create some objects with the Django shell. That’s pretty much how all shortener objects will work.
Writing views
As I said before, a view is a simple function that takes a request and returns a response. So let’s see how to create a hello world view.
Basic template response
Inside of “urlshortener/views.py” file create a function home_view. aa It returns a simple message “Hello world”. Later you will see how it looks in the browser. Now create a “urls.py”, there will stand all the URL patterns of the app. touch urls.py Add the following code. The appname variable declares (as its name suggests) the namespacing of the urlshortener app. Quickly explaining we are importing the path function, which returns an element to include in the urlpatterns of the app. The name attribute is the namespace of the path, that can be called inside templates if necessary. Now, let’s modify the overall project URLs. Now let’s run the server again. If you run the server, you’ll get a simple “Hello world” message. This is because you are including the urlpatterns from the URL shortener app, into the overall project.
This is just a starting point. Now it’s time to create a form to let the user create Shortened URLs by themselves.
Creating forms
In Django, a form is a simple class that allows getting input from the User. You are going to create a forms.py file. It is a convention to store all the forms of the app in that file. Inside of that file you are going to create a class “ShortenerForm” which extends from “ModelForm”. It is a model form since its purpose is to create a model object from the user input. We also make use of the widget argument, which lets us specify the “class” (class in CSS, not python) attribute. This is because we are going to stylize the app with bootstrap later.
Finishing the views
After building the forms is time to create the final business logic of the application. Navigate to the views.py file inside the shortener app, and modify the home_view view. You can check out the Github repo at this moment to get an idea of how the project structure looks like. There are two views for the URL shortener app: Let’s start with the home view which is the most complex. You will need to import the Shortener model and form. You still using a function since I want you to understand all the data flow of the view. Also, you’ll be using the path for a template (Which is not created yet).
Home view
The view is based on two conditionals: A tricky way of getting the complete site URL dynamically is by using the request object method build_absolute_uri . As a safe way of processing a wrong request (The user didn’t enter a valid URL), we get the form errors, pass them as context and render the template as normal. Later you’ll see how to implement the error display in the template.
Redirect view
The redirect_url_view , is a little bit simpler. It is a detailed view which means, the view only works with an object. This function takes as parameters, the user’s request and the shortened_part of the URL. It isn’t necessary to assert the type of request we are getting, since we are not working with forms in this view. We protect the view with a try/except statement, in case the shortened part isn’t found in the database. If the object is found it adds 1 to the times_followed field and redirects with the HttpResponseRedirect function to the site URL corresponding to the random code.
Updating URLs
Once you created the two views of the app, it’s time to create the final URL patterns by including the path to the redirect_url_view. As always you start by importing the views, and then creating a path function and passing as arguments:
The URL route The view pointing to the path The name of the path
With this URL setup, the routing of the app looks like this.
localhost:8000/: Home view localhost:8000/URL-code: Redirection to the long URL
Creating templates
You are almost there. The only thing that separates you from having built this app is the user interface. For that, we use Django templates. Templates are used to render a clean interface to the app user. These files are created inside of the app in a double folder structure of the form: “templates/appname” Note: The double folder structure and the Django Template language are beyond the scope of this tutorial but you can read about them in the official documentation.
Base template
Django allows template inheritance. This means that we can have a base template and extend it with the purpose of following the DRY (Don’t repeat yourself) principle. The base.html file is a convention and means that every other template on the app, must be an extension of this one. We are going to use the bootstrap CDN, to make a quick and pretty interface without needing CSS or javascript files. If you want to learn deeply about DTL tags, you can do it with the official docs.
Home template
The home template, inherence from the base.html file. That means that this template includes all the HTML from the parent file. I’ll quickly explain the data flow of this template:
The Shortener form is displayed. Inside, the crsf token is set (Security reasons), and only the long URL field of the form is shown. Remember that this field has the CSS class, “form-control form-control-lg”, because we set that in the form. If any errors are found, then show them If the POST operation succeeds then, the new URL is shown.
Final application
Congratulations! 🎉. You’ve built a complete functional URL shortener app with Django. Here are some screenshots of how the application looks like. Get only:
Error shortening URL:
Successful shortened URL:
URL redirected:
What do you think of exposing a demo of this URL shortener app to someone? Check how to expose a Django Demo app to the internet.
Challenge 🔥
If you feel comfortable with your Django skills, why not practice with a challenge ?. Clone the code of this application and create an authentication system, where only registered users can shorten their URLs. When you are done, send a pull request and ping me on Twitter to showcase your achievements.
Wrapping up
You’ve reached the end of this tutorial. Believe it or not, you just reviewed all the main aspects of creating a Django project. I hope you found it extremely useful. In this tutorial you:
Learned about the workflow of creating a Django app. Built a resume project Understood the differences and the structure of Django projects and Django apps. Discovered the MVT pattern. Created Function base views Used the Django ORM (Object Relational Mapper) to create simple models
That’s all, there is a lot to cover with the Django web framework, so keep in touch for more amazing tutorials.