Django知识点汇总

本文详尽汇总了Django框架的核心知识点,包括WSGI接口、中间件、URL路由、Template模板、Views视图、Model与ORM、Admin后台、Http协议、Cookie与Session、用户认证、Form与ModelForm、分页、缓存、信号、序列化、Ajax以及数据库性能优化等。通过实例解析和代码展示,帮助读者深入理解并掌握Django的各个方面。
摘要由CSDN通过智能技术生成

Django知识点汇总

目录

一、wsgi接口

二、中间件

三、URL路由系统

四、Template模板

五、Views视图

六、Model&ORM

七、Admin相关

八、Http协议

九、COOKIE 与 SESSION

十、Django的用户认证

十一、From与ModelForm

十二、分页

十三、缓存

十四、信号

十五、序列化

十六、Ajax

十七、数据库性能相关

0、Django的生命周期

 

一、wsgi接口

了解了HTTP协议和HTML文档,我们其实就明白了一个Web应用的本质就是:

  1. 浏览器发送一个HTTP请求;

  2. 服务器收到请求,生成一个HTML文档;

  3. 服务器把HTML文档作为HTTP响应的Body发送给浏览器;

  4. 浏览器收到HTTP响应,从HTTP Body取出HTML文档并显示。

所以,最简单的Web应用就是先把HTML用文件保存好,用一个现成的HTTP服务器软件,接收用户请求,从文件中读取HTML,返回。Apache、Nginx、Lighttpd等这些常见的静态服务器就是干这件事情的。

如果要动态生成HTML,就需要把上述步骤自己来实现。不过,接受HTTP请求、解析HTTP请求、发送HTTP响应都是苦力活,如果我们自己来写这些底层代码,还没开始写动态HTML呢,就得花个把月去读HTTP规范。

正确的做法是底层代码由专门的服务器软件实现,我们用Python专注于生成HTML文档。因为我们不希望接触到TCP连接、HTTP原始请求和响应格式,所以,需要一个统一的接口,让我们专心用Python编写Web业务。

这个接口就是WSGI:Web Server Gateway Interface。

WSGI接口定义非常简单,它只要求Web开发者实现一个函数,就可以响应HTTP请求。我们来看一个最简单的Web版本的“Hello, web!”:

?
1
2
3
def application(environ, start_response):
     start_response( '200 OK' , [( 'Content-Type' , 'text/html' )])
     return '<h1>Hello, web!</h1>'

  

上面的application()函数就是符合WSGI标准的一个HTTP处理函数,它接收两个参数:

  • environ:一个包含所有HTTP请求信息的dict对象;

  • start_response:一个发送HTTP响应的函数。

application()函数中,调用:

?
1
start_response( '200 OK' , [( 'Content-Type' , 'text/html' )])

就发送了HTTP响应的Header,注意Header只能发送一次,也就是只能调用一次start_response()函数。start_response()函数接收两个参数,一个是HTTP响应码,一个是一组list表示的HTTP Header,每个Header用一个包含两个strtuple表示。

通常情况下,都应该把Content-Type头发送给浏览器。其他很多常用的HTTP Header也应该发送。

然后,函数的返回值'<h1>Hello, web!</h1>'将作为HTTP响应的Body发送给浏览器。

有了WSGI,我们关心的就是如何从environ这个dict对象拿到HTTP请求信息,然后构造HTML,通过start_response()发送Header,最后返回Body。

整个application()函数本身没有涉及到任何解析HTTP的部分,也就是说,底层代码不需要我们自己编写,我们只负责在更高层次上考虑如何响应请求就可以了。

不过,等等,这个application()函数怎么调用?如果我们自己调用,两个参数environstart_response我们没法提供,返回的str也没法发给浏览器。

所以application()函数必须由WSGI服务器来调用。有很多符合WSGI规范的服务器,我们可以挑选一个来用。但是现在,我们只想尽快测试一下我们编写的application()函数真的可以把HTML输出到浏览器,所以,要赶紧找一个最简单的WSGI服务器,把我们的Web应用程序跑起来。

