Study Notes of Django

  • The model layer
  • The view layer
  • The template layer

[toc]

Project Structure

  • docs: documentation
  • scripts
    • manage.py: installed to PATH via setup.py
  • [project_name]
    • apps: project-specific applications
    • settings: settings for different environments, see below
    • urls.py
    • wsgi.py
  • static: site-specific static files
  • templates: site-specific templates
  • tests: site-specific tests (mostly in-browser ones)
  • tmp: excluded from git
  • setup.py

The model layer

A model is the single, definitive source of information about your data. It contains the essential fields and behaviors of the data you’re storing. Generally, each model maps to a single database table.

  • Each model is a Python class that subclasses django.db.models.Model.
  • Each attribute of the model represents a database field.

Defined the model

1
2
3
4
5
6
7
8
9
from django.db import models

class Person(models.Model):
"""
first_name and last_name are fields of the model.
Each field is specified as a class attribute, and each attribute maps to a database column.
"""
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)

Using models

  • Once you have defined your models, you need to tell Django you’re going to use those models.
  • Do this by editing your settings file and changing the INSTALLED_APPS setting to add the name of the module that contains your models.py.
1
2
3
4
5
INSTALLED_APPS = [
#...
'myapp',
#...
]

Model methods

  • Define custom methods on a model to add custom “row-level” functionality to your objects.
  • Whereas Manager methods are intended to do “table-wide” things, model methods should act on a particular model instance.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
from django.db import models

