Django框架全面讲解

2019年12月07日 阅读数:93
这篇文章主要向大家介绍Django框架全面讲解,主要内容包括基础应用、实用技巧、原理机制等方面,希望对大家有所帮助。

Python的WEB框架有Django、Tornado、Flask 等多种,Django相较与其余WEB框架其优点为:大而全,框架自己集成了ORM、模型绑定、模板引擎、缓存、Session等诸多功能。css

本文将如下方面带你们全面了解Django框架,笔者使用的版本为1.10.html

  1. 流程前端

  2. 基本配置
  3. 路由系统
  4. 视图view
  5. 模板
  6. Model
  7. 中间件
  8. Form
  9. 认证系统
  10. CSRF
  11. 分页
  12. Cookie
  13. Seesion
  14. 缓存
  15. 序列化
  16. 信号
  17. admin

1、 Django流程介绍

 

MVC是众所周知的模式,即:将应用程序分解成三个组成部分:model(模型),view(视图),和 controller(控制 器)。其中:
      M——管理应用程序的状态(一般存储到数据库中),并约束改变状态的行为(或者叫作“业务规则”)。
      C——接受外部用户的操做,根据操做访问模型获取数据,并调用“视图”显示这些数据。控制器是将“模型”和“视图”隔离,并成为两者之间的联系纽带。
      V——负责把数据格式化后呈现给用户。python

Django也是一个MVC框架。可是在Django中,控制器接受用户输入的部分由框架自行处理,因此 Django 里更关注的是模型(Model)、模板(Template)和视图(Views),称为 MTV模式:

    M 表明模型(Model),即数据存取层。 该层处理与数据相关的全部事务: 如何存取、如何验证有效性、包含哪些行为以及数据之间的关系等。

    T 表明模板(Template),即表现层。 该层处理与表现相关的决定: 如何在页面或其余类型文档中进行显示。

    V 表明视图(View),即业务逻辑层。 该层包含存取模型及调取恰当模板的相关逻辑。 你能够把它看做模型与模板之间的桥梁。jquery

 

2、 Django 基本配置

1. 建立django程序

  • 终端命令:django-admin startproject sitename  (在当前目录下建立一个Django程序)
  • IDE建立Django程序时,本质上都是自动执行上述命令

其余经常使用命令:git

  python manage.py runserver ip:port  (启动服务器,默认ip和端口为http://127.0.0.1:8000/)ajax

  python manage.py startapp appname  (新建 app)正则表达式

  python manage.py syncdb  (同步数据库命令,Django 1.7及以上版本须要用如下的命令)shell

  python manage.py makemigrations  (显示并记录全部数据的改动)数据库

  python manage.py migrate  (将改动更新到数据库)

  python manage.py createsuperuser  (建立超级管理员)

  python manage.py dbshell  (数据库命令行)

  python manage.py  (查看命令列表)

 

2. 程序目录

 

3. 配置文件

a、数据库

支持SQLite 3(默认)、PostgreSQL 、MySQL、Oracle数据库的操做

  具体配置

Django框架对于开发者而言高度透明化,对于不一样数据库的具体使用方法是一致的,改变数据库类型只须要变更上述配置便可。

想要了解更多请戳这里

 

b、静态文件添加

  settings配置

 

3、 Django 路由系统

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

参数说明:

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

 

1. 示例

1
2
3
4
5
6
7
8
9
10
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中的值,用括号括起来,会当参数传入 views 视图。
  • 没有必要添加一个斜线,由于每一个URL都有。例如,它^articles不是^/articles
  • 'r'前面的每一个正则表达式字符串中是可选的,但建议。它告诉Python字符串是“原始” -没有什么字符串中应该进行转义。

请求示例:

  • 一个请求 /articles/2005/03/ 会匹配上面列表中的第三条. Django 会调用函数 views.month_archive(request, '2005', '03').
  • /articles/2005/3/ 不会匹配上面列表中的任何条目, 由于第三条的月份须要二位数字.
  • /articles/2003/ 会匹配上第一条而不是第二条,由于匹配是按照从上到下顺序而进行的, Django 会调用函数 views.special_case_2003(request)
  • /articles/2003 不会匹配上面列表中的任何条目, 由于每一个URL应该以 / 结尾.
  • /articles/2003/03/03/ 会匹配上最后一条. Django 会调用函数 views.article_detail(request, '2003', '03', '03').

 

2. 命名组(Named groups)

在上面的简单例子中,并无使用正则表达式分组,在更高级的用法中,颇有可能使用正则分组来匹配URL而且将分组值经过参数传递给view函数。

在Python的正则表达式中,分组的语法是 (?P<name>pattern), name表示分组名,pattern表示一些匹配正则.

这里是一个简单的小例子:

1
2
3
4
5
6
7
8
9
10
11
12
# 正则知识
import  re
 
ret = re.search( '(?P<id>\d{3})/(?P<name>\w{3})' , 'weeew34ttt123/ooo' )
 
print (ret.group())
print (ret.group( 'id' ))
print (ret.group( 'name' ))
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
123 / ooo
123
ooo

  

1
2
3
4
5
6
7
8
9
10
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),
]

For example:

  • A request to /articles/2005/03/ 会调用函数 views.month_archive(request, year='2005',month='03'), 而不是 views.month_archive(request, '2005', '03').
  • A request to /articles/2003/03/03/ 会调用函数 views.article_detail(request, year='2003',month='03', day='03').