好消息是Python内置了一个WSGI服务器,这个模块叫wsgiref,它是用纯Python编写的WSGI服务器的参考实现。所谓“参考实现”是指该实现完全符合WSGI标准,但是不考虑任何运行效率,仅供开发和测试使用。

运行WSGI服务

我们先编写hello.py,实现Web应用程序的WSGI处理函数:

?
1
2
3
4
5
# hello.py
 
def application(environ, start_response):
     start_response( '200 OK' , [( 'Content-Type' , 'text/html' )])
     return '<h1>Hello, web!</h1>'

然后,再编写一个server.py,负责启动WSGI服务器,加载application()函数:

?
1
2
3
4
5
6
7
8
9
10
11
# server.py
# 从wsgiref模块导入:
from wsgiref.simple_server import make_server
# 导入我们自己编写的application函数:
from hello import application
 
# 创建一个服务器,IP地址为空,端口是8000,处理函数是application:
httpd = make_server( '' , 8000, application)
print ( "Serving HTTP on port 8000..."
# 开始监听HTTP请求:
httpd.serve_forever()

确保以上两个文件在同一个目录下,然后在命令行输入python server.py来启动WSGI服务器:

 

注意:如果8000端口已被其他程序占用,启动将失败,请修改成其他端口。

启动成功后,打开浏览器,输入http://localhost:8000/,就可以看到结果了:

复制代码
整个application()函数本身没有涉及到任何解析HTTP的部分,也就是说,底层代码不需要我们自己编写,
我们只负责在更高层次上考虑如何响应请求就可以了。

application()函数必须由WSGI服务器来调用。有很多符合WSGI规范的服务器,我们可以挑选一个来用。

Python内置了一个WSGI服务器,这个模块叫wsgiref    
    
    
application()函数就是符合WSGI标准的一个HTTP处理函数,它接收两个参数:

        //environ:一个包含所有HTTP请求信息的dict对象;
        
        //start_response:一个发送HTTP响应的函数。

在application()函数中,调用:

start_response('200 OK', [('Content-Type', 'text/html')])

就发送了HTTP响应的Header,注意Header只能发送一次,也就是只能调用一次start_response()函数。
start_response()函数接收两个参数,一个是HTTP响应码,一个是一组list表示的HTTP Header,每
个Header用一个包含两个str的tuple表示。

通常情况下,都应该把Content-Type头发送给浏览器。其他很多常用的HTTP Header也应该发送。

然后,函数的返回值b'<h1>Hello, web!</h1>'将作为HTTP响应的Body发送给浏览器。

有了WSGI,我们关心的就是如何从environ这个dict对象拿到HTTP请求信息,然后构造HTML,
通过start_response()发送Header,最后返回Body。
复制代码
注意

 

回到顶部

二、中间件

django 中的中间件(middleware),在django中,中间件其实就是一个类,在请求到来和结束后,django会根据自己的规则在合适的时机执行中间件中相应的方法。

在django项目的settings模块中,有一个 MIDDLEWARE_CLASSES 变量,其中每一个元素就是一个中间件

中间件中一共有五个方法:

process_request

- 有,直接执行当前中间件和上方中间件的process_response

- 应用: 用户登录授权(排除不需要登录的url)

process_view

 

process_exception

- process_tempalte_response
- 必须有返回值
- 必须对象中要有render方法

process_response

    - 必须有返回值
中间件五种方法

 

中间件之process_request,process_response

process_request(self,request)

process_response(self, request, response)

当用户发起请求的时候会依次经过所有的的中间件,这个时候的请求时process_request,最后到达views的函数中,views函数处理后,在依次穿过中间件,这个时候是process_response,最后返回给请求者

在django中叫中间件,在其他web框架中,有的叫管道,httphandle

 

中间件之process_view执行过程:

当最后一个中间的process_request到达路由关系映射之后,返回到中间件1的process_view,然后依次往下,到达views函数,最后通过process_response依次返回到达用户

中间件之process_exception

process_exception(self, request, exception)

当views的函数中出现错误时,就会执行process_exception方法

如果在中间中添加了process_exception方法,工作图示为:

  这样当用户发起请求的时候到达中间件3的process_request之后会到达urls路由关系映射这里,如果匹配到了就会到中间件1的process_view,然后依次传递到中间件3的process_view,到达view函数。如果view函数中有报错,则会从中间件3依次向上判断每个中间件的process_exception是否能匹配到这个错误信息,如果匹配到则直接返回到最后一个中间件,这里即中间件3的process_response,然后依次返回到用户,如果没有匹配到这个错误则直接在页面显示错误信息。如果view函数中没有错误,则到中间3即最后一个中间件3的process_response,然后依次向上,传到用户

中间件之process_template_responseprocess

process_template_response(self,request,response)

只有当views函数中返回的对象中具有render方法,是就会直接process_template_responseprocess

 中间件的应用

所有请求统一做处理时使用
- 登录验证

-添加访问日志等

 

自定义中间件

上述图中的中间件都是django中的,我们也可以自己定义一个中间件,我们可以自己写一个类,但是必须继承MiddlewareMixin

所以需要导入:from django.utils.deprecation import MiddlewareMixin

我们在项目文件下创建一个Middle目录,并在下面创建m1.py代码例子如下

#AUTHOR:FAN
from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse

class Row1(MiddlewareMixin):
    def process_request(self,request):
        print("中间件1请求")
    def process_response(self,request,response):
        print("中间件1返回")
        return response

class Row2(MiddlewareMixin):
    def process_request(self,request):
        print("中间件2请求")
        # return HttpResponse("")
    def process_response(self,request,response):
        print("中间件2返回")
        return response

class Row3(MiddlewareMixin):
    def process_request(self,request):
        print("中间件3请求")
    def process_response(self,request,response):
        print("中间件3返回")
        return response
自定义中间件

配置settings.py

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'Middle.m1.Row1',
    'Middle.m1.Row2',
    'Middle.m1.Row3',
]
自定义中间件-配置setting.py

 