class Person(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
birth_date = models.DateField()

def baby_boomer_status(self):
"Returns the person's baby-boomer status."
import datetime
if self.birth_date < datetime.date(1945, 8, 1):
return "Pre-boomer"
elif self.birth_date < datetime.date(1965, 1, 1):
return "Baby boomer"
else:
return "Post-boomer"

@property
def full_name(self):
"""
Also known as “managed attributes”, and a feature of Python since version 2.2.
This is a neat way to implement attributes whose usage resembles attribute access,
but whose implementation uses method calls.
"""
"Returns the person's full name."
return '%s %s' % (self.first_name, self.last_name)
  • basic operations
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 增:增加一条数据,可以接受字典类型数据 **kwargs
models.Tb1.objects.create(c1='xx', c2='oo')

# 删:删除指定条件的数据
models.Tb1.objects.filter(name='seven').delete()

# 改:将指定条件的数据更新,均支持 **kwargs
models.Tb1.objects.filter(name='seven').update(gender='0')
obj = models.Tb1.objects.get(id=1)
obj.c1 = '111'
obj.save()

# 查
# 获取单条数据,不存在则报错(不建议)
models.Tb1.objects.get(id=123)
# 获取全部
models.Tb1.objects.all()
# 获取指定条件的数据
models.Tb1.objects.filter(name='seven')
  • Double Underscore
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# Get the number
models.Tb1.objects.filter(name='seven').count()

# Greater than, Less than
models.Tb1.objects.filter(id__gt=1) # Get the value with id greater than 1
models.Tb1.objects.filter(id__lt=10) # Get the value with id less than 1
models.Tb1.objects.filter(id__lt=10, id__gt=1) # Get the value with id greater than 1 and less than 10

# in
models.Tb1.objects.filter(id__in=[11, 22, 33]) # Get data with id equal to 11, 22, 33
models.Tb1.objects.exclude(id__in=[11, 22, 33]) # not in

# contains
models.Tb1.objects.filter(name__contains="ven")
models.Tb1.objects.filter(name__icontains="ven") # icontains: Case-insensitive
models.Tb1.objects.exclude(name__icontains="ven")# Not contain

# range
models.Tb1.objects.filter(id__range=[1, 2]) # bettwen and

# Other similar
# startswith,istartswith, endswith, iendswith

# order by
models.Tb1.objects.filter(name='seven').order_by('id') # asc
models.Tb1.objects.filter(name='seven').order_by('-id') # desc

# limit / offset
models.Tb1.objects.all()[10:20]

# group by

# SELECT "app01_tb1"."id", COUNT("app01_tb1"."num") AS "c"
# FROM "app01_tb1"
# WHERE "app01_tb1"."c1" = 1
# GROUP BY "app01_tb1"."id"

from django.db.models import Count, Min, Max, Sum
models.Tb1.objects.filter(c1=1).values('id').annotate(c=Count('num'))

Making queries

  • Retrieving specific objects with filters

    • The QuerySet returned by all() describes all objects in the database table. Usually, though, you’ll need to select only a subset of the complete set of objects.

    • To create such a subset, you refine the initial QuerySet, adding filter conditions. The two most common ways to refine a QuerySet are:

      • filter(\kwargs)**

        returns a new QuerySet containing objects that match the given lookup parameters.

      • exclude(\kwargs)**

        Returns a new QuerySet containing objects that do not match the given lookup parameters.

    • Field lookups

      Basic lookups keyword arguments take the form field__lookuptype=value. (That’s a double-underscore).

      1
      2
      3
      4
      # Django
      Entry.objects.filter(pub_date__lte='2006-01-01')
      # SQL
      SELECT * FROM blog_entry WHERE pub_date <= '2006-01-01';
    • Filters can reference fields on the model

      1
      2
      3
      4
      5
      6
      7
      8
      9
      # To find all the blog entries with more than twice as many comments as pingbacks, we modify the query:
      Entry.objects.filter(number_of_comments__gt=F('number_of_pingbacks') * 2)

      # To find all the entries where the rating of the entry is less than the sum of the pingback count and comment count:
      Entry.objects.filter(rating__lt=F('number_of_comments') + F('number_of_pingbacks'))

      # An F() object with a double underscore will introduce any joins needed to access the related object.
      # To retrieve all the entries where the author’s name is the same as the blog name:
      Entry.objects.filter(authors__name=F('blog__name'))

The view layer

Writing views

  • A view function, or view for short, is a Python function that takes a Web request and returns a Web response.

  • For the sake of putting the code somewhere, the convention is to put views in a file called views.py, placed in your project or application directory.

  • Simple example

    • The view returns an HttpResponse object that contains the generated response.

    • Each view function is responsible for returning an HttpResponse object.

    • To display this view at a particular URL, you’ll need to create a URLconf; see URL dispatcher for instructions.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #  import the class HttpResponse from the django.http module, along with Python’s datetime library.
    from django.http import HttpResponse
    import datetime

    def current_datetime(request):
    """
    This is the view function.
    We define a function called current_datetime.
    Each view function takes an HttpRequest object as its first parameter, which is typically named request.
    """
    now = datetime.datetime.now()
    html = "<html><body>It is now %s.</body></html>" % now
    return HttpResponse(html)

URL dispatcher

  • To design URLs for an app, you create a Python module informally called a URLconf (URL configuration). This module is pure Python code and is a mapping between URL path expressions to Python functions (your views).

  • How Django processes a request

  • Simple Example

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    from django.urls import path
    from . import views

    # uising path
    urlpatterns = [
    path('articles/2003/', views.special_case_2003), # To capture a value from the URL, use angle brackets.
    path('articles/<int:year>/', views.year_archive), # Captured values can optionally include a converter type.
    path('articles/<int:year>/<int:month>/', views.month_archive),
    path('articles/<int:year>/<int:month>/<slug:slug>/', views.article_detail),
    ]

    # /articles/2003/03/building-a-django-site/ would match the final pattern.
    # Django would call the function views.article_detail(request, year=2003, month=3, slug="building-a-django-site").


    # using re_path
    urlpatterns = [
    path('articles/2003/', views.special_case_2003),
    re_path(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),
    re_path(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.month_archive),
    re_path(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<slug>[\w-]+)/$', views.article_detail),
    ]
  • Path converters

    • str - Matches any non-empty string, excluding the path separator, '/'. This is the default if a converter isn’t included in the expression.
    • int - Matches zero or any positive integer. Returns an int.
    • slug - Matches any slug string consisting of ASCII letters or numbers, plus the hyphen and underscore characters. For example, building-your-1st-django-site.
    • uuid - Matches a formatted UUID. To prevent multiple URLs from mapping to the same page, dashes must be included and letters must be lowercase. For example, 075194d3-6885-417e-a8a8-6c931e272f00. Returns a UUID instance.
    • path - Matches any non-empty string, including the path separator, '/'. This allows you to match against a complete URL path rather than a segment of a URL path as with str.

The template layer

Templates

  • Variables

    • A variable outputs a value from the context, which is a dict-like object mapping keys to values
    • Dictionary lookup, attribute lookup and list-index lookups are implemented with a dot notation
    1
    2
    3
    4
    5
    My first name is {{ first_name }}. My last name is {{ last_name }}.

    {{ my_dict.key }}
    {{ my_object.attribute }}
    {{ my_list.0 }}
  • Tags

    • Tags provide arbitrary logic in the rendering process.
    • This definition is deliberately vague. For example, a tag can output content, serve as a control structure e.g. an “if” statement or a “for” loop, grab content from a database, or even enable access to other template tags.
    1
    2
    3
    {% csrf_token %}
    {% cycle 'odd' 'even' %}
    {% if user.is_authenticated %}Hello, {{ user.username }}.{% endif %}
  • Filters

    • Filters transform the values of variables and tag arguments.
    1
    2
    {{ django|title }}
    {{ my_date|date:"Y-m-d" }}
  • Comments

    1
    {# this won't be rendered #}

Python programmers

  • Overview

    • You configure an Engine.
    • You compile template code into a Template.
    • You render the template with a Context.
  • Loading a template

    1
    2
    3
    from django.template import Template

    template = Template("My name is {{ my_name }}.")
  • Rendering a context

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    >>> from django.template import Context, Template
    >>> template = Template("My name is {{ my_name }}.")

    >>> context = Context({"my_name": "Adrian"})
    >>> template.render(context)
    "My name is Adrian."

    >>> context = Context({"my_name": "Dolores"})
    >>> template.render(context)
    "My name is Dolores."

SOME TIPS

VIEWS

1
2
3
# url: mypage.com/?page=2
request.GET['page'] # That will force get page param, and you will if not found
request.GET.get('page', '1') # Tha will check if param exists, and return 1 if not found
Author

Haojun(Vincent) Gao

Posted on

2020-09-29

Updated on

2022-02-22

Licensed under

Comments