常见写法实例:

 

3. 二级路由(Including)

那若是映射 url 太多怎么办,全写一个在  urlpatterns 显得繁琐,so 二级路由应用而生

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from  django.conf.urls  import  include, url
 
from  apps.main  import  views as main_views
from  credit  import  views as credit_views
 
extra_patterns  =  [
     url(r '^reports/$' , credit_views.report),
     url(r '^reports/(?P<id>[0-9]+)/$' , credit_views.report),
     url(r '^charge/$' , credit_views.charge),
]
 
urlpatterns  =  [
     url(r '^$' , main_views.homepage),
     url(r '^help/' , include( 'apps.help.urls' )),
     url(r '^credit/' , include(extra_patterns)),
]

在上面这个例子中,若是请求url为 /credit/reports/ 则会调用函数 credit_views.report().

 

使用二级路由也能够减小代码冗余,使代码更加简洁易懂

  

4. 添加额外的参数

URLconfs 有一个钩子可让你加入一些额外的参数到view函数中.

1
2
3
4
5
6
from  django.conf.urls  import  url
from  import  views
   
urlpatterns  =  [
     url(r '^blog/(?P<year>[0-9]{4})/$' , views.year_archive, { 'foo' 'bar' }),
]

在上面的例子中,若是一个请求为 /blog/2005/, Django 将会调用函数l views.year_archive(request, year='2005',foo='bar').

须要注意的是,当你加上参数时,对应函数views.year_archive必须加上一个参数,参数名也必须命名为 foo,以下:

 

1
2
3
def  year_archive(request, foo):
     print (foo)
     return  render(request,  'index.html' )

  

5. 别名的使用

1
url(r '^index' ,views.index,name = 'bieming' )

url中还支持name参数的配置,若是配置了name属性,在模板的文件中就可使用name值来代替相应的url值.

咱们来看一个例子:

  name的应用

  

6. 指定view的默认配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 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" ):
     # Output the appropriate page of blog entries, according to num.
     ...

在上述的例子中,两个 URL 模式指向同一个视图 views.page 但第一图案不捕获从 URL 任何东西。若是第一个模式匹配,该 page() 函数将使用它的默认参数 num"1"。若是第二图案相匹配时, page()将使用任何 num 值由正则表达式捕获。

 

4、 Django Views(视图函数)

http请求中产生两个核心对象:

  http请求:HttpRequest对象

  http响应:HttpResponse对象

 

1. HttpRequest对象

当请求一个页面时,Django 建立一个 HttpRequest对象包含原数据的请求。而后 Django 加载适当的视图,经过 HttpRequest做为视图函数的第一个参数。每一个视图负责返回一个HttpResponse目标。

复制代码
path:       请求页面的全路径,不包括域名

method:     请求中使用的HTTP方法的字符串表示。全大写表示。例如

                   if  req.method=="GET":

                             do_something()

                   elseif req.method=="POST":

                             do_something_else()

GET:         包含全部HTTP GET参数的类字典对象

POST:       包含全部HTTP POST参数的类字典对象

             服务器收到空的POST请求的状况也是可能发生的,也就是说,表单form经过
             HTTP POST方法提交请求,可是表单中可能没有数据,所以不能使用
             if req.POST来判断是否使用了HTTP POST 方法;应该使用  if req.method=="POST"



COOKIES:     包含全部cookies的标准Python字典对象;keys和values都是字符串。

FILES:      包含全部上传文件的类字典对象;FILES中的每个Key都是<input type="file" name="" />标签中 
            name属性的值,FILES中的每个value同时也是一个标准的python字典对象,包含下面三个Keys:

            filename:      上传文件名,用字符串表示
            content_type:   上传文件的Content Type
            content:       上传文件的原始内容


user:       是一个django.contrib.auth.models.User对象,表明当前登录的用户。若是访问用户当前
             没有登录,user将被初始化为django.contrib.auth.models.AnonymousUser的实例。你
             能够经过user的is_authenticated()方法来辨别用户是否登录:
             if req.user.is_authenticated();只有激活Django中的AuthenticationMiddleware
             时该属性才可用

session:    惟一可读写的属性,表明当前会话的字典对象;本身有激活Django中的session支持时该属性才可用。

META:       一个标准的Python字典包含全部可用的HTTP头。可用标题取决于客户端和服务器,但这里是一些例子:

            CONTENT_LENGTH       – 请求体的长度(一个字符串)。
            CONTENT_TYPE         – 请求体的类型。
            HTTP_ACCEPT          - 为响应–能够接受的内容类型。
            HTTP_ACCEPT_ENCODING – 接受编码的响应
            HTTP_ACCEPT_LANGUAGE – 接受语言的反应
            HTTP_HOST            – 客户端发送的HTTP主机头。
            HTTP_REFERER         – 参考页面
            HTTP_USER_AGENT      – 客户端的用户代理字符串。
            QUERY_STRING         – 查询字符串,做为一个单一的(分析的)字符串。
            REMOTE_ADDR          – 客户端的IP地址
            REMOTE_HOST          – 客户端的主机名
            REMOTE_USER          – 用户经过Web服务器的身份验证。
            REQUEST_METHOD       – 字符串,如"GET""POST"
            SERVER_NAME          – 服务器的主机名
            SERVER_PORT          – 服务器的端口(一个字符串)。