返回顶部 

 三、URL路由系统(URLconf)

URL配置(URLconf)就像Django 所支撑网站的目录。它的本质是URL与要为该URL调用的视图函数之间的映射表;你就是以这种方式告诉Django,对于这个URL调用这段代码,对于那个URL调用那段代码。

 '''
    
    urlpatterns = [
         url(正则表达式, views视图函数,参数,别名),
]


参数说明:

    一个正则表达式字符串
    一个可调用对象,通常为一个视图函数或一个指定视图函数路径的字符串
    可选的要传递给视图函数的默认参数(字典形式)
    一个可选的name参数

    '''
URLconf说明

3.1 简单配置

from django.conf.urls import url

from . import views

urlpatterns = [
    url(r'^articles/2003/$', views.special_case_2003),
    url(r'^articles/([0-9]{4})/$', views.year_archive),
    url(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive),
    url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail),
]
url配置实例
'''
    NOTE:
    1 一旦匹配成功则不再继续
    2 若要从URL 中捕获一个值,只需要在它周围放置一对圆括号。
    3 不需要添加一个前导的反斜杠,因为每个URL 都有。例如,应该是^articles 而不是 ^/articles。
    4 每个正则表达式前面的'r' 是可选的但是建议加上。

一些请求的例子:

    /articles/2005/3/ 不匹配任何URL 模式,因为列表中的第三个模式要求月份应该是两个数字。
    /articles/2003/ 将匹配列表中的第一个模式不是第二个,因为模式按顺序匹配,第一个会首先测试是否匹配。
    /articles/2005/03/ 请求将匹配列表中的第三个模式。Django 将调用函数
                       views.month_archive(request, '2005', '03')。

#设置项是否开启URL访问地址后面不为/跳转至带有/的路径
APPEND_SLASH=True

'''
url配置注意事项

3.2 有名分组(named group)

  上面的示例使用简单的、没有命名的正则表达式组(通过圆括号)来捕获URL 中的值并以位置 参数传递给视图。在更高级的用法中,可以使用命名的正则表达式组来捕获URL 中的值并以关键字 参数传递给视图。

  在Python 正则表达式中,命名正则表达式组的语法是(?P<name>pattern),其中name 是组的名称,pattern 是要匹配的模式。

下面是以上URLconf 使用命名组的重写:

from django.conf.urls import url

from . import views

