Django JsonResponse, Class-Based Views, and Template Syntax

目录- JsonResponse object

  • Frontend-backend separation
  • CBV and source code analysis
  • CBV: Class-Based Views
  • CBV source code: understanding the flow
  • How CBV automatically executes different methods based on request type
  • Adding decorators to CBV
  • Template syntax
  • Template syntax format
  • Template variable passing
  • Filters
  • Tags
  • For loops
  • If statements
  • Combined usage
  • Iterating over dictionaries
  • Template variable access
  • Custom filters and tags
  • Three preparation steps for customization:
  • Custom filter
  • Using custom filters
  • Custom tag
  • Using custom tags
  • Custom inclusion_tag
  • Using inclusion_tag
  • Template inheritance
  • Template inclusion

JsonResponse Object

  • Essential trio for beginners: HttpResponse, render, redirect
  • View functions must return an HTTPResponse object
  • render: Template + Context
def test(request):
    from django.template import Template, Context
    html_obj = Template('<h1>{{user}}</h1>')
    data_obj = Context({'user': {'user_name': 'jason'}})
    complete_html = html_obj.render(data_obj)
    return HttpResponse(complete_html)


Frontend-Backend Separation

  • Frontend and backend data interaction uses JSON, string-formatted dictionaries
  • Backend implements URL interfaces, frontend accesses these interfaces
  • Backend returns a large dictionary to frontend along with documentation
  • Frontend renders pages based on the dictionary data and documentation
  • Serialization/deserialization methods used by frontend and backend
  • Python backend: json.dumps, json.loads
  • JavaScript frontend: JSON.stringify, JSON.parse
  • Prevent JSON from automatically encoding Chinese characters
  • Method 1: Check json.dumps source code-->find ensure_ascii parameter, set it to False
def test(request):
    import json
    user_dic = {'name': 'Cai Qilong'}
    json_str = json.dumps(user_dic, ensure_ascii=False)  # {"name": "Cai Qilong"}
    return HttpResponse(json_str)  # {"name": "\u8521\u542f\u9f99"}


  • Method 2: Use Django's encapsulated JsonResponse

Check JsonResponse source code-->find json.dumps-->infer json_dumps_params parameter value

def test(request):
    from django.http import JsonResponse
    user_dic = {'name': 'Cai Qilong'}  # {"name": "\u8521\u542f\u9f99"}
    return JsonResponse(user_dic, json_dumps_params={'ensure_ascii': False})  # {"name": "Cai Qilong"}


  • Enable serialization of other data types in JSON

Based on error message, change parameter: safe=False

def test(request):
    from django.http import JsonResponse
    numbers = [1, 2]
    return JsonResponse(numbers, safe=False)  # [1, 2]
# In order to allow non-dict objects to be serialized set the safe parameter to False.


CBV and Source Code Analysis

CBV: Class-Based Views

  • FBV: Function-Based Views
  • FBV implementation: route + view function name, url(r'^index/', views.index)
  • CBV implementation: url(r'^login/', views.MyLogin.as_view()), # Returns view, CBV is essentially FBV, route + function name

CBV Source Code: Understanding the Flow

How CBV Automatically Executes Different Methods Based on Request Type

  • Function name with parentheses has highest execution priority
  • When project starts, as_view method is automatically executed
  • Only understand source code parts you can comprehend, don't get stuck on incomprehensible parts
  1. Execute as_view() method of the class, returns view
  2. When regex matches "login/", execute view()
  3. view() returns dispatch(request, ...)
  4. Execute dispatch(request, ...), which gets the request method string and finds methods in the object through reflection
  5. If found, records the method to handler, if not found, records error function to handler, finally returns handler's execution result, an HttpResponse object
from django.views import View


class MyLogin(View):
    def get(self, request):
        print('MyLogin get method')
        return render(request, 'login.html')

    def post(self, request):
        return HttpResponse('MyLogin post method')


@classonlymethod
def as_view(cls, **initkwargs):
    def view(request, *args, **kwargs):  # Closure function inside as_view
        self = cls(**initkwargs)  # cls is custom MyLogin class, self is instance of custom class
        return self.dispatch(request, *args, **kwargs)

    return view


