This article is participating in Python Theme Month. See the link to the event for more details

Rest cannot be enjoyed by lazy people.~

preface

The data generated in a project usually changes, so the data presented to the user on the front page of a full-stack project should also be dynamically generated data from the back end, so how the data generated in the back end is transmitted to the front end and how the front end receives and renders the data sent from the back end is part of the topic of this article. All three of these problems can be solved using Django’s template language, so let’s take a look

Tips

There are two types of template syntax: {{}} and {% %}. Django template syntax is a fixed format and can only be used. I’m going to value it. You can also click on.key:

{{}}   # Variable related, used to receive data passed from the back end, filters, custom filters
{% %}   # Logically related, used in tags (if for loop), custom tags simple_tag, inclusion_tag, template inheritance extend, and import include
<p>{{ d.key }}</p>	The dictionary uses point-key mode
<p>{{ my_str. 0 }}</p>  # String is indexed by points
<p>{{ l. 0 }}</p>			# Lists are indexed by points
<p>{{ obj.get_class }}</p>		# Object points to properties or methods
Copy the code

How can back-end data be transmitted to the front end

The first thing you need to know is how the back end passes data to the front end or what data types can the Django back end pass to the front end? Support is provided for both Python’s basic data types and Python’s functions, classes, and objects when passing values.

Basic data type

The basic data types in Python are passed to the front end, and the front end can be rendered. The basic data types include STR, int, float, bool, set, dict, list, tuple. The way the back end of a Django project passes data to an HTML page is very simple. Return the page in the view function and return the data required by the front end. There are two ways to achieve this, bosses can choose:

The value is passed in dictionary mode

In this way, the forward end to pass the value, only the front end needs the data to the front end page, the disadvantage is too troublesome, the front end to get the value of the variable passed by the back end is through the key of the dictionary to get.

# views.py
def index(request) :
    my_str = 'string'
    my_int = 11
    my_list = [1.2.3]
    my_tup = (1.2.3)
    my_dic = {'name': 'python'.'age': 18}
    my_set = {1.3.4}
    my_bool = True
    my_float = 11.11
    return_dic = {
        'str': my_str,
        'int': my_int,
        'list': my_list,
        'dict': my_dic,
        'tuple': my_tup,
        'set': my_set,
        'bool': my_bool,
        'float': my_float,
    }
    return render(request, 'render_html.html', return_dic)

# render_html.html
<body>
    {{ str }}
    {{ int }}
    {{ list }}
    {{ dict }}
    {{ tuple }}
    {{ set }}
    {{ bool }}
    {{ float }}
</body>
Copy the code

locals()

Locals () passes all variables from the back-end view functions to the front page. The advantage of locals() is that some data may not be needed by the front end. This is recommended as a convenient way to get the value passed from the back end and value it directly by the original variable name.

# views.py
def index(request) :
    my_str = 'string'
    my_int = 11
    my_list = [1.2.3]
    my_tup = (1.2.3)
    my_dic = {'name': 'python'.'age': 18}
    my_set = {1.3.4}
    my_bool = True
    my_float = 11.11
    return render(request, 'render_html.html'.locals())

# render_html.html
<body>
    {{ my_str }}
    {{ my_int }}
    {{ my_list }}
    {{ my_tup }}
    {{ my_dic }}
    {{ my_set }}
    {{ my_bool }}
    {{ my_float }}
</body>
Copy the code

Object by value

Template syntax also supports passing functions, classes, and objects from the back end to the front;

If you pass a function name, the front end automatically calls the function in parentheses and returns the value of that function, but the template syntax does not support passing parameters to functions.

If the class name is passed, the front end directly instantiates the type corresponding to the back end as an object and prints the object on the front end page, returning the value of the __str__ method if the object has one.

If an instantiated object is passed and the object has a __call__ method, that is, if the object can be called in parentheses, the return value from __call__ is executed first; If there is no such method, the object is printed directly again.

# views.py
from django.shortcuts import render