urlpatterns = [
    url(r'^articles/2003/$', views.special_case_2003),
    url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),
    url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.month_archive),
    url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})/$', views.article_detail),
]
url有名分组

这个实现与前面的示例完全相同,只有一个细微的差别:捕获的值作为关键字参数而不是位置参数传递给视图函数。例如:

/articles/2005/03/    
请求将调用views.month_archive(request, year='2005', month='03')函数
/articles/2003/03/03/ 
请求将调用函数views.article_detail(request, year='2003', month='03', day='03')。
url有名分组实例

在实际应用中,这意味你的URLconf 会更加明晰且不容易产生参数顺序问题的错误 —— 你可以在你的视图函数定义中重新安排参数的顺序。当然,这些好处是以简洁为代价;有些开发人员认为命名组语法丑陋而繁琐。

3.3 URLconf 在什么上查找

URLconf 在请求的URL 上查找,将它当做一个普通的Python 字符串。不包括GET和POST参数以及域名。

例如,http://www.example.com/myapp/ 请求中,URLconf 将查找myapp/

在http://www.example.com/myapp/?page=3 请求中,URLconf 仍将查找myapp/

URLconf 不检查请求的方法。换句话讲,所有的请求方法 —— 同一个URL的POSTGETHEAD等等 —— 都将路由到相同的函数。

3.4 捕获的参数永远是字符串

每个捕获的参数都作为一个普通的Python 字符串传递给视图,无论正则表达式使用的是什么匹配方式。例如,下面这行URLconf 中:

url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),

views.year_archive() 的year 参数将是一个字符串

3.5 指定视图参数的默认值

有一个方便的小技巧是指定视图参数的默认值。 下面是一个URLconf 和视图的示例

# URLconf
from django.conf.urls import url

from . import views

urlpatterns = [
    url(r'^blog/$', views.page),
    url(r'^blog/page(?P<num>[0-9]+)/$', views.page),
]

# View (in blog/views.py)
def page(request, num="1"):

    ...
View Code

 

  在上面的例子中,两个URL模式指向同一个视图views.page —— 但是第一个模式不会从URL 中捕获任何值。如果第一个模式匹配,page() 函数将使用num参数的默认值"1"。如果第二个模式匹配,page() 将使用正则表达式捕获的num 值。

3.1.6 路由分发( Including other URLconfs)

在项目中,若需要将某一应用下url统一跳转,则可以使用 Including other URLconfs

#At any point, your urlpatterns can “include” other URLconf modules. This
#essentially “roots” a set of URLs below other ones.

#For example, here’s an excerpt of the URLconf for the Django website itself.
#It includes a number of other URLconfs:


from django.conf.urls import include, url

urlpatterns = [
   url(r'^admin/', admin.site.urls),
   url(r'^blog/', include('blog.urls')),
]
路由分发(include other是url)

 返回顶部

四、Template模板

  python的模板:HTML代码+逻辑控制代码

4.1 模板支持的语法

4.1.1  变量(使用双大括号来引用变量)
语法格式:       {
    {var_name}}

Django 模板解析非常快捷。 大部分的解析工作都是在后台通过对简短正则表达式一次性调用来完成。 这和基于 XML 的模板引擎形成鲜明对比,那些引擎承担了 XML 解析器的开销,且往往比 Django 模板渲染引擎要慢上几个数量级。

from django.shortcuts import render,HttpResponse
from django.template.loader import get_template #记得导入
# Create your views here.


import datetime
from django.template import Template,Context

# def current_time(req):
    #原始的视图函数
    # now=datetime.datetime.now()
    # html="<html><body>现在时刻:<h1>%s.</h1></body></html>" %now
    # return HttpResponse(html)

# def current_time(req):

      #django模板修改的视图函数
#     now=datetime.datetime.now()
#     t=Template('<html><body>现在时刻是:<h1 style="color:red">{
      {current_date}}</h1></body></html>')
      #t=get_template('current_datetime.html')
#     c=Context({
     'current_date':now})
#     html=t.render(c)
#     return HttpResponse(html)

#另一种写法(推荐)

def current_time(req):

    now=datetime.datetime.now()

    return render(req, 'current_datetime.html', {
     'current_date':now})