复制代码

 

2. HttpResponse对象

对于HttpRequest对象来讲,是由django自动建立的,可是,HttpResponse对象就必须咱们本身建立。每一个view请求处理方法必须返回一个HttpResponse对象。

在HttpResponse对象上扩展的经常使用方法:

  • 页面渲染:render(推荐),render_to_response,
  • 页面跳转:redirect
  • locals:   能够直接将对应视图函数中全部的变量传给模板    

值得注意的是对于页面渲染的方法中,render和render_to_response使用方法和功能相似,可是render功能更为强大,推荐使用

 

3. render()

render( requesttemplate_namecontext=Nonecontent_type=Nonestatus=Noneusing=None) [source]
结合给定的模板与一个给定的上下文,返回一个字典HttpResponse在渲染文本对象

所需的参数

 template_name 一个模板的使用或模板序列名称全称。若是序列是给定的,存在于第一个模板将被使用。

可选参数

context    一组字典的值添加到模板中。默认状况下,这是一个空的字典。

content_type    MIME类型用于生成文档。

status    为响应状态代码。默认值为200

using    这个名字一个模板引擎的使用将模板。

复制代码
from django.shortcuts import render

def my_view(request):
    # View code here...
    return render(request, 'myapp/index.html', {
        'foo': 'bar',
    }, content_type='application/xhtml+xml')
复制代码

 

5、 模板

1. 模板的执行

模版的建立过程,对于模版,其实就是读取模版(其中嵌套着模版标签),而后将 Model 中获取的数据插入到模版中,最后将信息返回给用户。

  示例

 

2.  模板语言

模板中也有本身的语言,该语言能够实现数据展现

  • {{ item }}
  • {% for item in item_list %}  <a>{{ item }}</a>  {% endfor %}
      forloop.counter
      forloop.first
      forloop.last 
  • {% if ordered_warranty %}  {% else %} {% endif %}
  • 母板:{% block title %}{% endblock %}
    子板:{% extends "base.html" %}
       {% block title %}{% endblock %}
  • 帮助方法:
    {{ item.event_start|date:"Y-m-d H:i:s"}}
    {{ bio|truncatewords:"30" }}
    {{ my_list|first|upper }}
    {{ name|lower }}

 小知识点:在模板语言中字典数据类型的取值是经过dict.xxx而不是dict[xxx]

 

3. 自定义标签

由于在模板语言中不可以作运算等一些稍显复杂的操做,因此在Django中提供了两种自定制标签,一种是simple_tag,一种是filter。

simple_tag: 任意传递参数,可是不能用做布尔判断

filter: 最多只能传递二个参数,能够用做布尔判断

在这里着重介绍simple_tag类型,filter的实现相似

a、在app中建立templatetags模块

b、建立任意 .py 文件,如:xx.py

复制代码
#!/usr/bin/env python
#coding:utf-8
from django import template
from django.utils.safestring import mark_safe
from django.template.base import resolve_variable, Node, TemplateSyntaxError
  
register = template.Library()
  
@register.simple_tag
def my_simple_time(v1,v2,v3):
    return  v1 + v2 + v3
  
@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的html文件中导入以前建立的 xx.py 文件名

{% load xx %}

d、使用simple_tag

{% my_simple_time 1 2 3%}
{% my_input 'id_username' 'hide'%}

e、在settings中配置当前app,否则django没法找到自定义的simple_tag

  示例

更多见文档:https://docs.djangoproject.com/en/1.10/ref/templates/language/

 

6、 Model

Django提供了一个抽象层(“Model”)来构建和管理Web应用程序的数据。

django中遵循 Code Frist 的原则,即:根据代码中定义的类来自动生成数据库表。

关系对象映射(Object Relational Mapping,简称ORM)。

 

1. 建立表

a、基本结构

1
2
3
4
5
6
from  django.db  import  models
    
  class  userinfo(models.Model):
     name  =  models.CharField(max_length = 30 )
     email  =  models.EmailField()
     memo  =  models.TextField()
复制代码
一、null=True
  数据库中字段是否能够为空
二、blank=True
  django的 Admin 中添加数据时是否可容许空值
三、primary_key = False
  主键,对AutoField设置主键后,就会代替原来的自增 id 列
4、auto_now 和 auto_now_add
  auto_now   自动建立---不管添加或修改,都是当前操做的时间
  auto_now_add  自动建立---永远是建立时的时间
5、choices
GENDER_CHOICE = (
        (u'M', u'Male'),
        (u'F', u'Female'),
    )
gender = models.CharField(max_length=2,choices = GENDER_CHOICE)
6、max_length
7、default  默认值
8、verbose_name  Admin中字段的显示名称
九、name|db_column  数据库中的字段名称
十、unique=True  不容许重复
十一、db_index = True  数据库索引
十二、editable=True  在Admin里是否可编辑
1三、error_messages=None  错误提示
1四、auto_created=False  自动建立
15、help_text  在Admin中提示帮助信息
1六、validators=[]
1七、upload-to
复制代码
复制代码
一、models.AutoField  自增列 = int(11)
  若是没有的话,默认会生成一个名称为 id 的列,若是要显示的自定义一个自增列,必须将给列设置为主键 primary_key=True。
2、models.CharField  字符串字段
  必须 max_length 参数
三、models.BooleanField  布尔类型=tinyint(1)
  不能为空,Blank=True
