Go Back

Design Patterns in Django

Discover high-level design patterns in Django to address different use cases. Learn best practices for creating scalable, maintainable architectures tailored to your project's needs.
June 4th, 2024

IMAGE_ALT

There are countless design patterns possible with any tech stack. Your creativity and specific use case will determine which pattern is best suited for your needs. Below, I outline various design patterns to inspire you. These patterns can be combined and modified in numerous ways—how you implement them is up to you. It's also common to start with one pattern and later transition to another as your project evolves.

1. Starting with a very basic design pattern

IMAGE_ALT

In the above diagram,

  • there is 1 Django project with multiple apps
  • Project 1 is running on a server(local machine or cloud VM)
  • Project 1 is connected to a database on a db server(this db server can be present on the same machine where Project 1 is running or on a separate machine)
  • There is one user table(even if you want to have multiple user types, you have to manage them using a common table)
  • Now in order to make the above system available to public, first thing you will have to do is to point your domain to the server’s IP address using DNS Server(if you want to access your system through the domain name).
  • For deploying there can be multiple ways
    1. Directly running Django using Gunicorn(WSGI Server) on port 80. 2 strategies to do this(for comparison https://stackoverflow.com/questions/19916016/gunicorn-nginx-server-via-socket-or-proxy) -
    2. Running the project using Gunicorn(WSGI Server) on port 8000(or any other port using the above methods), then placing a web server(for ex. Nginx) in front of it.
      • This web server will provide the following functionalities:
        • Reverse Proxy - in order to route traffic coming on 80 port(HTTP)(either through IP address or domain/subdomain) to Gunicorn
        • Handling static and media files - instead of putting a load on Django, you can serve static files by this web server
        • SSL certificate - If this is configured, traffic will come on 443 port(HTTPS)
    3. Packaging your django app using docker
      • in the docker-compose file, run django app using gunicorn as a service, and then running docker-compose up —-build -d
      • You can run nginx also by specifying in docker-compose and making configurations for SSL, static & media files, and traffic routing or you can also run nginx normally on the machine and routing traffic to the exposed port of the docker container
      • You can also use traefik(a light weight reverse proxy) in order to route traffic to docker container, but traefik do not serve static files. With traefik, there is no need to expose the port of django service in the container. You just have to make sure that traefik and django docker containers share a common network.

2. Multiple domains/subdomains linked to the same project

IMAGE_ALT

IMAGE_ALT

  • First of all you will have to route traffic according to domain/subdomain through reverse proxy(nginx or any other) to django app.
  • Now django app will have to internally route the traffic according to domain/subdomain. If in case you want to route traffic to apps associated to specific subdomain, then you can try django-subdomains python pip package(there are other alternatives too) or you can create your own internal router.
  • Deployment can be done using the ways specified in the 1st design pattern.

3. Multiple domains/subdomains linked to the same project but now you want same model to be associated to different domains/subdomain(or websites)

For ex. You created a blog backend, now there are 2 domains/subdomains(techblog.com, financeblog.com), if a request come through the techblog.com domain you have to return blogs linked to techblog.com and if the request comes through financeblog.com then blogs associated to this. But you want to use the same table for both of them, then you can use django site framework . It's also possible to link an object with both websites using ManyToManyField with site object.

You can deploy this in 2 ways -

  1. Serving both websites using the same codebase, this will use get_current_site() (https://docs.djangoproject.com/en/4.1/ref/contrib/sites/#django.contrib.sites.shortcuts.get_current_site) to get the domain with which user has requested for, and give response accordingly.
  2. Deploying each website independently, 2 identical django projects but deployed separately(difference will be in settings.py file + webserver/reverse proxy configuration). In this case also you can use get_current_site() to identify user request domain but here ****you can also specify SITE_ID in django settings, this SITE_ID will be specific to domain/subdomain and decide which data has to be returned to the user. Ofcourse you can scale both horizontally independently as much as possible.
    • Cons
      • If any change happens to repo, it has to be updated in 2 places

4. Deploying same code independently, to serve different functionality on both

IMAGE_ALT

in project’s urls.py disabling some app URLs for server 1 and some in server 2.

You can deploy in this fashion in a lot of ways -

  • Deploying both on same server by making separate settings file and urls.py file
  • Deploying on 2 different servers(here also separate settings file)
  • You can even associate multiple subdomains/domains to one independent deployment.

5. Using a different user table to server multiple user types

IMAGE_ALT

There are multiple ways to handle it:

  • Making a separate user table in a database, then making a custom authentication backend
  • Using a different database on same db server or a different db server(on same or different machine)
  • You can associate domain/subdomain according to your scenario by taking ideas from above design patterns

6. Using Microservice Architecture

IMAGE_ALT IMAGE_ALT

  • For communication between 2 microservices, you can use following ways:

    • Remote Procedure Calls(RPC)
    • Message Brokers
    • REST API
  • You can deploy both microservices on the same server or different servers

Further for scaling your application, you can check out this video: https://www.youtube.com/watch?v=yoggLJv72Ps&t=2229s

In order to scale DB, there are different techniques available like replication and sharding which I will be covering in the separate blog.

See you in the next blog :)


Django
Backend Development

Join my newsletter & get latest updates




© 2024, Priyanshu Gupta