Django模板使用比较
4.1.2 深度变量的查找(万能的句点号)

在到目前为止的例子中,我们通过 context 传递的简单参数值主要是字符串,然而,模板系统能够非常简洁地处理更加复杂的数据结构,例如list、dictionary和自定义的对象。在 Django 模板中遍历复杂数据结构的关键是句点字符 (.)。

#最好是用几个例子来说明一下。
# 首先,句点可用于访问列表索引,例如:

>>> from django.template import Template, Context
>>> t = Template('Item 2 is {
      { items.2 }}.')
>>> c = Context({
     'items': ['apples', 'bananas', 'carrots']})
>>> t.render(c)
'Item 2 is carrots.'

#假设你要向模板传递一个 Python 字典。 要通过字典键访问该字典的值,可使用一个句点:
>>> from django.template import Template, Context
>>> person = {
     'name': 'Sally', 'age': '43'}
>>> t = Template('{
      { person.name }} is {
      { person.age }} years old.')
>>> c = Context({
     'person': person})
>>> t.render(c)
'Sally is 43 years old.'

#同样,也可以通过句点来访问对象的属性。 比方说, Python 的 datetime.date 对象有
#year 、 month 和 day 几个属性,你同样可以在模板中使用句点来访问这些属性:

>>> from django.template import Template, Context
>>> import datetime
>>> d = datetime.date(1993, 5, 2)
>>> d.year
1993
>>> d.month
5
>>> d.day
2
>>> t = Template('The month is {
      { date.month }} and the year is {
      { date.year }}.')
>>> c = Context({
     'date': d})
>>> t.render(c)
'The month is 5 and the year is 1993.'

# 这个例子使用了一个自定义的类,演示了通过实例变量加一点(dots)来访问它的属性,这个方法适
# 用于任意的对象。
>>> from django.template import Template, Context
>>> class Person(object):
...     def __init__(self, first_name, last_name):
...         self.first_name, self.last_name = first_name, last_name
>>> t = Template('Hello, {
      { person.first_name }} {
      { person.last_name }}.')
>>> c = Context({
     'person': Person('John', 'Smith')})
>>> t.render(c)
'Hello, John Smith.'

# 点语法也可以用来引用对象的方法。 例如,每个 Python 字符串都有 upper() 和 isdigit()
# 方法,你在模板中可以使用同样的句点语法来调用它们:
>>> from django.template import Template, Context
>>> t = Template('{
      { var }} -- {
      { var.upper }} -- {
      { var.isdigit }}')
>>> t.render(Context({
     'var': 'hello'}))
'hello -- HELLO -- False'
>>> t.render(Context({
     'var': '123'}))
'123 -- 123 -- True'

# 注意这里调用方法时并* 没有* 使用圆括号 而且也无法给该方法传递参数;你只能调用不需参数的
# 方法。
句点号查找实例
4.1.3 变量的过滤器(filter)的使用
#语法格式:      {
     {obj|filter:param}}
 
# 1  add          :   给变量加上相应的值
# 2  addslashes   :    给变量中的引号前加上斜线
# 3  capfirst     :    首字母大写
# 4  cut          :   从字符串中移除指定的字符
# 5  date         :   格式化日期字符串
# 6  default      :   如果值是False,就替换成设置的默认值,否则就是用本来的值
# 7  default_if_none:  如果值是None,就替换成设置的默认值,否则就使用本来的值
 
 
#实例:
 
#value1="aBcDe"
{
      { value1|upper }}<br>
 
#value2=5
{
      { value2|add:3 }}<br>
 
#value3='he  llo wo r ld'
{
      { value3|cut:' ' }}<br>
 
#import datetime
#value4=datetime.datetime.now()
{
      { value4|date:'Y-m-d' }}<br>
 
#value5=[]
{
      { value5|default:'空的' }}<br>
 
#value6='<a href="#">跳转</a>'
 
{
      { value6 }}
 
{
      % autoescape off %}
  {
      { value6 }}
{
      % endautoescape %}
 
{
      { value6|safe }}<br>
 
{
      { value6|striptags }}
 