四、models.ComaSeparatedIntegerField  用逗号分割的数字=varchar
  继承CharField,因此必须 max_lenght 参数
5、models.DateField  日期类型 date
  对于参数,auto_now = True 则每次更新都会更新这个时间;auto_now_add 则只是第一次建立添加,以后的更新再也不改变。
6、models.DateTimeField  日期类型 datetime
  同DateField的参数
七、models.Decimal  十进制小数类型 = decimal
  必须指定整数位max_digits和小数位decimal_places
八、models.EmailField  字符串类型(正则表达式邮箱) =varchar
  对字符串进行正则表达式
九、models.FloatField  浮点类型 = double
10、models.IntegerField  整形
11、models.BigIntegerField  长整形
  integer_field_ranges = {
    'SmallIntegerField': (-32768, 32767),
    'IntegerField': (-2147483648, 2147483647),
    'BigIntegerField': (-9223372036854775808, 9223372036854775807),
    'PositiveSmallIntegerField': (0, 32767),
    'PositiveIntegerField': (0, 2147483647),
  }
12、models.IPAddressField  字符串类型(ip4正则表达式)
13、models.GenericIPAddressField  字符串类型(ip4和ip6是可选的)
  参数protocol能够是:both、ipv四、ipv6
  验证时,会根据设置报错
14、models.NullBooleanField  容许为空的布尔类型
15、models.PositiveIntegerFiel  正Integer
16、models.PositiveSmallIntegerField  正smallInteger
17、models.SlugField  减号、下划线、字母、数字
18、models.SmallIntegerField  数字
  数据库中的字段有:tinyint、smallint、int、bigint
1九、models.TextField  字符串=longtext
20、models.TimeField  时间 HH:MM[:ss[.uuuuuu]]
21、models.URLField  字符串,地址正则表达式
22、models.BinaryField  二进制
23、models.ImageField   图片
2四、models.FilePathField 文件
复制代码
复制代码
class UserInfo(models.Model):
        nid = models.AutoField(primary_key=True)
        username = models.CharField(max_length=32)
        class Meta:
            # 数据库中生成的表名称 默认 app名称 + 下划线 + 类名
            db_table = "table_name"

            # 联合索引
            index_together = [
                ("pub_date", "deadline"),
            ]

            # 联合惟一索引
            unique_together = (("driver", "restaurant"),)

            # admin中显示的表名称
            verbose_name

            # verbose_name加s
            verbose_name_plural
        
    更多:https://docs.djangoproject.com/en/1.10/ref/models/options/
复制代码
复制代码
1.触发Model中的验证和错误提示有两种方式:
        a. Django Admin中的错误信息会优先根据Admiin内部的ModelForm错误信息提示,若是都成功,才来检查Model的字段并显示指定错误信息
        b. 调用Model对象的 clean_fields 方法,如:
            # models.py
            class UserInfo(models.Model):
                nid = models.AutoField(primary_key=True)
                username = models.CharField(max_length=32)

                email = models.EmailField(error_messages={'invalid': '格式错了.'})

            # views.py
            def index(request):
                obj = models.UserInfo(username='11234', email='uu')
                try:
                    print(obj.clean_fields())
                except Exception as e:
                    print(e)
                return HttpResponse('ok')

           # Model的clean方法是一个钩子,可用于定制操做,如:上述的异常处理。

    2.Admin中修改错误提示
        # admin.py
        from django.contrib import admin
        from model_club import models
        from django import forms


        class UserInfoForm(forms.ModelForm):
            username = forms.CharField(error_messages={'required': '用户名不能为空.'})
            email = forms.EmailField(error_messages={'invalid': '邮箱格式错误.'})
            age = forms.IntegerField(initial=1, error_messages={'required': '请输入数值.', 'invalid': '年龄必须为数值.'})

            class Meta:
                model = models.UserInfo
                # fields = ('username',)
                fields = "__all__"


        class UserInfoAdmin(admin.ModelAdmin):
            form = UserInfoForm


        admin.site.register(models.UserInfo, UserInfoAdmin)
复制代码

 

b、连表结构

  • 一对多:models.ForeignKey(其余表)
  • 多对多:models.ManyToManyField(其余表)
  • 一对一:models.OneToOneField(其余表)