def dispatch(self, request, *args, **kwargs):
    if request.method.lower() in self.http_method_names:  # Check if current request method is within eight default methods
        handler = getattr(self, request.method.lower(), self.http_method_not_allowed)  # Take get request as example, getattr(obj, 'get')
    else:
        handler = self.http_method_not_allowed  # Call get method
    return handler(request, *args, **kwargs)  # Return result of calling get method, an HttpResponse object


Adding Decorators to CBV

from functools import wraps
import time


def decorator(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        start_time = time.time()
        res = func(*args, **kwargs)
        exec_time = time.time() - start_time
        print('Function execution time: %s' % (exec_time,))
        return res


Method 1: Direct Decoration

'''
@decorator
def get(self, request):
	...
'''


Method 2: Using Built-in Module, Direct decoration on class will cause error: 'function' object has no attribute 'as_view'

from django.utils.decorators import method_decorator

'''
@method_decorator(decorator, name='post')
class MyLogin(View):
	...

@method_decorator(decorator)  # Recommended approach
def get(self, request):
	...
'''



Method 3: Add Decorators to All Methods in Class at Once, If you want to perform operations before view functions execute, you can customize dispatch method in CBV

from django.utils.decorators import method_decorator


@method_decorator(decorator, name='dispatch')
class MyLogin(View):
    def dispatch(self, request, *args, **kwargs):
        return super().dispatch(request, *args, **kwargs)


Template Syntax

Template Syntax Format

Two types: Variable-related {{}}, Logic-related {{%%}}

Template Variable Passing

All basic Python data types are supported

def test(request):
    numbers = [1, 2, 3]
    text = 'hello world'
    file_size = 666666
    html_tag = "<h1>Tag</h1>"
    user_info = {'name': 'jason', 'pwd': '123'}

    def index():
        return 'Index function return value'

    class TestClass:
        pass

    test_obj = TestClass()

    # locals passes all names in current namespace to HTML page
    return render(request, 'test.html', locals())


  • Passing function name: <p>{{ index }}</p>

When passing a function name to HTML page, it automatically calls the function and displays the return value, but doesn't support function parameters

  • Passing class name: Automatically instantiates with parentheses, any callable object passed to HTML page will automaticaly be called with parentheses
'''
<p>{{ TestClass }}</p>
<p>{{ test_obj }}</p>

<app02.views.test.<locals>.TestClass object at 0x0000028D321F9F28>
<app02.views.test.<locals>.TestClass object at 0x0000028D321EAD30>
'''


Filters

Built-in methods provided by template syntax for quick data processing, but最多只能有两个参数

Will pass data to the left of | as first parameter to filter, and data to the right of : as second parameter

  • Count length: <p>{{ numbers|length }}</p>, # 3, Returns 0 if cannot count
  • Addition operation: <p>{{ text|add:'nick' }}</p>, # hello worlnick
  • Slicing: <p>{{ numbers|slice:'0:2:1' }}</p>, # [1, 2], Includes start, excludes end, supports step but not negative indexing
  • Convert to file size format: <p>{{ file_size|filesizeformat }}</p>, # 651.0 KB
  • Truncate text: <p>{{ text|truncatechars:5}}</p>, # he..., Truncates 5 characters, including 3 dots
  • Truncate 5 words, calculated by spaces, 3 dots not counted: truncatewords
  • Check if has value: <p>{{ ''|default:'Default value when empty' }}</p>, # Default value when empty, Shows original value if not empty, shows default if empty
  • Display text with tags:

By default, doesn't automatically convert to HTML tags to prevent malicious attacks

To recognize HTML syntax, can set to escape in frontend or backend

'''
Frontend set to escape
    <p>{{ html_tag }}</p>  # <h1>Tag</h1>
    <p>{{ html_tag|safe }}</p>  # Tag
'''

# Backend set to escape
from django.utils.safestring import mark_safe
safe_tag = mark_safe(html_tag)
# <p>{{ safe_tag }}</p>  # Tag


Tags

Tags refer to logic-related code such as if statements, for loops, etc.

For Loops

'''
forloop object: 
	first/last checks start and end of for loop
	count0, index value starting from 0
	counter, counter for data, e.g., solving non-continuous primary keys

{% for num in numbers %}
    <p>{{ forloop }}</p>
{% endfor %}

{'parentloop': {}, 'counter0': 0, 'counter': 1, 'revcounter': 3, 'revcounter0': 2, 'first': True, 'last': False}
...
'''


If Statements

{% if text %}
    <p>Text has value</p>
 {% else %}
    <p>Text has no value</p>
{% endif %}


Combined Usage

{% for num in numbers %}
    {% if forloop.first %}
        <p>First iteration, number: {{ num }}</p>
    {% elif forloop.last %}
        <p>Last iteration, number: {{ num }}</p>
    {% else %}
        <p>Middle iteration, number: {{ num }}</p>
    {% endif %}
    {% empty %}
        <p>Triggered when for loop object is empty</p>
{% endfor %}


Iterating Over Dictionaries

'''
{% for key in user_info.keys %}
    <p>{{ key }}</p>
{% endfor %}  # name  pwd

{% for value in user_info.values %}
    <p>{{ value }}</p>  # jason  123
{% endfor %}

{% for item in user_info.items %}
    <p>{{ item }}</p>  # ('name', 'jason')  ('pwd', '123')
{% endfor %}
'''


Template Variable Access

Only one way, using dot notation: "."

'''
complex_dict = {'name': 'json', 'hobby': ['read', ['run', {'music': 'if you'}]]}
<p>{{ complex_dict.hobby.1.1.music }}</p>  # if you, Gets music value

# Use alias when copying data access method, but alias can only be used inside with
{% with complex_dict.hobby.1.1.music as music %}
    <p>{{ music }}</p>
{% with %}
'''


Custom Filters and Tags

Custom filters can be used in logical statements, while custom tags cannot, regular tags also use {%%} syntax

Three Preparation Steps for Customization:

  1. Create a folder named templatetages under the app directory
  2. Create any .py file in that folder
  3. Add two lines of code in the .py file: from django.template import Library, register = Library()

Custom Filter:

# Custom filter
@register.filter(name='division')
def handle(x, y):  # Same as default filter, max two parameters
    return x / y


Using Custom Filter

First need to load the filter file, similar to import

{% load custom_filters_tags %}
{{ 1|division:10 }}


Custom Tag

Can receive any number of parameters

# Custom tag
@register.simple_tag(name='my_tag')
def handle(a, b, c):
    return '%s?%s?%s' % (a, b, c)


Using Custom Tag

Multiple parameters must be separated by spaces

'''
{% load custom_filters_tags %}
{% my_tag 'c' 'q' 'l' %}  # c?q?l
'''


Custom inclusion_tag

  1. Is a function that can recieve parameters from outside and pass them to an HTML fragment
  2. That HTML fragment gets data and renders
  3. Finally returns the rendered HTML fragment to where inclusion_tag was called
# Custom inclusion_tag
@register.inclusion_tag('part_html.html')
def inclusion_tag(n):
    items = []
    for i in range(n):
        items.append('Item %s' % (i,))
    return locals()  # Passes items to HTML fragment


Using inclusion_tag, Important

Use case: When needing to use page components that require parameter dynamic rendering

'''
part_html.html:
<ul>
    {% for ele in items %}
        <li>{{ ele }}</li>
    {% endfor %}
</ul>

test.html:
{% load custom_filters_tags %}
{% inclusion_tag 3 %}
'''


Template Inheritance

Need to define areas on the HTML page that will be used in advance. After inheritance, only these defined areas can be modified, otherwise no content can be changed

Typically at least three areas: HTML code area, CSS area, JS area

  1. Define areas on parent page using block template syntax
  2. Inherit parent page on child page using extends template syntax
  3. Use block template syntax on child page to select areas to modify
{% extends 'test.html' %}

{% block css %}
    <style>
        h1 {
            color: red;
        }
    </style>
{% endblock %}

{% block content %}
    <h1>Login Page</h1>
    {{ block.super }}  {#    Use parent page content in child page#}
{% endblock %}

{% block js %}
    <script>
        alert(123)
    </script>
{% endblock %}


Template Inclusion

Import an HTML fragment as a module

Difference from inclusion_tag:

  • Template inclusion is static, doesn't support parameters,
  • While inclusion_tag supports parameters, can dynamically render HTML fragments based on different parameters
'''
test111.html:
	<h1>This is a beautiful form</h1>

{% block content %}
    {% include 'test111.html' %}
{% endblock %}
'''


Tags: Django json-response class-based-views template-syntax

Posted on Sat, 24 Oct 2026 16:48:23 +0000 by ndjustin20