#value7='1234'
{
      { value7|filesizeformat }}<br>
{
      { value7|first }}<br>
{
      { value7|length }}<br>
{
      { value7|slice:":-1" }}<br>
 
#value8='http://www.baidu.com/?a=1&b=3'
{
      { value8|urlencode }}<br>
    value9='hello I am yuan'
filter过滤器使用说明
4.1.4自定义filter和simple_tag

a、在app中创建templatetags模块(必须的)

b、创建任意 .py 文件,如:my_tags.py

from django import template
from django.utils.safestring import mark_safe

register = template.Library()   #register的名字是固定的,不可改变


@register.filter
def filter_multi(v1,v2):
    return  v1 * v2


@register.simple_tag
def simple_tag_multi(v1,v2):
    return  v1 * v2


@register.simple_tag
def my_input(id,arg):
    result = "<input type='text' id='%s' class='%s' />" %(id,arg,)
    return mark_safe(result)
自定义过滤器

c、在使用自定义simple_tag和filter的html文件中导入之前创建的 my_tags.py :{% load my_tags %}

d、使用simple_tag和filter(如何调用)

-------------------------------.html
{
      % load my_tags %}   #首行
    
    
 # num=12
{
      { num|filter_multi:2 }} #24

{
      { num|filter_multi:"[22,333,4444]" }}

{
      % simple_tag_multi 2 5 %}  参数不限,但不能放在if for语句中
{
      % simple_tag_multi num 5 %}
调用自定义过滤器

e、在settings中的INSTALLED_APPS配置当前app,不然django无法找到自定义的simple_tag.

注意:

filter可以用在if等语句后,simple_tag不可以

{% if num|filter_multi:30 > 100 %}
    {
      { num|filter_multi:30 }}
{
      % endif %}
View Code

4.2 标签(tag)的使用(使用大括号和百分比的组合来表示使用tag)

语法格式:    {% tags %}

{% if %} 的使用 

{% if %}标签计算一个变量值,如果是“true”,即它存在、不为空并且不是false的boolean值,系统则会显示{% if %}和{% endif %}间的所有内容

{% if num >= 100 and 8 %}

    {
      % if num > 200 %}
        <p>num大于200</p>
    {
      % else %}
        <p>num大于100小于200</p>
    {
      % endif %}

{
      % elif num < 100%}
    <p>num小于100</p>

{
      % else %}
    <p>num等于100</p>

{
      % endif %}



{
      % if %} 标签接受and,or或者not来测试多个变量值或者否定一个给定的变量
{
      % if %} 标签不允许同一标签里同时出现and和or,否则逻辑容易产生歧义,例如下面的标签是不合法的:

{
      % if obj1 and obj2 or obj3 %} 
{% if%}标签使用

{% for %}的使用

{% for %}标签允许你按顺序遍历一个序列中的各个元素,每次循环模板系统都会渲染{% for %}和{% endfor %}之间的所有内容

<ul>
{
      % for obj in list %}
    <li>{
     { obj.name }}</li>
{
      % endfor %}
</ul>


#在标签里添加reversed来反序循环列表:

    {
      % for obj in list reversed %}
    ...
    {
      % endfor %}

#{
      % for %}标签可以嵌套:

    {
      % for country in countries %}
        <h1>{
     { country.name }}</h1>
        <ul>
         {
      % for city in country.city_list %}
            <li>{
     { city }}</li>
         {
      % endfor %}
        </ul>
    {
      % endfor %}


#系统不支持中断循环,系统也不支持continue语句,{
      % for %}标签内置了一个forloop模板变量,
#这个变量含有一些属性可以提供给你一些关于循环的信息

1,forloop.counter表示循环的次数,它从1开始计数,第一次循环设为1:

    {
      % for item in todo_list %}
        <p>{
     { forloop.counter }}: {
     { item }}</p>
    {
      % endfor %}
2,forloop.counter0 类似于forloop.counter,但它是从0开始计数,第一次循环设为0
3,forloop.revcounter
4,forloop.revcounter0
5,forloop.first当第一次循环时值为True,在特别情况下很有用:

    
    {
      % for object in objects %}   
         {
      % if forloop.first %}<li class="first">{% else %}<li>{% endif %}   
         {
      { object }}   
        </li>  
    {
      % endfor %}  
    
