Django Architecture

  • MVC vs MCT Architecture
  • Both MVC and MVT are one of the famous design patterns
  • They are used for many web application frameworks.
  • It is an architectural pattern that separates an application into three main logical components

2.1 Model View Controller(MVC)

  • Model
    • This is responsible for maintaining data. Handles database basically.
    • Manages data, Business Logic
  • View
    • This is responsible for displaying data (data representation)
  • Controller
    • This is responsible for the interactions between the Model and View.
    • It controls the data flow into Model and updates View when data is changed.

MVC Architecture

2.2 Model View Template (MVT)

  • Django follows MVT Architecture
  • Model
    • models.py
    • This is responsible for maintaining data. Handles database basically.
  • Views
    • views.py
    • It is the business logic layer
    • View interact with both models and templates
  • Templates
    • templates(.html)
    • It is a presentation layer, the component with which user interacts
  • Controller
    • There is no separate controller and complete application is based on Model View and Template.
    • But the three components(M-V-T) communicate with each other via an inner controller
    • And that controller is actually Django framework, It does the controlling part itself

MVT Architecture

2.3 Why is Django called loosely coupled framework?

  • The various layers of the framework should not know about each other unless absolutely necessary.
  • Django is called a loosely coupled framework because of its MVT architecture, which is a variant of the MVC architecture.
  • It helps in separating the server code from the client-related code.
  • Server code –> models and views take care of the server code
  • Client code –> templates are mostly HTML and CSS that just need data from models passed in by the views to render them.
  • Since these components are independent of each other, Django is called a loosely coupled framework.

2.4 django-admin and manage.py

  • django-admin
    • A command-line utility of Django for administrative tasks.
  • manage.py
    • It is automatically created in each Django project
    • It does the same thing as django-admin but also sets the DJANGO_SETTINGS_MODULE environment variable.

Create a django project

# Create a Django project
django-admin startproject mysite

# File Structure --> of Django Project
mysite/
  manage.py
  mysite/
    __init__.py
    settings.py
    urls.py
    asgi.py
    wsgi.py

Run Django project

# Ways to run django server
python manage.py runserver
python manage.py runserver 8080
python manage.py runserver 0:8000

#OR
export DJANGO_SETTINGS_MODULE=mysite.settings
django-admin runserver

#Reset
export DJANGO_SETTINGS_MODULE=django.conf.global_settings

Create Django App

# Create a app
python manage.py startapp polls

# File Structure
mysite/
  manage.py
  mysite/
polls/
    __init__.py
    admin.py
    apps.py
    migrations/
      __init__.py
    models.py
    tests.py
    views.py

2.5 Write custom django-admin commands?

  • Also called as management commands
  • Create below files and folders inside app dir
# Management command file structure
polls/
  management/
    __init__.py
    commands/
      __init__.py
      my_custom_command.py

Positional Arguments

# my_custom_command.py
from django.core.management.base import BaseCommand

class Command(BaseCommand):
    help = 'Positional Arguments'

    def add_arguments(self, parser):
        parser.add_argument('num', type=int, help='Enter a number')
        parser.add_argument('name', type=str, help='Enter a name')

    def handle(self, *args, **kwargs):
        print(kwargs.get('num'), kwargs.get('name'))

# python manage.py my_custom_command 30 amrit
# 30 amrit

Optional Arguments

  • -name or --name is used for optional arguments
# my_custom_command.py
from django.core.management.base import BaseCommand


class Command(BaseCommand):
    help = 'Optional Arguments'

    def add_arguments(self, parser):
        parser.add_argument('-n', type=int, help='Enter a number')
        parser.add_argument('--name', type=str, help='Enter a name')
        parser.add_argument('-c', '--count', type=int, help='NA')

    def handle(self, *args, **kwargs):
        print(kwargs.get('n'), kwargs.get('name'), kwargs.get('count'))

# python manage.py my_custom_command -n 1 --name amrit -c 111
# python manage.py my_custom_command -n 1 --name amrit --count 111
# 1 amrit 111

Flag Arguments

  • action='store_true' is used to indicate Flag argument
# my_custom_command.py
from django.core.management.base import BaseCommand


class Command(BaseCommand):
    help = 'Flag Arguments'

    def add_arguments(self, parser):
        parser.add_argument('total', type=int, help='NA')
        parser.add_argument('-p', '--prefix', type=str, help='NA')
        parser.add_argument('-a', '--admin', action='store_true')


    def handle(self, *args, **kwargs):
        print(kwargs.get('total'), kwargs.get('prefix'), kwargs['admin'])

# python manage.py my_custom_command 1 -p amrit -a
# python manage.py my_custom_command 1 -p amrit --admin
# 1 amrit True
# python manage.py my_custom_command 1 -p amrit
# 1 amrit False

Arbitrary List of Arguments

  • Can pass a single or any number of inputs(separated by spaces) as list
# my_custom_command.py
from django.core.management.base import BaseCommand


class Command(BaseCommand):
    help = 'Arbitrary List of Arguments'

    def add_arguments(self, parser):
        parser.add_argument('user_id', nargs='+', type=int, help='NA')

    def handle(self, *args, **kwargs):
        print(kwargs.get('user_id'))

# python manage.py my_custom_command 1
# 1
# python manage.py my_custom_command 1 2 3
# 1 2 3

Styling

# my_custom_command.py
from django.core.management.base import BaseCommand


class Command(BaseCommand):
    help = 'Styling'

    def handle(self, *args, **kwargs):
        self.stdout.write(self.style.ERROR('error - A major error.'))
        self.stdout.write(self.style.NOTICE('notice - A minor error.'))
        self.stdout.write(self.style.SUCCESS('success - A success.'))
        self.stdout.write(self.style.WARNING('warning - A warning.'))
        self.stdout.write(self.style.SQL_FIELD('sql_field - The name of a model field in SQL.'))
        self.stdout.write(self.style.SQL_COLTYPE('sql_coltype - The type of a model field in SQL.'))
        self.stdout.write(self.style.SQL_KEYWORD('sql_keyword - An SQL keyword.'))
        self.stdout.write(self.style.SQL_TABLE('sql_table - The name of a model in SQL.'))
        self.stdout.write(self.style.HTTP_INFO('http_info - A 1XX HTTP Informational server response.'))
        self.stdout.write(self.style.HTTP_SUCCESS('http_success - A 2XX HTTP Success server response.'))
        self.stdout.write(self.style.HTTP_NOT_MODIFIED('http_not_modified - A 304 HTTP Not Modified server response.'))
        self.stdout.write(self.style.HTTP_REDIRECT('http_redirect - A 3XX HTTP Redirect server response other than 304.'))
        self.stdout.write(self.style.HTTP_NOT_FOUND('http_not_found - A 404 HTTP Not Found server response.'))
        self.stdout.write(self.style.HTTP_BAD_REQUEST('http_bad_request - A 4XX HTTP Bad Request server response other than 404.'))
        self.stdout.write(self.style.HTTP_SERVER_ERROR('http_server_error - A 5XX HTTP Server Error response.'))
        self.stdout.write(self.style.MIGRATE_HEADING('migrate_heading - A heading in a migrations management command.'))
        self.stdout.write(self.style.MIGRATE_LABEL('migrate_label - A migration name.'))

Reference