应用场景:

  • 一对多:当一张表中建立一行数据时,有一个单选的下拉框(能够被重复选择)
    例如:建立用户信息时候,须要选择一个用户类型【普通用户】【金牌用户】【铂金用户】等。
  • 多对多:在某表中建立一行数据是,有一个能够多选的下拉框
    例如:建立用户信息,须要为用户指定多个爱好
  • 一对一:在某表中建立一行数据时,有一个单选的下拉框(下拉框中的内容被用过一次就消失了
    例如:原有含10列数据的一张表保存相关信息,通过一段时间以后,10列没法知足需求,须要为原来的表再添加5列数据
  字段以及参数

 

2. 操做表

a、基本操做

  基本操做

 

b、进阶操做(了不得的双下划线

利用双下划线将字段和对应的操做链接起来

复制代码
# 获取个数
        #
        # models.Tb1.objects.filter(name='seven').count()

        # 大于,小于
        #
        # models.Tb1.objects.filter(id__gt=1)              # 获取id大于1的值
        # models.Tb1.objects.filter(id__gte=1)              # 获取id大于等于1的值
        # models.Tb1.objects.filter(id__lt=10)             # 获取id小于10的值
        # models.Tb1.objects.filter(id__lte=10)             # 获取id小于10的值
        # models.Tb1.objects.filter(id__lt=10, id__gt=1)   # 获取id大于1 且 小于10的值

        # in
        #
        # models.Tb1.objects.filter(id__in=[11, 22, 33])   # 获取id等于十一、2二、33的数据
        # models.Tb1.objects.exclude(id__in=[11, 22, 33])  # not in

        # isnull
        # Entry.objects.filter(pub_date__isnull=True)

        # contains
        #
        # models.Tb1.objects.filter(name__contains="ven")
        # models.Tb1.objects.filter(name__icontains="ven") # icontains大小写不敏感
        # models.Tb1.objects.exclude(name__icontains="ven")

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

        # 其余相似
        #
        # 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

        # group by
        #
        # from django.db.models import Count, Min, Max, Sum
        # models.Tb1.objects.filter(c1=1).values('id').annotate(c=Count('num'))
        # SELECT "app01_tb1"."id", COUNT("app01_tb1"."num") AS "c" FROM "app01_tb1" WHERE "app01_tb1"."c1" = 1 GROUP BY "app01_tb1"."id"

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

        # regex正则匹配,iregex 不区分大小写
        #
        # Entry.objects.get(title__regex=r'^(An?|The) +')
        # Entry.objects.get(title__iregex=r'^(an?|the) +')

        # date
        #
        # Entry.objects.filter(pub_date__date=datetime.date(2005, 1, 1))
        # Entry.objects.filter(pub_date__date__gt=datetime.date(2005, 1, 1))

        # year
        #
        # Entry.objects.filter(pub_date__year=2005)
        # Entry.objects.filter(pub_date__year__gte=2005)

        # month
        #
        # Entry.objects.filter(pub_date__month=12)
        # Entry.objects.filter(pub_date__month__gte=6)

        # day
        #
        # Entry.objects.filter(pub_date__day=3)
        # Entry.objects.filter(pub_date__day__gte=3)

        # week_day
        #
        # Entry.objects.filter(pub_date__week_day=2)
        # Entry.objects.filter(pub_date__week_day__gte=2)

        # hour
        #
        # Event.objects.filter(timestamp__hour=23)
        # Event.objects.filter(time__hour=5)
        # Event.objects.filter(timestamp__hour__gte=12)

        # minute
        #
        # Event.objects.filter(timestamp__minute=29)
        # Event.objects.filter(time__minute=46)
        # Event.objects.filter(timestamp__minute__gte=29)

        # second
        #
        # Event.objects.filter(timestamp__second=31)
        # Event.objects.filter(time__second=2)
        # Event.objects.filter(timestamp__second__gte=31)
复制代码

 

c、其余操做

复制代码
# extra
    #
    # extra(self, select=None, where=None, params=None, tables=None, order_by=None, select_params=None)
    #    Entry.objects.extra(select={'new_id': "select col from sometable where othercol > %s"}, select_params=(1,))
    #    Entry.objects.extra(where=['headline=%s'], params=['Lennon'])
    #    Entry.objects.extra(where=["foo='a' OR bar = 'a'", "baz = 'a'"])
    #    Entry.objects.extra(select={'new_id': "select id from tb where id > %s"}, select_params=(1,), order_by=['-nid'])

    # F
    #
    # from django.db.models import F
    # models.Tb1.objects.update(num=F('num')+1)


    # Q
    #
    # 方式一:
    # Q(nid__gt=10)
    # Q(nid=8) | Q(nid__gt=10)
    # Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption='root')
    # 方式二:
    # con = Q()
    # q1 = Q()
    # q1.connector = 'OR'
    # q1.children.append(('id', 1))
    # q1.children.append(('id', 10))
    # q1.children.append(('id', 9))
    # q2 = Q()
    # q2.connector = 'OR'
    # q2.children.append(('c1', 1))
    # q2.children.append(('c1', 10))
    # q2.children.append(('c1', 9))
    # con.add(q1, 'AND')
    # con.add(q2, 'AND')
    #
    # models.Tb1.objects.filter(con)


    # 执行原生SQL
    #
    # from django.db import connection, connections
    # cursor = connection.cursor()  # cursor = connections['default'].cursor()
    # cursor.execute("""SELECT * from auth_user where id = %s""", [1])
    # row = cursor.fetchone()
复制代码

 

d、连表操做(了不得的双下划线)

利用双下划线和 _set 将表之间的操做链接起来

  表结构实例
  一对一操做
  一对多
  多对多操做

 

扩展:

a、自定义上传

复制代码
def upload_file(request):
    if request.method == "POST":
        obj = request.FILES.get('fafafa')
        f = open(obj.name, 'wb')
        for chunk in obj.chunks():
            f.write(chunk)
        f.close()
    return render(request, 'file.html')
复制代码

b、Form上传文件实例

复制代码
# HTML

       <form method="post" action="/view1/" enctype="multipart/form-data">
           <input type="file" name="ExcelFile" id="id_ExcelFile" />
           <input type="submit" value="提交" />
       </form>



# Form

class FileForm(forms.Form):
    ExcelFile = forms.FileField()

# Models

from django.db import models

class UploadFile(models.Model):
    userid = models.CharField(max_length = 30)
    file = models.FileField(upload_to = './upload/')
    date = models.DateTimeField(auto_now_add=True)

# Views

def UploadFile(request):
    uf = AssetForm.FileForm(request.POST,request.FILES)
    if uf.is_valid():
            upload = models.UploadFile()
            upload.userid = 1
            upload.file = uf.cleaned_data['ExcelFile']
            upload.save()
            
            print upload.file
复制代码

c、ajax上传文件实例

复制代码
<div>
       {{ up.ExcelFile }}
       <input type="button" id="submitj" value="提交" />
   </div>


<script src="/static/js/jquery-2.1.4.min.js"></script>
<script>
    $('#submitj').bind("click",function () {
        var file = $('#id_ExcelFile')[0].files[0];
        var form = new FormData();
        form.append('ExcelFile', file);
         $.ajax({
                type:'POST',
                url: '/view1/',
                data: form,
                processData: false,  // tell jQuery not to process the data
                contentType: false,  // tell jQuery not to set contentType
                success: function(arg){
                    console.log(arg);
                }
            })
    })
</script>
复制代码
class FileForm(forms.Form):
    ExcelFile = forms.FileField()
复制代码
from django.db import models

class UploadFile(models.Model):
    userid = models.CharField(max_length = 30)
    file = models.FileField(upload_to = './upload/')
    date = models.DateTimeField(auto_now_add=True)
复制代码
复制代码
from study1 import forms

def UploadFile(request):
    uf = AssetForm.FileForm(request.POST,request.FILES)
    if uf.is_valid():
            upload = models.UploadFile()
            upload.userid = 1
            upload.file = uf.cleaned_data['ExcelFile']
            upload.save()
            
            print upload.file

return render(request, 'file.html', locals())
复制代码

 

7、中间件(MiddleWare)

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

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

与mange.py在同一目录下的文件夹 wupeiqi/middleware下的auth.py文件中的Authentication类

中间件中能够定义五个方法,分别是:

  • process_request(self,request)
  • process_view(self, request, callback, callback_args, callback_kwargs)
  • process_template_response(self,request,response)
  • process_exception(self, request, exception)
  • process_response(self, request, response)

分析源码得知前二个方法是从前日后执行的,后三个方法是从后往前执行的

 因此前两个方法是请求进来时要穿越的,然后三个方法是请求出去时要穿越的

一张图告诉你中间件的运行流程

 

自定义中间件

一、建立中间件类

1
2
3
4
5
6
7
8
9
10
11
12
class  Middle_Test( object ):
       
     def  process_request( self ,request):
         pass
     def  process_view( self , request, callback, callback_args, callback_kwargs):
         = 1
         pass
     def  process_exception( self , request, exception):
         pass
       
     def  process_response( self , request, response):
         return  response

  

二、注册中间件

1
2
3
4
5
6
7
8
9
10
MIDDLEWARE_CLASSES  =  (
     'django.contrib.sessions.middleware.SessionMiddleware' ,
     'django.middleware.common.CommonMiddleware' ,
     'django.middleware.csrf.CsrfViewMiddleware' ,
     'django.contrib.auth.middleware.AuthenticationMiddleware' ,
     'django.contrib.auth.middleware.SessionAuthenticationMiddleware' ,
     'django.contrib.messages.middleware.MessageMiddleware' ,
     'django.middleware.clickjacking.XFrameOptionsMiddleware' ,
     'sparks.middleware.auth.Middle_Test' ,
)

  

8、 Form

django中的Form通常有两种功能:

  • 输入html
  • 验证用户输入
  Form
  示例

 

利用Form还能够自动生成前端的input标签:

  form.py
  views.py
  form1.html

 

扩展:ModelForm

在使用Model和Form时,都须要对字段进行定义并指定类型,经过ModelForm则能够省去From中字段的定义

  ModelForm

 

 

 

9、 认证系统(auth)

auth模块是Django提供的标准权限管理系统,能够提供用户身份认证, 用户组管理,而且能够和admin模块配合使用.

在INSTALLED_APPS中添加'django.contrib.auth'使用该APP, auth模块默认启用.

model

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from  django.contrib.auth.models  import  User
 
# 数据库中该表名为auth_user.
CREATE TABLE  "auth_user"  (
     "id"  integer NOT NULL PRIMARY KEY AUTOINCREMENT,
     "password"  varchar( 128 ) NOT NULL,  "last_login"  datetime NULL,
     "is_superuser"  bool  NOT NULL,
     "first_name"  varchar( 30 ) NOT NULL,
     "last_name"  varchar( 30 ) NOT NULL,
     "email"  varchar( 254 ) NOT NULL,
     "is_staff"  bool  NOT NULL,
     "is_active"  bool  NOT NULL,
     "date_joined"  datetime NOT NULL,
     "username"  varchar( 30 ) NOT NULL UNIQUE
)

新建用户

user = User.objects.create_user(username, email, password)
user.save()

# 不存储用户密码明文而是存储一个Hash值

认证用户

复制代码
复制代码
from django.contrib.auth import authenticate

user = authenticate(username=username, password=password)

# 认证用户的密码是否有效, 如有效则返回表明该用户的user对象, 若无效则返回None.
# 该方法不检查is_active标志位.
复制代码
复制代码

修改密码

复制代码
复制代码
user.set_password(new_password)

# 如下实例为先认证经过后才能够修改密码
user = auth.authenticate(username=username, password=old_password)
if user is not None:
    user.set_password(new_password)
    user.save()
复制代码
复制代码

登陆

复制代码
复制代码
from django.contrib.auth import login

# login向session中添加SESSION_KEY, 便于对用户进行跟踪:
'login(request, user)'

# login不进行认证,也不检查is_active标志位
# 实例
user = authenticate(username=username, password=password)
if user is not None:
    if user.is_active:
        login(request, user)
复制代码
复制代码

退出登陆

复制代码
复制代码
# logout会移除request中的user信息, 并刷新session

from django.contrib.auth import logout

def logout_view(request):
    logout(request)
复制代码
复制代码

只容许登陆的用户访问

@login_required修饰器修饰的view函数会先经过session key检查是否登陆, 已登陆用户能够正常的执行操做, 未登陆用户将被重定向到login_url指定的位置.

若未指定login_url参数, 则重定向到settings.LOGIN_URL

复制代码
复制代码
from django.contrib.auth.decorators import login_required

@login_required(login_url='/accounts/login/')
def userinfo(request):
    ...

# settings 配置
LOGIN_URL = '/index/'
# views
@login_required
def userinfo(request):
    ...
复制代码
复制代码

 

 

10、 跨站请求伪造(csrf)

django为用户实现防止跨站请求伪造的功能,经过中间件 django.middleware.csrf.CsrfViewMiddleware 来完成。而对于django中设置防跨站请求伪造功能有分为全局和局部。

全局:

  中间件 django.middleware.csrf.CsrfViewMiddleware

局部:

  • @csrf_protect,为当前函数强制设置防跨站请求伪造功能,即使settings中没有设置全局中间件。
  • @csrf_exempt,取消当前函数防跨站请求伪造功能,即使settings中设置了全局中间件。

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

  在Django1.10中,为了防止BREACH攻击,对cookie-form类型的csrf作了一点改进,即在cookie和form中的token值是不相同的

 

应用

一、普通表单

1
2
3
4
5
veiw中设置返回值:
      return  render(request,  'xxx.html' , data)
   
html中设置Token:
  { %  csrf_token  % }

  

二、Ajax

对于传统的form,能够经过表单的方式将token再次发送到服务端,而对于ajax的话,使用以下方式。

  view.py
  text.html

更多:https://docs.djangoproject.com/en/dev/ref/csrf/#ajax

 

11、 分页

1. Django内置分页

  views.py
  Html
  扩展内置分页:views.py
  扩展内置分页:Html

2. 自定义分页

分页功能在每一个网站都是必要的,对于分页来讲,其实就是根据用户的输入计算出应该在数据库表中的起始位置。

一、设定每页显示数据条数

二、用户输入页码(第一页、第二页...)

三、根据设定的每页显示条数和当前页码,计算出须要取数据表的起始位置

四、在数据表中根据起始位置取值,页面上输出数据


需求又来了,须要在页面上显示分页的页面。如:[上一页][1][2][3][4][5][下一页]

一、设定每页显示数据条数

二、用户输入页码(第一页、第二页...)

三、设定显示多少页号

四、获取当前数据总条数

五、根据设定显示多少页号和数据总条数计算出,总页数

六、根据设定的每页显示条数和当前页码,计算出须要取数据表的起始位置

七、在数据表中根据起始位置取值,页面上输出数据

八、输出分页html,如:[上一页][1][2][3][4][5][下一页]

  分页实例

总结,分页时须要作三件事:

  • 建立处理分页数据的类
  • 根据分页数据获取数据
  • 输出分页HTML,即:[上一页][1][2][3][4][5][下一页]

 

12、 Cookie

1. 获取Cookie:

1
2
3
4
5
6
request.COOKIES[ 'key' ]
request.get_signed_cookie(key, default = RAISE_ERROR, salt = '', max_age = None )
     参数:
         default: 默认值
            salt: 加密盐
         max_age: 后台控制过时时间

2. 设置Cookie:

1
2
3
4
5
6
7
8
9
10
11
12
13
rep  =  HttpResponse(...) 或 rep = render(request, ...)
 
rep.set_cookie(key,value,...)
rep.set_signed_cookie(key,value,salt = '加密盐' ,...)
     参数:
         key,              键
         value = '',         值
         max_age = None ,     超时时间
         expires = None ,     超时时间(IE requires expires, so  set  it  if  hasn't been already.)
         path = '/' ,         Cookie生效的路径, /  表示根路径,特殊的:跟路径的cookie能够被任何url的页面访问
         domain = None ,      Cookie生效的域名
         secure = False ,     https传输
         httponly = False     只能http协议传输,没法被JavaScript获取(不是绝对,底层抓包能够获取到也能够被覆盖)

因为cookie保存在客户端的电脑上,因此,JavaScript和jquery也能够操做cookie。

1
2
<script src = '/static/js/jquery.cookie.js' >< / script>
$.cookie( "list_pager_num" 30 ,{ path:  '/'  });

 

十3、 Session

Django中默认支持Session,其内部提供了5种类型的Session供开发者使用:

  • 数据库(默认)
  • 缓存
  • 文件
  • 缓存+数据库
  • 加密cookie

一、数据库Session

  View Code

二、缓存Session

  View Code

三、文件Session

  View Code

四、缓存+数据库Session

  View Code

五、加密cookie Session

  View Code

跟数据库的操做同样,在Django中不一样缓存方式的使用方法是一致的,想要改变缓存的类型只须要改变上述相应配置便可。

更多参考:猛击这里 和 猛击这里

扩展:Session用户验证(装饰器)

1
2
3
4
5
6
7
def  login(func):
     def  wrap(request,  * args,  * * kwargs):
         # 若是未登录,跳转到指定页面
         if  request.path  = =  '/test/' :
             return  redirect( 'http://www.baidu.com' )
         return  func(request,  * args,  * * kwargs)
     return  wrap

  

十4、 缓存

因为Django是动态网站,全部每次请求均会去数据进行相应的操做,当程序访问量大时,耗时必然会更加明显,最简单解决方式是使用:缓存,缓存将一个某个views的返回值保存至内存或者memcache中,5分钟内再有人来访问时,则再也不去执行view中的操做,而是直接从内存或者Redis中以前缓存的内容拿到,并返回。

Django中提供了6种缓存方式:

  • 开发调试
  • 内存
  • 文件
  • 数据库
  • Memcache缓存(python-memcached模块)
  • Memcache缓存(pylibmc模块)

和数据库相似,缓存的具体操做都是同样的,使用不一样的方式只须要将配置改掉便可

一、配置

a、开发调试

  View Code

b、内存

  View Code

c、文件

  View Code

d、数据库

  View Code

e、Memcache缓存(python-memcached模块)

  View Code

f、Memcache缓存(pylibmc模块)

  View Code

 

二、应用

a. 全站使用

  View Code

b. 单独视图缓存

  View Code

c、局部视图使用

  View Code

注:若是出现多个url匹配同一个view函数的状况,缓存机制会根据每个不一样的url作单独的缓存

更多:猛击这里

 

 

十5、 序列化

关于Django中的序列化主要应用在将数据库中检索的数据返回给客户端用户,特别的Ajax请求通常返回的为Json格式。

1. serializers

1
2
3
4
5
from  django.core  import  serializers
 
ret  =  models.BookType.objects. all ()
 
data  =  serializers.serialize( "json" , ret)

2. json.dumps

1
2
3
4
5
6
7
8
import  json
 
#ret = models.BookType.objects.all().values('caption')
ret  =  models.BookType.objects. all ().values_list( 'caption' )
 
ret = list (ret)
 
result  =  json.dumps(ret)

因为json.dumps时没法处理datetime日期,因此能够经过自定义处理器来作扩展,如:

  自定义示例

 

十6、 信号

Django中提供了“信号调度”,用于在框架执行操做时解耦。通俗来说,就是一些动做发生的时候,信号容许特定的发送者去提醒一些接受者。

一、Django内置信号

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Model signals
     pre_init                     # django的modal执行其构造方法前,自动触发
     post_init                    # django的modal执行其构造方法后,自动触发
     pre_save                     # django的modal对象保存前,自动触发
     post_save                    # django的modal对象保存后,自动触发
     pre_delete                   # django的modal对象删除前,自动触发
     post_delete                  # django的modal对象删除后,自动触发
     m2m_changed                  # django的modal中使用m2m字段操做第三张表(add,remove,clear)先后,自动触发
     class_prepared               # 程序启动时,检测已注册的app中modal类,对于每个类,自动触发
Management signals
     pre_migrate                  # 执行migrate命令前,自动触发
     post_migrate                 # 执行migrate命令后,自动触发
Request / response signals
     request_started              # 请求到来前,自动触发
     request_finished             # 请求结束后,自动触发
     got_request_exception        # 请求异常后,自动触发
Test signals
     setting_changed              # 使用test测试修改配置文件时,自动触发
     template_rendered            # 使用test测试渲染模板时,自动触发
Database Wrappers
     connection_created           # 建立数据库链接时,自动触发

对于Django内置的信号,仅需注册指定信号,当程序执行相应操做时,自动触发注册函数:

  View Code

 

二、自定义信号

a. 定义并注册信号

1
2
3
4
5
6
7
8
9
# 自定制信号
import  django.dispatch
pizza_done  =  django.dispatch.Signal(providing_args = [ "toppings" "size" ])
 
def  callback(sender,  * * kwargs):
     print ( "self-define" )
     print (sender, kwargs)
 
pizza_done.connect(callback)

  

b. 触发信号

1
2
3
from  路径  import  pizza_done
  
pizza_done.send(sender = 'seven' ,toppings = 123 , size = 456 )

  

因为内置信号的触发者已经集成到Django中,因此其会自动调用,而对于自定义信号则须要开发者在任意位置触发。

更多:猛击这里

 

十7、admin

django amdin是django提供的一个后台管理页面,改管理页面提供完善的html和css,使得你在经过Model建立完数据库表以后,就能够对数据进行增删改查,而使用django admin 则须要如下步骤:

  • 建立后台管理员
  • 配置url
  • 注册和配置django admin后台管理页面

注:不建议新手常用admin,会造成依赖,核心的是model模块的操做!

一、建立后台管理员

python manage.py createsuperuser

二、配置后台管理url(默认已配)

url(r '^admin/' , include(admin.site.urls))

三、注册和配置django admin 后台管理页面

a、在admin中执行以下配置
  View Code
b、设置数据表名称
  View Code
c、打开表以后,设定默认显示,须要在model中做以下配置
  View Code
d、为数据表添加搜索功能
  View Code
e、添加快速过滤
  View Code

更多:https://docs.djangoproject.com/en/1.11/ref/contrib/admin/