# Create your views here.
def index(request) :

    def func() :
        print('I am the func)
        return 'func'

    class Class() :
        def get_self(self) :
            return 'self'

        @staticmethod
        def static() :
            return 'static'

        @classmethod
        def class_method(cls) :
            return cls
        Print class/object is automatically triggered, instead of the object's memory address
        def __str__(self) :
            return 'Who am I? '
    obj = Class()
    return render(request,'data.html'.locals())

# data.html< p > the transfer function, will be the backend function automatically add parentheses calls, get the function return value, but the template syntax doesn't support to the function parameter < / p > < p > the name of the class will also automatically add parentheses calls, namely instantiation < / p > < p > template syntax can automatically determine the current internal variable name call whether can add parentheses, If it can be done automatically, Is aimed at the function name and the name of the Class < / p > < p > {{func}} {{Class}} < / p > < p > {{obj}} < / p > < p > {{obj. Get_self}} < / p > < p > {{obj. Static}} < / p > < p > {{ obj.class_method}}</p>Copy the code

Filter filters

In Django template language, display can change variables through the filter, filter is similar to the template syntax built-in built-in method, similar with the back-end data types of built-in methods, basic syntax for {{data | filter: parameters}}, the parameter is optional, two parameters before and after the pipeline operator | respectively, Filters support chaining, where the output of one filter can be used as input to another. There are more than 60 filters built into Django. Here are some of the most common ones.

<! -- Common filters -->
<p>Statistical length {{my_str | length}}</p>
<p>The default value, if the Boolean is True, the default value is True, or show the value of the colon {{my_bool | default: 'nothing'}}</p>
<p>File size: {{file_size | filesizeformat}}</p>
<p>The date format: {{current_time | date: 'Y -m - d H: I: s'}}</p>
<p>Slicing operation, support the step length, head regardless of tail {{my_list | slice: '0:2:1'}}</p>
<p>This paper consists of three points (for example, the nuggets articles) {{info | truncatechars: 9}}</p>
<p>Cut out words, do not include three points, it will only according to the space segmentation word {{egn | truncatewords: '9'}}</p>
<p>To remove specific characters {{MSG | the cut: "'}}</p>
<p>Concatenation operation {{my_str | join: '@'}}</p>
<p>Add operation (concatenation operation) {{my_int | add: 12}}</p>
<p>Add operation (concatenation operation) {{my_str | add: '12'}}</p>

Copy the code

In writing the whole stack project, front-end code writing, not necessarily in the front page can also be written on the back end, and then passed to the front, the front is required to the back-end of variables to escape, you need to use safe filter, the filter means tell HTML document pass back end tag is safe to render.

<! -- Backend code -->
def index(request):
	h = '<h1>I'm an HTML tag</h1>'
	return render(request, 'render_html.html', locals())

<! -- Front end escape, filter means to tell the browser that the label written back end is safe and can be rendered -->
{{h|safe}}
Copy the code

At the same time, the back end can also be directly labeled strings into front-end code, and the front-end can be used directly through the template syntax.

<! From Django.utils. Safestring import mark_safe def index(request): S = '<h1> back end escape </h1>' res = mark_safe(s) return(request, 'render_html.html', locals()) <! -- code --> {{res}}Copy the code

The label

The tag is not the tag in the HTML document, but a bunch of logic in the template syntax that can be used to process the data passed from the back end to the front end.

Front page for loop

There are two ways to use a template language for looping data on a front page. One is to directly loop out each element of the object to be looping, as in Python, or the other is to get information about each element through a forloop. The template syntax for the for loop is as follows:

{% endfor %} {% endfor %} {% endfor %} {% endfor %} {% endfor %}Copy the code

As follows:

# views.py
from django.shortcuts import render


# Create your views here.
def index(request) :
    my_str = 'string'
    my_dic = {'name': 'python'.'age': 18}
    my_list = []
    return render(request, 'render_html.html'.locals())
Copy the code
<! --render_html.html-->
<body>
    <p>I is the element value for each loop, and the forloop for each loop is the details of each element</p>
    {% for i in my_str %}
        <p>{{ i }}, {{ forloop }}</p>
    {% endfor %}
    {% for i in my_list %}
    	<p>I will not be executed</p>
    	{% empty %}
    		<p>Because my_list is empty, so I'm going to get executed</p>
    {% endfor %}
    <! -- The for loop handles dictionaries much like the Python back end -->
    {% for foo in my_dic.keys %}
        <p>{{ foo }}</p>
    {% endfor %}

    {% for foo in my_dic.values %}
        <p>{{ foo }}</p>
    {% endfor %}

    {% for foo in my_dic.items %}
        <p>{{ foo }}</p>
    {% endfor %}
    
</body>-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- page results are as follows -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- s, {' parentloop: {}, 'counter0' : 0, 'counter': 1, 'revcounter': 6, 'revcounter0': 5, 'first': True, 'last': False} t, {'parentloop': {}, 'counter0': 1, 'counter': 2, 'revcounter': 5, 'revcounter0': 4, 'first': False, 'last': False} r, {'parentloop': {}, 'counter0': 2, 'counter': 3, 'revcounter': 4, 'revcounter0': 3, 'first': False, 'last': False} i, {'parentloop': {}, 'counter0': 3, 'counter': 4, 'revcounter': 3, 'revcounter0': 2, 'first': False, 'last': False} n, {'parentloop': {}, 'counter0': 4, 'counter': 5, 'revcounter': 2, 'revcounter0': 1, 'first': False, 'last': False} g, {'parentloop': {}, 'counter0': 5, 'counter': 6, 'revcounter': 1, 'revcounter0': 0, 'first': False, 'last': True} ...... -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- the results analysis -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- each row is the first element of the for loop after I value; The dictionary at the end of each row is forloop, with details of each element, which means: Counter0: the index is calculated from zero, the current element's index counter: Revcounter: Evaluates the index from 1 and reverses the value of the current element revCounter0: evaluates the index from 0 and reverses the value of the current element first: Indicates whether the current element is the first element. Last: indicates whether the current element is the last elementCopy the code

If judgment

The if judgment in the template syntax is similar to the if judgment in Python, and supports and, OR, ==, >, <,! =, <=, >=, in, not in, IS, is not judgment.

<body>{% endif %} {% endif %} my_bool {% elif False %}</body>
Copy the code

With names

In the with syntax, you can quickly use aliases after as to retrieve data in a very complicated way, that is, to alias complex variables, such as:

from django.shortcuts import render


# Create your views here.
def index(request) :
    my_dic = {
        'name': 'python'.'age': 18.'hobby': ['study'.'play']}return render(request, 'render_html.html'.locals())
Copy the code
<body>{% with my_dic. Hobby.0 as myhobby %} with syntax {{my_dic. Hobby.0}} {% endwith %}</body>
Copy the code

Customize filters & tags &inclusion_tag

Customizing filters, customizing tags, and customizing inclusion_tag are the same three steps in the customization process:

(1) Create a folder in the application with the name templateTags;

② Create a py file of any name in this folder;

③ The following two lines of code must be written in the py file;

from django import template


register = template.Library()
Copy the code

Custom filter

A custom filter needs to be defined in the py file created in the TemplateTags directory. The filter functions are the same as the built-in filter, which receives and processes data from the view function. If the built-in filter does not meet the requirements, you can use a custom filter. Note that a custom filter can only take two parameters at most. For example, define a filter that evaluates the sum of two elements:

# templatetags/my_filter.py
from django import template


register = template.Library()
@register.filter(name='sum')  # name= Name of the custom filter
# Filter function
def my_sum(v1, v2) :  # Filter receives two parameters
    return v1 + v2
Copy the code

To use a custom filter in an HTML document, load it as follows:

<body>
{% load sum %}  <! -- load custom filter first -->
{{ my_int }}
{{ my_int|my_sum:666 }}  
</body>
Copy the code

Custom tags

Also need to create py in templatetags directory file, can use the same py files and custom filters, but suggested that separate convenient management, front page calls a custom tag for data processing, if the template syntax in existing label does not meet the logic to handle the data can be custom tag to deal with data. For example, the following custom tags:

# templatetags/my_tag.py
from django import template

register = template.Library()
# Custom tag, can have more than one parameter
@register.simple_tag(name='my_tag')  # name= the name of the custom tag
def index(a,b,c) :
    return f'{a}{b}{c}'
Copy the code

To use a custom tag in an HTML document, you first need to load the file where the custom tag is located. The method is as follows:

<body>
{% load my_tag %}
<! -- Custom tag use syntax: {% tag name parameter 1 parameter 2 parameter 3.... %}, label multiple parameters separated by Spaces -->
{% my_tag 'a' 'b' 'c' 'd' %}
</body>
Copy the code

Custom inclusion_tag

Customizing inclusion_tag is a little more complicated. Here’s how it works:

First, create a py file in the TemplateTags directory and define the method. When you define the method, you specify which HTML document to pass the data returned by the method, such as a.html;

Call the method in an HTML document, such as B.HTML, and pass a value to the method when called.

A custom method will receive the data from b. HTML and return the result to the HTML page a.HTML specified when defining the method.

Finally, place the rendered A.HTML page where the B.HTML called the custom method.

B: well… I also feel a little convoluted, or draw a picture to explain it again ~

** Consider using inclusion_tag when you need to pass parameters in one part of the HTML page to render dynamically and when you need to use that part of the page on multiple pages. ** The specific use mode is as follows:

# templatetags/my_inclusion_tag.py
from django import template

register = template.Library()


@register.inclusion_tag(filename='local.html'The name ='my_inclusion')  If you do not specify a name, write the name of the function when you call inclusion_tag in the page
def test(n) :
    data = ['Item {}'.format(i) for i in range(n)]
    return locals(a)Copy the code
<! --local.html, inclusion_tag -->
{% for i in data %}
    <li>{{ i }}</li>
{% endfor %}
Copy the code
<! --render_html.html, call the inclusion_tag page -->
<body>
{% load my_inclusion_tag %}  <! Start with inclusion_tag-->
{% my_inclusion 5 %}  <! -- call inclusion_tag with {% custom inclusion_tag parameter %}-->
</body>
Copy the code

Page template inheritance

Do not know to have careful friend find actually a lot of web page changes not all are changing, but only partial changes, is only part of the change in order to achieve the page can be achieved by template inheritance, such as the Denver nuggets of the navigation bar no matter which page navigation bar will not change, the effect can be used to page template inheritance. Implementing template inheritance can be broken down into the following steps:

The first step is to select a template page that will be inherited from other pages.

The second step is to clear the HTML document of the other pages that inherit the template page, because this page is no longer a whole page, but a local page, called a child page, on which you need to write the following code;

{% extends' name of template page '%}<! This line of code is meant to inherit all content on the template page.
Copy the code

The third step, delimit the area that can be modified on the template page, delimit the way as the following code:

<! -- Template page -->{% endblock%} {% endblock%}}Copy the code

Step 4: Declare on the subpage that you want to modify the content on the template page:

{% endblock%} {% endblock%}}Copy the code

In addition, it should be added that generally the template page should have at least three areas that can be modified, which are:

  • The CSS area is in the head tag
  • HTML area
  • The js area is placed at the bottom of the page

So template page will need to have three can be drawn in the changes, so that each child page can have their own unique js and CSS code, but it is important to note that in general the more defined area on a page template, then the template of extensibility is higher, but also not draw too much area:

<! -- Template page -->
<! DOCTYPEhtml>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    {% block css %}
    <style></style>
	{% endblock %}
</head>
<body>
    <p>I can't change it</p>{% endblock %} {% endblock %}</body>
    
{% block js %}
    <script></script>
{% endblock %}
    
</html>
Copy the code

Template to import

In addition to inheritance, template can also import a certain page (local page) as a module, which page needs to be directly imported, as shown in the following code:

Syntax: {% include 'Name of the page to be imported '%} {% include 'mu.html' %}Copy the code

conclusion

The article was first published in the wechat public account program Yuan Xiaozhuang, synchronized with nuggets.

Please explain where it came from. If you pass by, please put out your cute little finger and click like before you go (╹▽╹)