# 富有魔力的forloop变量只能在循环中得到,当模板解析器到达{
      % endfor %}时forloop就消失了
# 如果你的模板context已经包含一个叫forloop的变量,Django会用{
      % for %}标签替代它
# Django会在for标签的块中覆盖你定义的forloop变量的值
# 在其他非循环的地方,你的forloop变量仍然可用


#{
      % empty %}

{
      {li }}
      {
      %  for i in li %}
          <li>{
     { forloop.counter0 }}----{
     { i }}</li>
      {
      % empty %}
          <li>this is empty!</li>
      {
      % endfor %}

#         [11, 22, 33, 44, 55]
#            0----11
#            1----22
#            2----33
#            3----44
#            4----55
{% for %}标签使用

csrf_token标签

用于生成csrf_token的标签,用于防治跨站攻击验证。 其实,这里是会生成一个input标签,和其他表单标签一起提交给后台的。

{% url %}

引用路由配置的地址

<form action="{% url "bieming"%}" >
          <input type="text">
          <input type="submit"value="提交">
          {
      %csrf_token%}
</form>
{% url %}标签使用

{% with %}

用更简单的变量名替代复杂的变量名

{% with total=fhjsaldfhjsdfhlasdfhljsdal %} {
     { total }} {% endwith %}
{% with %}标签使用

4.3 extend模板继承

步骤:

a、新建 base.html,放在template目录下

b、使用模板标签: {% block %}分块,用于子模板继承 

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html lang="en">
<head>
    <title>{% block title %}{% endblock %}</title>
</head>
<body>
    <h1>My helpful timestamp site</h1>
    {
      % block content %}{% endblock %}
    {
      % block footer %}
    <hr>
    <p>Thanks for visiting my site.</p>
    {
      % endblock %}
</body>
</html>
新建母版文件(base.html)

c、子模版集成(即重载block块)

{% extends "base.html" %}
 
{
      % block title %}The current time{% endblock %}
 
{
      % block content %}
<p>It is now {
     { current_date }}.</p>
{
      % endblock %}
子母版继承

继承的常见三层法:

   <1> 创建 base.html 模板,在其中定义站点的主要外观感受。 这些都是不常修改甚至从不修改的部分。
   <2> 为网站的每个区域创建 base_SECTION.html 模板(例如, base_photos.html 和 base_forum.html )。这些模板对base.html 进行拓展,
       并包含区域特定的风格与设计。
   <3> 为每种类型的页面创建独立的模板,例如论坛页面或者图片库。 这些模板拓展相应的区域模板。
继承的常见三层法

模板继承的一些诀窍

<1>如果在模板中使用 {% extends %} ,必须保证其为模板中的第一个模板标记。 否则,模板继承将不起作用。

 <2>一般来说,基础模板中的 {% block %} 标签越多越好。 记住,子模板不必定义父模板中所有的代码块,因此
    你可以用合理的缺省值对一些代码块进行填充,然后只对子模板所需的代码块进行(重)定义。 俗话说,钩子越
    多越好。

 <3>如果发觉自己在多个模板之间拷贝代码,你应该考虑将该代码段放置到父模板的某个 {% block %} 中。
    如果你需要访问父模板中的块的内容,使用 {
      { block.super }}这个标签吧,这一个魔法变量将会表现出父模
    板中的内容。 如果只想在上级代码块基础上添加内容,而不是全部重载,该变量就显得非常有用了。

 <4>不允许在同一个模板中定义多个同名的 {% block %} 。 存在这样的限制是因为block 标签的工作方式是双向的。
    也就是说,block 标签不仅挖了一个要填的坑,也定义了在父模板中这个坑所填充的内容。如果模板中出现了两个
    相同名称的 {
      % block %} 标签,父模板将无从得知要使用哪个块的内容。
模板继承的诀窍

 返回顶部

 五、Views视图

django中请求处理方式有2种:FBV 和 CBV

 5.1 CBV(class base views)

CBV(class base views) 就是在视图里使用类处理请求。

5.1.1. 基本使用

使用方法为:urls.py 修改为如下:

from mytest import views

