• web框架django第二天


    ###URL配置 settings.py
    * ROOT_URLCONF = 'mysite.urls'
    
    
    ###url转换(静态路由)
    * from django.urls import path, re_path
    * re_path(r'^add_book/$', views.add_book)
        * 浏览器访问 http://127.0.0.1:8000/add_book/
    * re_path(r'^book/add/$', views.add_book)
        * 浏览器访问 http://127.0.0.1:8000/book/add/
        
    * r'原生字符串' 
        * 不需要转义
    * 建议都写上$符号  
        * 防止url匹配问题
    * ^以什么开头,不需要添加/,系统会自动重定向
        * settings.py 配置文件
            * APPEND_SLASH = True  # 默认
            
      
    ###动态路由(正则表达式)
    * re_path(r'^blog/d{4}/$', views.blog)
        * 浏览器访问 http://127.0.0.1:8000/blog/1234/
            
          
    ###分组匹配
    * re_path(r'^blog/(d{4})/$', views.blog)
    * views.py 按照位置参数传递给函数
    ```python
    def blog(request, year):
        print(year, type(year))
        return HttpResponse('ok')
    ```
    
    
    ###分组命名匹配
    * urls.py
    ```python
    re_path(r'^blog/(?P<year>d{4})/$', views.blog)
    ```
    
    * views.py 按照关键字参数传递给函数
    ```python
    def blog(request, year):
        print(year, type(year))
        return HttpResponse('ok')
    ```
    
    
    ###视图函数中指定默认值
    * urls.py
    ```python
    re_path(r'^blog/$', views.blog)
    re_path(r'^blog/page(?P<num>d+)/$', views.blog)
    ```
    
    * views.py
    ```python
    def blog(request, num='1'):
        return HttpResponse('ok')
    ```
    
    
    ###include其他的URLconfs
    * urls.py
    ```python
    from django.urls import path, re_path, include
    re_path(r'^app01/', include('app01.urls')),
    ```
    
    * app01/urls.py
    ```python
    re_path(r'^blog/$', views.blog)
    ```
    
    * 浏览器访问 http://127.0.0.1:8000/app01/blog/
    
    
    ###使用最新版本的django2.2.3报错(使用HttpResponse时,添加encode('utf8'))
    * 报错信息
    ```python
    Traceback (most recent call last):
      File "G:python3.6libsocketserver.py", line 654, in process_request_thread
        self.finish_request(request, client_address)
      File "G:python3.6libsocketserver.py", line 364, in finish_request
        self.RequestHandlerClass(request, client_address, self)
      File "G:python3.6libsocketserver.py", line 724, in __init__
        self.handle()
      File "G:python3.6libsite-packagesdjangocoreserversasehttp.py", line 171, in handle
        self.handle_one_request()
      File "G:python3.6libsite-packagesdjangocoreserversasehttp.py", line 194, in handle_one_request
        handler.run(self.server.get_app())
      File "G:python3.6libwsgirefhandlers.py", line 144, in run
        self.close()
      File "G:python3.6libsite-packagesdjangocoreserversasehttp.py", line 111, in close
        super().close()
      File "G:python3.6libwsgirefsimple_server.py", line 35, in close
        self.status.split(' ',1)[0], self.bytes_sent
    AttributeError: 'NoneType' object has no attribute 'split'
    ```
        * return HttpResponse('ok'.encode('utf8'))  # 就不会报错了
    
    
    ###传递额外的参数给视图函数
    * urls.py
    ```python
    re_path(r'^blog/(?P<year>d{4})/$', views.blog, {'month': '12'})
    ```
    
    * views.py
    ```python
    def blog(request, *args, **kwargs):
        print(args)  # ()
        print(kwargs)  # {'year': '1234', 'month': '12'}
        return HttpResponse('ok'.encode('utf8')) 
    ```
    
    * 浏览器访问 http://127.0.0.1:8000/blog/1234/
    * 如果位置参数或关键字参数和后面额外传递的字典里的参数同名,则会被后面的字典里的参数替换
    
    
    ###URL命名和URL反向解析
    * urls.py
    ```python
    re_path(r'^book/add/$', views.add_book, name='add_book')
    ```
    
    * 模板文件
    ```html
    <a href="{% url 'add_book' %}">添加书名</a>
    ```
    
    * views.py视图函数
    ```python
    from django.shortcuts import render, redirect, HttpResponse, reverse
    return redirect(reverse('app01:add_book'))
    ```
    
    
    ###URL命名和URL反向解析(分组)
    * urls.py
    ```python
    re_path(r'^blog/(d{4})/$', views.blog, name='blog')
    ```
    
    * 模板文件
    ```html
    <a href="{% url 'blog' 2014 %}">添加书名</a>
    ```
    
    * views.py视图函数
    ```python
    from django.shortcuts import render, redirect, HttpResponse, reverse
    return redirect(reverse('blog', args=('2019',)))
    ```
    
    
    ###URL命名和URL反向解析(分组命名)
    * urls.py
    ```python
    re_path(r'^blog/(?P<year>d{4})/$', views.blog, name='blog')
    ```
    
    * 模板文件
    ```html
    <a href="{% url 'blog' year=2016 %}">添加书名</a>
    ```
    
    * views.py视图函数
    ```python
    from django.shortcuts import render, redirect, HttpResponse, reverse
    return redirect(reverse('blog', kwargs={'year': '2019'}))
    ```
    
    
    ###命名空间模式
    * urls.py
    ```python
    re_path(r'^app01/', include('app01.urls', namespace='app01')),
    re_path(r'^app02/', include('app02.urls', namespace='app02')),
    ```
    
    * 报错
    ```python
    Watching for file changes with StatReloader
    Exception in thread django-main-thread:
    Traceback (most recent call last):
      File "G:python3.6lib	hreading.py", line 916, in _bootstrap_inner
        self.run()
      File "G:python3.6lib	hreading.py", line 864, in run
        self._target(*self._args, **self._kwargs)
      File "G:python3.6libsite-packagesdjangoutilsautoreload.py", line 54, in wrapper
        fn(*args, **kwargs)
      File "G:python3.6libsite-packagesdjangocoremanagementcommands
    unserver.py", line 117, in inner_run
        self.check(display_num_errors=True)
      File "G:python3.6libsite-packagesdjangocoremanagementase.py", line 390, in check
        include_deployment_checks=include_deployment_checks,
      File "G:python3.6libsite-packagesdjangocoremanagementase.py", line 377, in _run_checks
        return checks.run_checks(**kwargs)
      File "G:python3.6libsite-packagesdjangocorechecks
    egistry.py", line 72, in run_checks
        new_errors = check(app_configs=app_configs)
      File "G:python3.6libsite-packagesdjangocorechecksurls.py", line 40, in check_url_namespaces_unique
        all_namespaces = _load_all_namespaces(resolver)
      File "G:python3.6libsite-packagesdjangocorechecksurls.py", line 57, in _load_all_namespaces
        url_patterns = getattr(resolver, 'url_patterns', [])
      File "G:python3.6libsite-packagesdjangoutilsfunctional.py", line 80, in __get__
        res = instance.__dict__[self.name] = self.func(instance)
      File "G:python3.6libsite-packagesdjangourls
    esolvers.py", line 579, in url_patterns
        patterns = getattr(self.urlconf_module, "urlpatterns", self.urlconf_module)
      File "G:python3.6libsite-packagesdjangoutilsfunctional.py", line 80, in __get__
        res = instance.__dict__[self.name] = self.func(instance)
      File "G:python3.6libsite-packagesdjangourls
    esolvers.py", line 572, in urlconf_module
        return import_module(self.urlconf_name)
      File "G:python3.6libimportlib\__init__.py", line 126, in import_module
        return _bootstrap._gcd_import(name[level:], package, level)
      File "<frozen importlib._bootstrap>", line 994, in _gcd_import
      File "<frozen importlib._bootstrap>", line 971, in _find_and_load
      File "<frozen importlib._bootstrap>", line 955, in _find_and_load_unlocked
      File "<frozen importlib._bootstrap>", line 665, in _load_unlocked
      File "<frozen importlib._bootstrap_external>", line 678, in exec_module
      File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
      File "G:2019老男孩周末26期day15课下练习mysite_day15mysite_day15urls.py", line 22, in <module>
        re_path(r'^app01/', include('app01.urls', namespace='app01')),
      File "G:python3.6libsite-packagesdjangourlsconf.py", line 39, in include
        'Specifying a namespace in include() without providing an app_name '
    django.core.exceptions.ImproperlyConfigured: Specifying a namespace in include() without providing an app_name is not supported. Set the app_name attribute in the included module, or pass a 2-tuple containing the list of patterns and app_name instead.
    ```
    
    * 解决方法 urls.py
    ```python
    from django.urls import path, re_path, include
    re_path(r'^app01/', include(('app01.urls', 'app01'), namespace='app01')),
    re_path(r'^app02/', include(('app02.urls', 'app02'), namespace='app02')),
    ```
    
    * app01/urls.py
    ```python
    from django.urls import path, re_path
    from app01 import views
    
    urlpatterns = [
        path('admin/', admin.site.urls),
        re_path(r'^home/$', views.home, name='home'),
    ]
    ```
    
    * app02/urls.py
    ```python
    from django.urls import path, re_path
    from app02 import views
    
    urlpatterns = [
        path('admin/', admin.site.urls),
        re_path(r'^home/$', views.home, name='home'),
    ]
    ```
    
    * app01/views.py
    ```python
    def home(request):
        return render(request, 'app01home.html')
    ```
    
    * app02/views.py
    ```python
    def home(request):
        return render(request, 'app02home.html')
    ```
    
    * app01home.html
    ```html
    <a href="{% url 'app01:home' %}">app01家目录</a>
    <a href="{% url 'app02:home' %}">app02家目录</a>
    ```
    
    -----------------------------------------------------------------------------------
    ###返回当前日期和时间的视图
    ```python
    import datetime
    
    def current_datetime(request):
        current_time = datetime.datetime.now()
        return HttpResponse('<html><body>current time: %s</body></html>' % current_time)
    ```
    
    
    ###FBV基于函数的视图(Function Base View)
    * mysite/urls.py 开始路由文件
    ```python
    from django.urls import path, re_path, include
    
    urlpatterns = [
        path('admin/', admin.site.urls),
        re_path(r'^app02/', include(('app02.urls', 'app02'), namespace='app02')),
    ]
    ```
    
    * app02/urls.py 命名空间app02路由文件
    ```python
    from app02 import viewsre_path(r'^class/add/$', views.add_class, name='add_class'),
    ```
    
    * app02/views.py 视图文件
    ```python
    from django.shortcuts import render, HttpResponse, redirect, reverse
    
    def add_class(request):
        if request.method == "POST":
            # 接收请求参数,添加到数据库
            return redirect(reverse('app01:home'))
        return render(request, 'add_class.html')
    ```
    
    
    ###CBV基于类的视图(Class Base View)
    * mysite/urls.py 开始路由文件
    ```python
    from django.urls import path, re_path, include
    
    urlpatterns = [
        path('admin/', admin.site.urls),
        re_path(r'^app01/', include(('app01.urls', 'app01'), namespace='app01')),
    ]
    ```
    
    * app01/urls.py 命名空间app01路由文件
    ```python
    urlpatterns = [
        path('admin/', admin.site.urls),
        re_path(r'^class/add/$', views.AddClasses.as_view(), name='add_class'),
    ]
    ```
    
    * app01/views.py 视图文件
    ```python
    from django.shortcuts import render, redirect, HttpResponse, reverse
    from django.views import View
    
    class AddClasses(View):
        def get(self, request):
            return render(request, 'add_class.html')
    
        def post(self, request):
            # 接收请求参数,添加到数据库
            return redirect(reverse('app01:home'))
    ```
    
    
    ###给视图加装饰器
    * 使用装饰器装饰FBV app02/views.py
    ```python
    from django.shortcuts import render, HttpResponse, redirect, reverse
    import time
    
    def wrapper(func):
        def inner(*args, **kwargs):
            start_time = time.time()
            # 执行被装饰函数前增加的逻辑
            ret = func(*args, **kwargs)
            # 执行被装饰函数后增加的逻辑
            print('used: %s' % (time.time() - start_time))
            return ret
        return inner
        
    
    @wrapper
    def add_class(request):
        if request.method == "POST":
            # 接收请求参数,添加到数据库
            return redirect(reverse('app02:home'))
        return render(request, 'add_class.html')
    ```
    
    * 使用装饰器装饰CBV app01/views.py 方法一(分别加在每个请求方法上)
    ```python
    from django.shortcuts import render, redirect, HttpResponse, reverse
    from django.utils.decorators import method_decorator
    from django.views import View
    import time
    
    
    def wrapper(func):
        def inner(*args, **kwargs):
            start_time = time.time()
            # 执行被装饰函数前增加的逻辑
            ret = func(*args, **kwargs)
            # 执行被装饰函数后增加的逻辑
            print('used: %s' % (time.time() - start_time))
            return ret
        return inner
        
    
    class AddClasses(View):
        @method_decorator(wrapper)
        def get(self, request):
            return render(request, 'add_class.html')
    
        @method_decorator(wrapper)
        def post(self, request):
            # 接收请求参数,添加到数据库
            return redirect(reverse('app01:home'))
    ```
    
    * 使用装饰器装饰CBV app01/views.py 方法二(加在dispatch方法上)
    ```python
    from django.shortcuts import render, redirect, HttpResponse, reverse
    from django.utils.decorators import method_decorator
    from django.views import View
    import time
    
    
    def wrapper(func):
        def inner(*args, **kwargs):
            start_time = time.time()
            # 执行被装饰函数前增加的逻辑
            ret = func(*args, **kwargs)
            # 执行被装饰函数后增加的逻辑
            print('used: %s' % (time.time() - start_time))
            return ret
        return inner
        
    
    class AddClasses(View):
        @method_decorator(wrapper)
        def dispatch(self, request, *args, **kwargs):
            return super().dispatch(request, *args, **kwargs)
    
        def get(self, request):
            return render(request, 'add_class.html')
    
        def post(self, request):
            # 接收请求参数,添加到数据库
            return redirect(reverse('app01:home'))
    ```
    
    
    * 使用装饰器装饰CBV app01/views.py 方法三(加在类上[请求方法])
    ```python
    from django.shortcuts import render, redirect, HttpResponse, reverse
    from django.utils.decorators import method_decorator
    from django.views import View
    import time
    
    
    def wrapper(func):
        def inner(*args, **kwargs):
            start_time = time.time()
            # 执行被装饰函数前增加的逻辑
            ret = func(*args, **kwargs)
            # 执行被装饰函数后增加的逻辑
            print('used: %s' % (time.time() - start_time))
            return ret
        return inner
        
    
    @method_decorator(wrapper, name='post')
    @method_decorator(wrapper, name='get')
    class AddClasses(View):
        def get(self, request):
            return render(request, 'add_class.html')
    
        def post(self, request):
            # 接收请求参数,添加到数据库
            return redirect(reverse('app01:home'))
    ```
    
    * 使用装饰器装饰CBV app01/views.py 方法二(加在dispatch方法上)
    ```python
    from django.shortcuts import render, redirect, HttpResponse, reverse
    from django.utils.decorators import method_decorator
    from django.views import View
    import time
    
    
    def wrapper(func):
        def inner(*args, **kwargs):
            start_time = time.time()
            # 执行被装饰函数前增加的逻辑
            ret = func(*args, **kwargs)
            # 执行被装饰函数后增加的逻辑
            print('used: %s' % (time.time() - start_time))
            return ret
        return inner
        
    
    class AddClasses(View):
        @method_decorator(wrapper)
        def dispatch(self, request, *args, **kwargs):
            return super().dispatch(request, *args, **kwargs)
    
        def get(self, request):
            return render(request, 'add_class.html')
    
        def post(self, request):
            # 接收请求参数,添加到数据库
            return redirect(reverse('app01:home'))
    ```
    
    
    * 使用装饰器装饰CBV app01/views.py 方法四(加在类上[dispatch方法])
    ```python
    from django.shortcuts import render, redirect, HttpResponse, reverse
    from django.utils.decorators import method_decorator
    from django.views import View
    import time
    
    
    def wrapper(func):
        def inner(*args, **kwargs):
            start_time = time.time()
            # 执行被装饰函数前增加的逻辑
            ret = func(*args, **kwargs)
            # 执行被装饰函数后增加的逻辑
            print('used: %s' % (time.time() - start_time))
            return ret
        return inner
        
    
    @method_decorator(wrapper, name='dispatch')
    class AddClasses(View):
        def get(self, request):
            return render(request, 'add_class.html')
    
        def post(self, request):
            # 接收请求参数,添加到数据库
            return redirect(reverse('app01:home'))
    ```
    
    
    ###框架
    * MVC框架(Model模型 View视图 Controller控制器)
        * 耦合性低,重用性高,生命周期成本低等优点,重视结果
     
    * MTV框架(Model模型 Template模板 View视图)
        * 重视过程
    
    * ORM对象关系映射(Object Relational Mapping)
    
    
    ###request对象
    * app02/views.py
    ```python
    from django.shortcuts import render, HttpResponse, redirect, reverse
    import datetime
    
    def current_datetime(request):
        print("path_info:", request.path_info)  # /app02/now/ 返回用户访问url,不包括域名
        print("method:", request.method)  # GET
        print("POST:", request.POST)  # <QueryDict: {}>
        print("GET:", request.GET)     # <QueryDict: {}>
        print("body:", request.body)  # b''
        print("scheme:", request.scheme)  # http或https
        print("path:", request.path)  # 同path_info
        print("session:", request.session)
        print("COOKIES:", request.COOKIES)
        print("FILES:", request.FILES)  # 文件
        print("META:", request.META)  # 请求头
        print("get_host:", request.get_host())
        print("get_full_path:", request.get_full_path())
        print("is_ajax:", request.is_ajax())
        current_time = datetime.datetime.now()
        return HttpResponse('<html><body>current time: %s</body></html>' % current_time)
    ```
    
    
    ###JsonResponse对象
    ```python
    from django.http import JsonResponse
    def func(request):
        dit = {"name": "lily"}
        return JsonResponse(dit)  # Content-Type: application/json
    ```
    
    * 对比json序列化
    ```python
    import json
    
    def func(request):
        dit = {"name": "lily"}
        return HttpResponse(json.dumps(dit))  # Content-Type: text/html; charset=utf-8
    ```
    
    * 通过修改响应值,返回json对象
    ```python
    import json
    
    def func(request):
        dit = {"name": "lily"}
        res = HttpResponse(json.dumps(dit))
        res['Content-Type'] = 'application/json'
        return res  # Content-Type: application/json
    ```
    
    * 指定响应内容类型
    ```python
    import json
    
    def func(request):
        dit = {"name": "lily"}
        res = HttpResponse(json.dumps(dit), content_type='application/json')
        return res  # Content-Type: application/json
    ```
    
    * In order to allow non-dict objects to be serialized set the safe parameter to False.
        * 为了允许非字典对象序列号设置safe参数为False
    ```python
    from django.http import JsonResponse
    
    def func(request):   
        return JsonResponse(['a', 8, 'z'], safe=False)  # Content-Type: application/json
    ```
    
    ---------------------------------------------------------------------------
    
    ###模板常用语法
    * {{ 变量 }} 
        * .索引
        * .key
        * .属性
        * .方法
        * views.py
        ```python
        def template_test(request):
            lst = ['abc', '123', 'xyz']
            dit = {'name': 'lily', 'age': 18}
        
            class Person(object):
                def __init__(self, name, age):
                    self.name = name
                    self.age = age
        
                def eating(self):
                    return '%s is eating.' % self.name
        
            Zhangsan = Person('zhangsan', 20)
            Lisi = Person('lisi', 21)
            WangWu = Person('wangwu', 22)
            person_lst = [Zhangsan, Lisi, WangWu]
        
            return render(request, 'template_test.html', {'lst': lst, 'dit': dit, 'person_lst': person_lst,
                                                          'file': 100 * 1024 * 1024, 'value': 4, 'v1': '这是什么鬼,到底什么情况啊?',
                                                          'v2': datetime.datetime.now(),
                                                          'atag': '<a  href="http://www.baidu.com">百度</a>'})
        ```
        
        * template_test.html
        ```html
        <!DOCTYPE html>
        <html lang="en">
        <head>
            <meta charset="UTF-8">
            <title>模板测试</title>
        </head>
        <body>
        列表:{{ lst }}
        <br>
        字典:{{ dit }}
        <br>
        对象列表:{{ person_lst }}
        <br>
        <br>
        列表中的第一个元素:{{ lst.0 }}
        <br>
        列表中的第二个元素:{{ lst.1 }}
        <br>
        列表中的第三个元素:{{ lst.2 }}
        <br>
        <br>
        字典的name值:{{ dit.name }}
        <br>
        字典的age值:{{ dit.age }}
        <br>
        字典的所有键值:{{ dit.keys }}
        <br>
        字典的所有元素:{{ dit.items }}
        <br>
        <br>
        对象列表的第一个对象:{{ person_lst.0 }}
        <br>
        对象列表的第二个对象:{{ person_lst.1 }}
        <br>
        对象列表的第三个对象:{{ person_lst.2 }}
        <br>
        <br>
        对象列表的第一个对象的name属性值:{{ person_lst.0.name }}
        <br>
        对象列表的第一个对象的age属性值:{{ person_lst.0.age }}
        <br>
        对象列表的第一个对象的eating方法:{{ person_lst.0.eating }}
        <br>
        <br>
        过滤器default: {{ aaa|default:"不存在或为空" }}
        <br>
        filesizeformat: {{ file|filesizeformat }}
        <br>
        add: {{ value|add:"2" }}
        <br>
        add: {{ value|add:"a" }}
        <br>
        add: {{ value|add:"2abc" }}
        <br>
        add: {{ lst|add:person_lst }}
        <br>
        upper: {{ lst.0|upper }}
        <br>
        lower: {{ lst.0|lower }}
        <br>
        title: {{ lst.0|title }}
        <br>
        length: {{ lst.0|length }}
        <br>
        ljust: {{ lst.0|ljust:"10" }}
        <br>
        rjust: {{ lst.0|rjust:"10" }}
        <br>
        center: {{ lst.0|center:"15" }}
        <br>
        first: {{ lst.0|first }}
        <br>
        last: {{ lst.0|last }}
        <br>
        slice: {{ lst|slice:"1:-1" }}
        <br>
        join: {{ lst|join:"-" }}
        <br>
        join: {{ lst.0|join:"-" }}
        <br>
        truncatechars: {{ v1|truncatechars:6 }}
        <br>
        date: {{ v2|date:"Y-m-d H:i:s" }}
        <br>
        默认:{{ atag }}
        <br>
        safe: {{ atag|safe }}
        </body>
        </html>
        ```
        
        * 浏览器访问效果
        ```html
        列表:['abc', '123', 'xyz'] 
        字典:{'name': 'lily', 'age': 18} 
        对象列表:[<app02.views.template_test.<locals>.Person object at 0x00000000047045C0>, <app02.views.template_test.<locals>.Person object at 0x0000000004704400>, <app02.views.template_test.<locals>.Person object at 0x000000000478FC18>] 
        
        列表中的第一个元素:abc 
        列表中的第二个元素:123 
        列表中的第三个元素:xyz 
        
        字典的name值:lily 
        字典的age值:18 
        字典的所有键值:dict_keys(['name', 'age']) 
        字典的所有元素:dict_items([('name', 'lily'), ('age', 18)]) 
        
        对象列表的第一个对象:<app02.views.template_test.<locals>.Person object at 0x00000000047045C0> 
        对象列表的第二个对象:<app02.views.template_test.<locals>.Person object at 0x0000000004704400> 
        对象列表的第三个对象:<app02.views.template_test.<locals>.Person object at 0x000000000478FC18> 
        
        对象列表的第一个对象的name属性值:zhangsan 
        对象列表的第一个对象的age属性值:20 
        对象列表的第一个对象的eating方法:zhangsan is eating. 
        
        过滤器default: 不存在或为空 
        filesizeformat: 100.0 MB 
        add: 6 
        add: 
        add: 
        add: ['abc', '123', 'xyz', <app02.views.template_test.<locals>.Person object at 0x00000000047045C0>, <app02.views.template_test.<locals>.Person object at 0x0000000004704400>, <app02.views.template_test.<locals>.Person object at 0x000000000478FC18>] 
        upper: ABC 
        lower: abc 
        title: Abc 
        length: 3 
        ljust: abc 
        rjust: abc 
        center: abc 
        first: a 
        last: c 
        slice: ['123'] 
        join: abc-123-xyz 
        join: a-b-c 
        truncatechars: 这是什么鬼… 
        date: 2019-07-22 21:42:33 
        默认:<a href="http://www.baidu.com">百度</a> 
        safe: 百度 
        ```
        
        * 当模板系统遇到一个(.)时,会按照如下的顺序去查询:
            * 在字典中查询
            * 属性或者方法
            * 数字索引
        
    * Tags{% %} 逻辑相关操作 
        * for循环
        ```html
        <table border="1">
        <tr>
            <th>forloop.counter</th>
            <th>forloop.counter0</th>
            <th>forloop.revcounter</th>
            <th>forloop.revcounter0</th>
            <th>forloop.first</th>
            <th>forloop.last</th>
            <th>p_obj.name</th>
            <th>p_obj.age</th>
        </tr>
        {% for p_obj in person_lst %}
            <tr>
            <td>{{ forloop.counter }}</td>
            <td>{{ forloop.counter0 }}</td>
            <td>{{ forloop.revcounter }}</td>
            <td>{{ forloop.revcounter0 }}</td>
            <td>{{ forloop.first }}</td>
            <td>{{ forloop.last }}</td>
            <td>{{ p_obj.name }}</td>
            <td>{{ p_obj.age }}</td>
            </tr>
        {% endfor %}
        {% for p_obj in person_lst0 %}
            <tr>
            <td>{{ forloop.counter }}</td>
            <td>{{ forloop.counter0 }}</td>
            <td>{{ forloop.revcounter }}</td>
            <td>{{ forloop.revcounter0 }}</td>
            <td>{{ forloop.first }}</td>
            <td>{{ forloop.last }}</td>
            <td>{{ p_obj.name }}</td>
            <td>{{ p_obj.age }}</td>
            </tr>
            {% empty %}
            <tr>
            <td colspan="8">空了</td>
            </tr>
        {% endfor %}
        </table>  
        ```
        
        * if判断
        ```html
        {% if person_lst.0.age > 40 %}
            40岁以上
        {% elif person_lst.0.age > 30 %}
            30岁以上
        {% elif person_lst.0.age > 20 %}
            20岁以上
        {% else %}
            20岁以下
        {% endif %}
        ```
        
        * with
        ```html
        {% with person_lst.0 as zhangsan %}
            zhangsan.name = {{ zhangsan.name }}
            <br>
            zhangsan.age = {{ zhangsan.age }}
        {% endwith %}
        ```
        
        * csrf_token csrf跨站请求伪造(Cross Site Request Forgery) token令牌
            * 这个标签用于跨站请求伪造保护。
            * 在页面的form表单里面写上{% csrf_token %}


    老师博客地址: https://www.cnblogs.com/maple-shaw/articles/9282718.html
            https://www.cnblogs.com/maple-shaw/articles/9285269.html
            https://www.cnblogs.com/maple-shaw/articles/9333821.html
  • 相关阅读:
    Guns 01 项目基本运行
    个人 比较好用的软件
    个人 软件开发 综合技能提升
    开源框架 综合知识
    开源框架 工作流框架
    开源框架 Java 开发框架 1
    开源框架 Java 管理系统
    开源框架 C#
    scp(安全拷贝)和rsync(增量复制)
    完全分布式集群的准备工作
  • 原文地址:https://www.cnblogs.com/lilyxiaoyy/p/11253431.html
Copyright © 2020-2023  润新知