urlpatterns = [
    # url(r‘^index/‘, views.index),
    url(r‘^index/‘, views.Index.as_view()),
]
#注:url(r‘^index/‘, views.Index.as_view()),  是固定用法。
CBV中urls.py文件

views.py 修改为如下:

from django.views import View

class Index(View):

    def dispatch(self, request, *args, **kwargs):
        res = super(AuthView,self).dispatch(request, *args, **kwargs)
        return res

    def get(self, req):
        print(‘method is :‘ + req.method)
        return render(req, ‘index.html‘)

    def post(self, req):
        print(‘method is :‘ + req.method)
        return render(req, ‘index.html‘)
#注:1、类要继承 View ,类中函数名必须小写。
        2、类中首先执行的是  dispatch方法
CBV中views.py文件

5.1.2. 基于dispatch和继承实现用户登录代码

  1、写一个登录验证类

class AuthView(object):
    def dispatch(self, request, *args, **kwargs):
        if not request.session.get('user_info'):
            return redirect('/login.html')
        res = super(AuthView,self).dispatch(request, *args, **kwargs)
        return res
CBV实现用户登录验证

2、修改views.py并继承验证

from django.views import View

class Index(AuthView,View):

    def get(self, req):
        print(‘method is :‘ + req.method)
        return render(req, ‘index.html‘)

    def post(self, req):
        print(‘method is :‘ + req.method)
        return render(req, ‘index.html‘)
#继承AuthView验证类即可
CBV实现用户登录验证

5.1.3. 装饰器

1、get,post方法上,给任意函数添加

from django.utils.decorators import method_decorator
from django.views import View

def test(func):
    def inner(*args,**kwargs):
        return func(*args,**kwargs)
    return inner


class Index(View):
    def dispatch(self, request, *args, **kwargs):
        res = super(AuthView,self).dispatch(request, *args, **kwargs)
        return res
    
    @method_decorator(test)
    def get(self, req):
        print(‘method is :‘ + req.method)
        return render(req, ‘index.html‘)

    @method_decorator(test
    def post(self, req):
        print(‘method is :‘ + req.method)
        return render(req, ‘index.html‘)

     
get,post方法上

2、dispatch方法上,同时给get、post添加装饰器

from django.shortcuts import render,HttpResponse,redirect
from django.views import View
from django.utils.decorators import method_decorator

class LoginView(View):
    @method_decorator(test)
    def dispatch(self, request, *args, **kwargs):
        return super(LoginView,self).dispatch(request, *args, **kwargs)

    def get(self,request):
        return render(request,'login.html')


    def post(self,request):
    return redirect('/index.html')
dispatch方法上

3、类上

from django.shortcuts import render,HttpResponse,redirect
from django.views import View
from django.utils.decorators import method_decorator

@method_decorator(test,name='get')
class LoginView(View):

    def dispatch(self, request, *args, **kwargs):
        return super(LoginView,self).dispatch(request, *args, **kwargs)

    def get(self,request):
        return render(request,'login.html')

    def post(self,request):
        return redirect('/index.html')
#类上添加装饰器,name后面有哪些函数,哪些函数就添加了装饰器 
类上

4、特殊:CSRF Token只能加到dispatch

from django.shortcuts import render,HttpResponse,redirect
from django.views import View
from django.utils.decorators import method_decorator

from django.views.decorators.csrf import csrf_exempt,csrf_protect


class LoginView(View):
    @method_decorator(csrf_exempt)
    def dispatch(self, request, *args, **kwargs):
        return super(LoginView,self).dispatch(request, *args, **kwargs)

    def get(self,request):
        return render(request,'login.html')

    def post(self,request):
        return redirect('/index.html')
#csrf_exempt 其他需要,加此装饰器的不需要
#csrf_protect 其他不需要需要,加此装饰器的需要
CSRF Token只能加到dispatch

5.2 FBV(function base views)

FBV(function base views) 就是在视图里使用函数处理请求。

5.2.1. 基本使用

1、使用方法为:urls.py 修改为如下:

from django.conf.urls import url, include

# from django.contrib import admin
from mytest import views

urlpatterns = [
    # url(r‘^admin/‘, admin.site.ur
  • 6
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值