Python全栈开发之21django

Posted 1000-7

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python全栈开发之21django相关的知识,希望对你有一定的参考价值。

http://www.cnblogs.com/wupeiqi/articles/5237704.html

http://www.cnblogs.com/wupeiqi/articles/5246483.html

http://www.cnblogs.com/yuanchenqi/articles/5786089.html

基本配置

常用命令

  django-admin startproject sitename

  python manage.py runserver 0.0.0.0
  python manage.py startapp appname
  python manage.py syncdb
  python manage.py makemigrations
  python manage.py migrate

  python manage.py createsuperuser

二、数据库配置(mysql)

DATABASES = {
    \'default\': {
    \'ENGINE\': \'django.db.backends.mysql\',
    \'NAME\':\'dbname\',
    \'USER\': \'root\',
    \'PASSWORD\': \'xxx\',
    \'HOST\': \'\',
    \'PORT\': \'\',
    }
}


# 由于Django内部连接MySQL时使用的是MySQLdb模块,而python3中还无此模块,所以需要使用pymysql来代替
# 如下设置放置的与project同名的配置的 __init__.py文件中
  
import pymysql
pymysql.install_as_MySQLdb()

三、配置模板和静态文件

TEMPLATE_DIRS = (
        os.path.join(BASE_DIR,\'templates\'),
    )
\'DIRS\': [os.path.join(BASE_DIR, \'templates\'), ],
STATICFILES_DIRS = ( os.path.join(BASE_DIR,\'static\'), ) # 特有的静态文件夹放在app里面, # 模板里面使用静态文件 <script src="/static/jquery-1.12.4.js"></script>

最后记得在setting里面注册app

Django流程

一、MTV模式

MVC模式:所谓MVC就是把web应用分为模型(M),控制器(C),视图(V)三层;他们之间以一种插件似的,松耦合的方式连接在一起。模型负责业务对象与数据库的对象(ORM),视图负责与用户的交互(页面),控制器(C)接受用户的输入调用模型和视图完成用户的请求。

               

Django的MTV模式本质上与MVC模式没有什么差别,也是各组件之间为了保持松耦合关系,只是定义上有些许不同,Django的MTV分别代表:

       Model(模型):负责业务对象与数据库的对象(ORM)

       Template(模版):负责如何把页面展示给用户

       View(视图):负责业务逻辑,并在适当的时候调用Model和Template

       此外,Django还有一个url分发器,它的作用是将一个个URL的页面请求分发给不同的view处理,view再调用相应的Model和Template

路由系统

URL模式以及要为该URL模式调用的视图函数之间的映射表,每个路由对应一个view中的函数,对于这个URL调用这段代码,对于那个URL调用那段代码

参数说明:

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

传递的参数始终是字符串

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/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$\', views.month_archive),
    
     # 路由分发
    url(r\'^contact/\', include(\'django_website.contact.urls\')),

    # 传给视图的默认参数,对应的视图函数也必须加上同名的参数
    url(r\'^blog/(?P<year>[0-9]{4})/$\', views.year_archive, {\'foo\': \'bar\'}),

    #name参数   
    url(r\'^index\',views.index,name=\'bieming\'),   
]

常见写法实例

  

urlpatterns = [
    url(r\'car\', views.car, {\'name\': \'jaon\'},),
    url(r\'index\', views.index, name=\'alias_login\',),
    # url(r\'index55555\', views.index, name=\'alias_login\',),
]


def car(request, name):
    return HttpResponse(\'car\'+name)

def index(request,):
    if request.method == \'POST\':
        username = request.POST.get(\'username\')
        print(username)
        if username == \'jason\':
            return HttpResponse(\'ok\')
        else:
            return HttpResponse(\'error\')
    return render(request, \'login.html\')

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form action="{% url \'alias_login\' %}" method="post">
        <input type="text" name="username">
        <input type="submit" value="提交">
    </form>
</body>
</html>

视图函数  

1、HttpRequest对象的属性:

# 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支持时该属性才可用。

HttpRequest对象的方法:get_full_path(),   比如:http://127.0.0.1:8000/index33/?name=123 ,req.get_full_path()得到的结果就是/index33/?name=123

2、HttpResponse对象:

对于HttpRequest对象来说,是由django自动创建的,但是,HttpResponse对象就必须我们自己创建。每个view请求处理方法必须返回一个HttpResponse对象。

  HttpResponse类在django.http.HttpResponse

  在HttpResponse对象上扩展的常用方法:页面渲染:render,render_to_response,

                                                        页面跳转:redirect

                                                        locals:   可以直接将函数中所有的变量传给模板    

         

         

django的ORM

这里先创建几张表,分别是一对多和多对多,其中一对一就是一对多的时候外键唯一

from django.db import models

# Create your models here.


class UserType(models.Model):
    nid = models.AutoField(primary_key=True)
    caption = models.CharField(max_length=32)


class UserInfo(models.Model):
    user = models.CharField(max_length=16)
    pwd = models.CharField(max_length=16)
    email = models.EmailField()
    userType = models.ForeignKey(UserType)


class Group(models.Model):
    name = models.CharField(max_length=16)
    h2g = models.ManyToManyField(\'Host\')


class Host(models.Model):
    hostname = models.CharField(max_length=16)
    ip = models.CharField(max_length=16)

下面来看一下表的增删改查的简单操作

#  第一种方式创建
    # usertype = models.UserType(caption=\'管理员\')
    # usertype.save()

    # 第二种方式创建
    # models.UserType.objects.create(caption=\'普通用户\')

    # 第三种
    # userTypeDict = {\'caption\': \'协管员\'}
    # models.UserType.objects.create(**userTypeDict)

    # 带外键添加数据库 推荐使用
    # userInfoDict = {
    #     \'user\': \'jason\',
    #     \'email\': \'jason123@qq.com\',
    #     \'pwd\': \'123\',
    #     \'userType_id\': 2,
    # }

    # userInfoDict = {
    #     \'user\': \'jason2\',
    #     \'email\': \'jason26663@qq.com\',
    #     \'pwd\': \'123\',
    #     \'userType\': models.UserType.objects.filter(nid=2).first(),
    # }

    # models.UserInfo.objects.create(**userInfoDict)

    # 删除
    # models.UserType.objects.filter(nid=3).delete()

    # 修改
    # models.UserType.objects.filter(nid=1).update(caption=\'超级管理员\')



    # 查询 查询结果是QuerySet
    # ret = models.UserType.objects.all()    # select会获取所有的映射
    # print(type(ret), ret, ret.query)       # ret 里面保存的是对象

    # ret = models.UserType.objects.all().values(\'nid\')  # 获取指定映射
    # print(type(ret), ret, ret.query)        # ret 里面保存的是字典

    # ret = models.UserType.objects.all().values_list(\'nid\')  # 获取指定映射
    # print(type(ret), ret, ret.query)  # ret 里面保存的是元祖

再来看一下一对多连表查找操作

# 连表 双下划线使用,注意什么情况下使用 表名_set 什么情况下使用 表名__字段
    # (表名_set 获取QuerySet对象) (表名__字段,查找过滤映射的时候用)

    # 正向查找,再多的一方查找一的一方
    # ret = models.UserInfo.objects.all().values(\'user\', \'userType__caption\')
    # print(ret)

    # ret = models.UserInfo.objects.filter(userType__caption="普通用户").values(\'user\', \'userType__caption\')
    # print(ret)

    # 反向查找 在一的一方查找多的一方
    # 在获取了一对多中一那一方的对象之后,要获取多的那一方对象使用反向表名_set
    # ret = models.UserType.objects.filter(caption=\'普通用户\').first()
    # print(ret.nid, ret.userinfo_set, ret.userinfo_set.all(), ret.userinfo_set.all()[0].user)

    # 直接在一对多一那一方使用查找或者过滤映射的时候使用反向表名__字段
    # ret = models.UserType.objects.all().values(\'caption\', \'userinfo__user\')
    # print(ret)

最后看一下多对多连表查找操作

\'\'\'
        创建表:
        直接使用m2m
        自已定义第三张表
        自已定义第三张表 + m2m(through) 可以通过through参数来指明存在的表

        直接使用m2m
            --- 获取值
            add添加
            remove删除(关系表),filter.delete()(关系表+..)
            set设置(添加、删除)
            get_or_create
            update_or_create

        自已定义第三张表 + m2m + through
            --关系表只能获取值 filter,all...
            通过第三张表进行操作


    \'\'\'
    \'\'\'
        # 直接使用
        class Host(models.Model):
            hid = models.AutoField(primary_key=True)
            hostname = models.CharField(max_length=32)
            ip =  models.CharField(max_length=32)
            # h2g = models.ManyToManyField(\'Group\')
        class Group(models.Model):
            gid = models.AutoField(primary_key=True)
            name = models.CharField(max_length=16)
        
            h2g = models.ManyToManyField(\'Host\')
    
    
    
        # 自定义第三张表
        # class Host(models.Model):
        #     hid = models.AutoField(primary_key=True)
        #     hostname = models.CharField(max_length=32)
        #     ip =  models.CharField(max_length=32)
        #     # h2g = models.ManyToManyField(\'Group\', through=\'HostToGroup\')
        # class Group(models.Model):
        #     gid = models.AutoField(primary_key=True)
        #     name = models.CharField(max_length=16)
        #
        #     h2g = models.ManyToManyField(\'Host\')
        #
        # class HostToGroup(models.Model):
        #     hgid = models.AutoField(primary_key=True)
        #     host_id = models.ForeignKey(\'Host\')
        #     group_id = models.ForeignKey(\'Group\')
        #     status = models.IntegerField()
        #     class Meta:
        #         # index_together = ("host_id",\'goup_id\') 组合索引
        #         unique_together = [
        #             (\'host_id\', \'group_id\'),             组合唯一索引
        #         ]

    \'\'\'
# 将多台机器分给一组 正向
    # obj = models.Group.objects.get(id=1)

    # hosts = models.Host.objects.filter(id__gt=2)
    # obj.h2g.add(*hosts)

    # host = models.Host.objects.get(id=2)
    # obj.h2g.add(host)

    # 给多个组分一台机器 反向
    # h = models.Host.objects.get(id=1)
    # h.group_set.add(*models.Group.objects.filter(id__gt=2))
    # h.group_set.add(2)   # 可以直接添加id或对象
    
    

    # h.group_set.remove(*models.Group.objects.filter(id__gt=3))  # 只删除关系表
    # h.group_set.filter(id__gt=2).delete()  # group_id>2 的关系表删除了,相应的group表数据也被删除了

    # h.group_set.set(models.Group.objects.filter(id__gt=1), clear=True) #大于1的全部清除在添加

    # h.group_set.set(models.Group.objects.filter(id__gt=2))  # 大于2 以前存在的不清除,不存在的添加

    # h.group_set.set(models.Group.objects.filter(id__gt=4))  # 小于5的被清除

    # r = h.group_set.update_or_create(name=\'人事部\')  # 两张表都不存在,先在group表创建在添加到关系表中去
    # print(r)

    # r = h.group_set.update_or_create(name=\'pm\')         # 和上面的效果一样,为什么

    # h.group_set.get_or_create(name=\'te\')    # 和上面的效果一样

具体操作

补充:

  一次插入多条数据

 author_list = []
    for i in range(7):
        name = \'alex\' + str(i)
        age = i
        author = models.Author(name=name, age=age)
        author_list.append(author)
    models.Author.objects.bulk_create(author_list)
1、models.AutoField  自增列 = int(11)
  如果没有的话,默认会生成一个名称为 id 的列,如果要显示的自定义一个自增列,必须将给列设置为主键 primary_key=True。
2、models.CharField  字符串字段
  必须 max_length 参数
3、models.BooleanField  布尔类型=tinyint(1)
  不能为空,Blank=True
4、models.ComaSeparatedIntegerField  用逗号分割的数字=varchar
  继承CharField,所以必须 max_lenght 参数
5、models.DateField  日期类型 date
  对于参数,auto_now = True 则每次更新都会更新这个时间;auto_now_add 则只是第一次创建添加,之后的更新不再改变。
6、models.DateTimeField  日期类型 datetime
  同DateField的参数
7、models.Decimal  十进制小数类型 = decimal
  必须指定整数位max_digits和小数位decimal_places
8、models.EmailField  字符串类型(正则表达式邮箱) =varchar
  对字符串进行正则表达式
9、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、ipv4、ipv6
  验证时,会根据设置报错
14、models.NullBooleanField  允许为空的布尔类型
15、models.PositiveIntegerFiel  正Integer
16、models.PositiveSmallIntegerField  正smallInteger
17、models.SlugField  减号、下划线、字母、数字
18、models.SmallIntegerField  数字
  数据库中的字段有:tinyint、smallint、int、bigint
19、models.TextField  字符串=longtext
20、models.TimeField  时间 HH:MM[:ss[.uuuuuu]]
21、models.URLField  字符串,地址正则表达式
22、models.BinaryField  二进制
23、models.ImageField   图片
24、models.FilePathField 文件

更多字段
1、null=True
  数据库中字段是否可以为空
2、blank=True
  django的 Admin 中添加数据时是否可允许空值
3、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中字段的显示名称
9、name|db_column  数据库中的字段名称
10、unique=True  不允许重复
11、db_index = True  数据库索引
12、editable=True  在Admin里是否可编辑
13、error_messages=None  错误提示
14、auto_created=False  自动创建
15、help_text  在Admin中提示帮助信息
16、validators=[]
17、upload-to

更多参数
# 获取个数
    #
    # models.Tb1.objects.filter(name=\'seven\').count()

    # 大于,小于
    #
    # models.Tb1.objects.filter(id__gt=1)              # 获取id大于1的值
    # models.Tb1.objects.filter(id__lt=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等于11、22、33的数据
    # models.Tb1.objects.exclude(id__in=[11, 22, 33])  # not in

    # 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

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

    # 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"

双下画线操作

 

示例、用Q进行简单搜索 

# F 使用查询条件的值
    #
    # from django.db.models import F
    # models.Tb1.objects.update(num=F(\'num\')+1)

    # Q 构建搜索条件
    from django.db.models import Q
    # 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)

    #
    # from django.db import connection
    # cursor = connection.cursor()
    # cursor.execute("""SELECT * from tb where name = %s""", [\'Lennon\'])
    # row = cursor.fetchone()

F和Q
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .left{
            float: left;
        }
        .clearfix:after{
            content: \'.\';
            clear: both;
            display: block;
            visibility: hidden;
            height: 0;
        }
    </style>
</head>
<body>
    <div class="condition">
        <div class="item clearfix">
            <div class="icon left" onclick="AddCondition(this);">+</div>
            <div class="left">
                <select onchange="ChangeName(this);">
                    <option value="name">书名</option>
                    <option value="book_type__caption">图书类型</option>
                    <option value="price">价格</option>
                    <option value="pages">页数</option>
                </select>
            </div>
            <div class="left"><input type="text" name="name" /></div>
        </div>
    </div>
    <div>
        <input type="button" onclick="Search();" value="搜索" />
    </div>

    <div class="container">

    </div>



    <script src="/static/jquery-1.12.4.js"></script>
    <script>
        function  AddCondition(ths) {
            var new_tag = $(ths).parent().clone();
            new_tag.find(\'.icon\').text(\'-\');
            new_tag.find(\'.icon\').attr(\'onclick\', \'RemoveCondition(this);\');

            $(ths).parent().parent().append(new_tag);
        }
        function  RemoveCondition(ths) {
            $(ths).parent().remove();
        }
        function ChangeName(ths) {
            var v = $(ths).val();
            $(ths).parent().next().find(\'input\').attr(\'name\',v);
        }
        function Search() {
            var post_data_dict = {};

            // 获取所有input的内容,提交数据
            $(\'.condition input\').each(function () {
                // console.log($(this)[0])
                var n = $(this).attr(\'name\');
                var v = $(this).val();
                var v_list = v.split(\',\');
                post_data_dict[n] = v_list;
            });
            console.log(post_data_dict);
            var post_data_str = JSON.stringify(post_data_dict);
            $.ajax({
                url: \'/index/\',
                type: \'POST\',
                data: { \'post_data\': post_data_str},
                dataType: \'json\',
                success: function (arg) {
                    // 字符串 "<table>" +
                    if(arg.status){
                        var table = document.createElement(\'table\');
                        table.setAttribute(\'border\',1);
                        // [{,name,pubdate,price,caption},]
                        $.each(arg.data, function(k,v){
                            var tr = document.createElement(\'tr\');

                            var td1 = document.createElement(\'td\');
                            td1.innerText = v[\'name\'];
                            var td2 = document.createElement(\'td\');
                            td2.innerText = v[\'price\'];
                            var td3 = document.createElement(\'td\');
                            td3.innerText = v[\'book_type__caption\'];
                            var td4 = document.createElement(\'td\');
                            td4.innerText = v[\'pubdate\'];
                            tr.appendChild(td1);
                            tr.appendChild(td2);
                            tr.appendChild(td3);
                            tr.appendChild(td4);

                            table.appendChild(tr);
                        });

                        $(\'.container\').empty();
                        $(\'.container\').append(table);
                    }else{
                        alert(arg.message);
                    }

                }

            })
        }
    </script>
</body>
</html>

前端index
from django.db import models

# Create your models here.


class Author(models.Model):
    name = models.CharField(max_length=32)
    age = models.IntegerField()


class BookType(models.Model):
    caption = models.CharField(max_length=32)


class Book(models.Model):
    name = models.CharField(max_length=64)
    price = models.DecimalField(max_digits=10, decimal_places=2)
    pubdate = models.DateField()

    authors = models.ManyToManyField(Author)
    book_type = models.ForeignKey(BookType)

后端models
from django.shortcuts import render,HttpResponse
from app01 import models
# Create your views here.
import json
def test(request):
    # models.BookType.objects.create(caption=\'技术\')
    # models.BookType.objects.create(caption=\'文学\')
    # models.BookType.objects.create(caption=\'动漫\')
    # models.BookType.objects.create(caption=\'男人装\')

    # models.Book.objects.create(name=\'文艺复兴\',pages=\'100\',price=\'40\',pubdate=\'1992-11-2\',book_type_id=\'1\')
    # models.Book.objects.create(name=\'解密\',pages=\'80\',price=\'10\', pubdate=\'2016-6-10\',book_type_id=\'2\')
    # models.Book.objects.create(name=\'刀锋\',pages=\'50\',price=\'3\', pubdate=\'2014-02-16\',book_type_id=\'2\')
    # models.Book.objects.create(name=\'查令十字路84号\',pages=\'260\',price=\'40\',pubdate=\'1999-10-12\',book_type_id=\'3\')
    # models.Book.objects.create(name=\'红楼\',pages=\'1000\',price=\'500\', pubdate=\'1760-1-1\',book_type_id=\'3\')
    # models.Book.objects.create(name=\'将夜\',pages=\'2000\',price=\'300\', pubdate=\'2010-3-3\',book_type_id=\'1\')
    # models.Book.objects.create(name=\'mysql从删库到跑路\',pages=\'20\',price=\'10\',pubdate=\'1998-9-2\',book_type_id=\'4\')
    # models.Book.objects.create(name=\'马克思主义\',pages=\'50\',price=\'100\',pubdate=\'1937-3-3\',book_type_id=\'2\')

    return HttpResponse(\'ok\')

import json
from datetime import date
from datetime import datetime
from decimal import Decimal
class JsonCustomEncoder(json.JSONEncoder):

    def default(self, field):

        if isinstance(field, datetime):
            return field.strftime(\'%Y-%m-%d %H:%M:%S\')
        elif isinstance(field, date):
            return field.strftime(\'%Y-%m-%d\')
        elif isinstance(field, Decimal):
            return str(field)
        else:
            return json.JSONEncoder.default(self, field)

def index(request):
    if request.method == \'POST\':
        ret = {\'status\': False, \'message\': \'\', \'data\':None}
        try:
            post_data = request.POST.get(\'post_data\',None)
            post_data_dict = json.loads(post_data)
            print(post_data_dict)
            # {\'name\': [\'11\', \'sdf\'],\'price\': [\'11\', \'sdf\']}
            # 构造搜索条件
            from django.db.models import Q
            con = Q()
            for k,v in post_data_dict.items():
                q = Q()
                q.connector = \'OR\'
                for item in v:
                    q.children.append((k, item))
                con.add(q, \'AND\')
            """
            ret = models.Book.objects.filter(con)
            print(ret) # queryset,[对象]

            from django.core import serializers
            data = serializers.serialize("json", ret)   # 这种方法获取到的图书类型是id不是book_type__caption
            print(type(data),data)
            # 字符串
            """
            """
            #ret = models.Book.objects.filter(con).values(\'name\',\'book_type__caption\')
            ret = models.Book.objects.filter(con).values_list(\'name\', \'book_type__caption\')
            print(ret,type(ret))
            li = list(ret)
            data = json.dumps(li)
            print(data,type(data))
            """
            result = models.Book.objects.filter(con).values(\'name\',\'price\',\'pubdate\',\'book_type__caption\')
            # ret = models.Book.objects.filter(con).values_list(\'name\', \'book_type__caption\')
            li = list(result)
            ret[\'status\'] = True
            ret[\'data\'] = li
        except Exception as e:
            ret[\'message\'] = str(e)
        ret_str = json.dumps(ret, cls=JsonCustomEncoder)
        return HttpResponse(ret_str)
    return render(request, \'index.html\')

后端view 

form验证 

#!/usr/bin/env python
# coding=utf-8

from django import forms


class Forml(forms.Form):
    # username = forms.CharField()
    # pwd = forms.CharField()

    user = forms.CharField(
        widget=forms.TextInput(attrs={
            \'class\': \'c1\',
        }),
        error_messages={
            \'required\': \'用户名不能为空\',
        },
    )
    pwd = forms.CharField(max_length=4, min_length=2)

    # email = forms.EmailField(
    #     error_messages={
    #         \'required\': \'邮箱不能为空\',
    #         \'invalid\': \'邮箱格式错误\',
    #     }
    # )
    email = forms.EmailField(
        error_messages={
            \'required\': \'邮箱不能为空\',
            \'invalid\': \'邮箱格式错误\'
        }
    )

    memo = forms.CharField(
        widget=forms.Textarea()
    )

    # 自定义
    user_type_choice = (
        (0, \'普通用户\'),
        (1, \'高级用户\'),
    )
    # 如果从数据库查找,则Forml里面定义的静态字段只会执行一次
    # user_type_choice = models.BookType.objects.values_list(\'id\', \'caption\')
    book_type = forms.CharField(
        widget=forms.widgets.Select(
            choices=user_type_choice,
            attrs={\'class\': "form-control"},
        )
    )

    # 数据库动态的
    # 如果从数据库查找,则Forml里面定义的静态字段只会执行一次,所以需要下面动态的
    # def __init__(self, *args, **kwargs):
    #     super(Forml, self).__init__(*args, **kwargs)
    #     self.fields[\'book_type\'] = forms.CharField(
    #         widget=forms.widgets.Select(
    #             choices=models.BookType.objects.values_list(\'id\', \'caption\'),
    #             attrs={\'class\': "form-control"},
    #         )
    #     )

forms
#!/usr/bin/env python
# coding=utf-8

from django.shortcuts import render

from django.http import HttpResponse

from form1.forms import Forml


def form1(req):
    f = Forml()
    if req.method == \'POST\':
        f = Forml(req.POST)
        if f.is_valid():
            print(f.cleaned_data)
        else:
            # print(f.errors.get(\'user\',None))
            # print(f.errors[\'pwd\'][0])
            # print(type(f.errors),f.errors)
            # from django.forms.utils import ErrorDict
            
            print(type(f.errors), f.errors)
        return render(req, \'account/form1.html\', {\'error\': f.errors, \'form\': f})
    return render(req, \'account/form1.html\', {\'form\': f})

Views
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        span{
            background-color: darkolivegreen;
        }
    </style>
</head>
<body>
<form action="/form1/" method="POST">
    <div>
        <!--<input type="text" name="username">-->
        {{form.user}}
        {% if error.user %}
        <span>{{error.user.0}}</span>
        {% endif %}
    </div>
      <div>
          {{form.pwd}}
          <!--<input type="text" name="password">-->
          {% if error.pwd %}
          <span>{{error.pwd.0}}</span>
          {% endif %}
    </div>

    <div>
        {{form.email}}
        {% if error.email %}
        <span>{{error.email.0}}</span>
        {% endif %}
    </div>

    <div>
        {{form.memo}}
        {% if error.memo %}
        <span>{{error.memo.0}}</span>
        {% endif %}
    </div>

     <div>
        {{form.book_type}}
        {% if error.book_type %}
        <span>{{error.book_type.0}}</span>
        {% endif %}
    </div>
    <button type="submit">提交</button>
    <!--<input type="submit"  value="提交"/>-->
    
</form>

</body>
</html>

前端index

 除此之外还支持自定义字段,具体用法看下面的使用

import re
from django import forms
from django.core.exceptions import ValidationError


def mobile_validate(value):
    mobile_re = re.compile(r\'^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$\')
    if not mobile_re.match(value):
        raise ValidationError(\'手机号码格式错误\')

class PublishForm(forms.Form):   

    # 这里手机号使用了自己自定义的验证规则
    phone = forms.CharField(validators=[mobile_validate, ],   
                            error_messages={\'required\': u\'手机不能为空\'},
                            widget=forms.TextInput(attrs={\'class\': "form-control",
                                                          \'placeholder\': u\'手机号码\'}))

cookie和session  

一、cookie

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


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

二、session

a. 配置 settings.py
 
    SESSION_ENGINE = \'django.contrib.sessions.backends.db\'   # 引擎(默认)
     
    SESSION_COOKIE_NAME = "sessionid"                       # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串(默认)
    SESSION_COOKIE_PATH = "/"                               # Session的cookie保存的路径(默认)
    SESSION_COOKIE_DOMAIN = None                             # Session的cookie保存的域名(默认)
    SESSION_COOKIE_SECURE = False                            # 是否Https传输cookie(默认)
    SESSION_COOKIE_HTTPONLY = True                           # 是否Session的cookie只支持http传输(默认)
    SESSION_COOKIE_AGE = 1209600                             # Session的cookie失效日期(2周)(默认)
    SESSION_EXPIRE_AT_BROWSER_CLOSE = False                  # 是否关闭浏览器使得Session过期(默认)
    SESSION_SAVE_EVERY_REQUEST = False                       # 是否每次请求都保存Session,默认修改之后才保存(默认)
 
 
 
b. 使用
 
    def index(request):
        # 获取、设置、删除Session中数据
        request.session[\'k1\']
        request.session.get(\'k1\',None)
        request.session[\'k1\'] = 123
        request.session.setdefault(\'k1\',123) # 存在则不设置
        del request.session[\'k1\']
 
        # 所有 键、值、键值对
        request.session.keys()
        request.session.values()
        request.session.items()
        request.session.iterkeys()
        request.session.itervalues()
        request.session.iteritems()
 
 
        # 用户session的随机字符串
        request.session.session_key
 
        # 将所有Session失效日期小于当前日期的数据删除
        request.session.clear_expired()
 
        # 检查 用户session的随机字符串 在数据库中是否
        request.session.exists("session_key")
 
        # 删除当前用户的所有Session数据
        request.session.delete("session_key")
 
        ...

数据库session
a. 配置 settings.py
 
    SESSION_ENGINE = \'django.contrib.sessions.backends.cache\'  # 引擎
    SESSION_CACHE_ALIAS = \'default\'                            # 使用的缓存别名(默认内存缓存,也可以是memcache),此处别名依赖缓存的设置
 
 
    SESSION_COOKIE_NAME = "sessionid"                        # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串
    SESSION_COOKIE_PATH = "/"                                # Session的cookie保存的路径
    SESSION_COOKIE_DOMAIN = None                              # Session的cookie保存的域名
    SESSION_COOKIE_SECURE = False                             # 是否Https传输cookie
    SESSION_COOKIE_HTTPONLY = True                            # 是否Session的cookie只支持http传输
    SESSION_COOKIE_AGE = 1209600                              # Session的cookie失效日期(2周)
    SESSION_EXPIRE_AT_BROWSER_CLOSE = False                   # 是否关闭浏览器使得Session过期
    SESSION_SAVE_EVERY_REQUEST = False                        # 是否每次请求都保存Session,默认修改之后才保存
 
 
 
b. 使用
 
    同上

缓存session



a. 配置 settings.py
 
    SESSION_ENGINE = \'django.contrib.sessions.backends.file\'    # 引擎
    SESSION_FILE_PATH = None                                    # 缓存文件路径,如果为None,则使用tempfile模块获取一个临时地址tempfile.gettempdir()                                                            # 如:/var/folders/d3/j9tj0gz93dg06bmwxmhh6_xm0000gn/T
 
 
    SESSION_COOKIE_NAME = "sessionid"                          # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串
    SESSION_COOKIE_PATH = "/"                                  # Session的cookie保存的路径
    SESSION_COOKIE_DOMAIN = None                                # Session的cookie保存的域名
    SESSION_COOKIE_SECURE = False                               # 是否Https传输cookie
    SESSION_COOKIE_HTTPONLY = True                              # 是否Session的cookie只支持http传输
    SESSION_COOKIE_AGE = 1209600                                # Session的cookie失效日期(2周)
    SESSION_EXPIRE_AT_BROWSER_CLOSE = False                     # 是否关闭浏览器使得Session过期
    SESSION_SAVE_EVERY_REQUEST = False                          # 是否每次请求都保存Session,默认修改之后才保存
 
b. 使用
 
    同上

文件session

数据库用于做持久化,缓存用于提高效率
 
a. 配置 settings.py
 
    SESSION_ENGINE = \'django.contrib.sessions.backends.cached_db\'        # 引擎
 
b. 使用
 
    同上

缓存+数据库session



a. 配置 settings.py
     
    SESSION_ENGINE = \'django.contrib.sessions.backends.signed_cookies\'   # 引擎
 
b. 使用
 
    同上


备注:保存在客户端

加密session

三、session用户验证

def login_auth(func):
    def wrapper(req, *args, **kwargs):
        if not req.session.get(\'is_login\', None):
            return redirect(\'/admin/login\')
        return func(req, *args, **kwargs)
    return wrapper

跨站请求伪造  

一、简介

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

全局:

  中间件 django.middleware.csrf.CsrfViewMiddleware

局部:

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

二、普通表单

veiw中设置返回值:
  return render_to_response(\'Account/Login.html\',data,context_instance=RequestContext(request))  
     或者
     return render(request, \'xxx.html\', data)   #这里也可以看出render 和 render_to_respone 的区别
  
html中设置Token:
  {% csrf_token %}

三、ajax发送  

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    {% csrf_token %}
  
    <input type="button" onclick="Do();"  value="Do it"/>
  
    <script src="/static/plugin/jquery/jquery-1.8.0.js"></script>
    <script src="/static/plugin/jquery/jquery.cookie.js"></script>
    <script type="text/javascript">
        var csrftoken = $.cookie(\'csrftoken\');
  
        function csrfSafeMethod(method) {
            // these HTTP methods do not require CSRF protection
            return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
        }
        $.ajaxSetup({
            beforeSend: function(xhr, settings) {
                if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
                    xhr.setRequestHeader("X-CSRFToken", csrftoken);
                }
            }
        });
        function Do(){
  
            $.ajax({
                url:"/app01/test/",
                data:{id:1},
                type:\'POST\',
                success:function(data){
                    console.log(data);
                }
            });
  
        }
    </script>
</body>
</html>

前端html
from django.template.context import RequestContext
# Create your views here.
  
  
def test(request):
  
    if request.method == \'POST\':
        print request.POST
        return HttpResponse(\'ok\')
    return  render_to_response(\'app01/test.html\',context_instance=RequestContext(request))

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

Views

django上传文件

一、普通上传文件

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\')


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form action="/upload_file/" enctype="multipart/form-data" method="POST">
        {% csrf_token %}
        <input type="file" name="fafafa" />

        <input type="submit" value="提交" />
    </form>
</body>
</html>

二、form上传文件

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)


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  

 django序列化

一、serializers

# 缺点外键字段不能很好显示

from django.core import serializers
 
ret = models.BookType.objects.all()
 
data = serializers.serialize("json", ret)

二、json

有些数据结构不支持,這里可以通过自定义处理器来做扩展

import json 
from datetime import date 
from datetime import datetime


class JsonCustomEncoder(json.JSONEncoder):

    def default(self, field):

        if isinstance(field, datetime):
            return field.strftime(\'%Y-%m-%d %H:%M:%S\')
        elif isinstance(field, date):
            return field.strftime(\'%Y-%m-%d\')
        elif isinstance(field, Decimal):
            return str(field)
        else:
            return json.JSONEncoder.default(self, field)

ret_str = json.dumps(ret, cls=JsonCustomEncoder)

django自定义分页

和tornado一样,只需修改一个地方

#!/usr/bin/env python
# -*- coding:utf-8 -*-

from django.utils.safestring import mark_safe


class Pagination:
    def __init__(self, current_page, all_item):
        try:
            page = int(current_page)
        except:
            page = 1
        if page < 1:
            page = 1

        all_pager, c = divmod(all_item, 5)
        if c > 0:
            all_pager += 1

        self.current_page = page
        self.all_pager = all_pager

    @property
    def start(self):
        return (self.current_page - 1) * 5

    @property
    def end(self):
        return self.current_page * 5

    def string_pager(self, base_url="/admin/manage/"):
        list_page = []
        if self.all_pager < 11:
            s = 1
            t = self.all_pager + 1
        else:  # 总页数大于11
            if self.current_page < 6:
                s = 1
                t = 12
            else:
                if (self.current_page + 5) < self.all_pager:
                    s = self.current_page - 5
                    t = self.current_page + 5 + 1
                else:
                    s = self.all_pager - 11
                    t = self.all_pager + 1
        # 首页
        # first = \'<a href="%s1">首页</a>\' % base_url
        # list_page.append(first)
        # 上一页
        # 当前页 page
        if self.current_page == 1:
            prev = \'<a href="javascript:void(0);">上一页</a>\'
        else:
            prev = \'<a href="%s%s">上一页</a>\' % (base_url, self.current_page - 1,)
        list_page.append(prev)

        for p in range(s, t):  # 1-11
            if p == self.current_page:
                temp = \'<a class="active" href="%s%s">%s</a>\' % (base_url, p, p)
            else:
                temp = \'<a href="%s%s">%s</a>\' % (base_url, p, p)
            list_page.append(temp)
        if self.current_page == self.all_pager:
            nex = \'<a href="javascript:void(0);">下一页</a>\'
        else:
            nex = \'<a href="%s%s">下一页</a>\' % (base_url, self.current_page + 1,)

        list_page.append(nex)

        # 尾页
        # last = \'<a href="%s%s">尾页</a>\' % (base_url, self.all_pager,)
        # list_page.append(last)

        # 跳转
        # jump = """<input type=\'text\' /><a onclick="Jump(\'%s\',this);">GO</a>""" % (\'/index/\', )
        # script = """<script>
        #     function Jump(baseUrl,ths){
        #         var val = ths.previousElementSibling.value;
        #         if(val.trim().length>0){
        #             location.href = baseUrl + val;
        #         }
        #     }
        #     </script>"""
        # list_page.append(jump)
        # list_page.append(script)
        str_page = "".join(list_page)
        return mark_safe(str_page)

模板

一、基础语法

{{ 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 }}

基本使用

二、自定义

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)

创建任意 .py 文件,如:xx.py

在使用自定义simple_tag的html文件中导入之前创建的 xx.py 文件名

{% load xx %}

使用simple_tag 

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

三、使用filter

@register.filter
def detail(value, arg):
    # 只能接受两个参数
    allcount, remainder = arg.split(\',\')
    allcount = int(allcount)
    remainder = int(remainder)
    if value % allcount == remainder:
        return True
    return False


<div>
    {% for item in detail_list %}
        {% if forloop.counter|detail1:"4,0" %}
            <div>
                <p>{{ item.student__name }}</p>
            </div>
        {% endif %}
    {% endfor %}
</div>

  

django中间件 

django 中的中间件(middleware),在django中,中间件其实就是一个类,在请求到来和结束后,django会根据自己的规则在合适的时机执行中间件中相应的方法。在django项目的settings模块中,有一个 MIDDLEWARE_CLASSES 变量,其中每一个元素就是一个中间件,穿过中间件的顺序就是下面列表的注册顺序

MIDDLEWARE = [
    \'middleware_test_1.middleware1.testMiddleware\',
    \'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\',
]

下面看一下流程图

 

正常流程,request->view->  url->views   ->response

如果request里面直接返回了, 或者出现其他问题,直接到最里面的response,不走django里面的视图处理了

 

自己自定义的中间件类可以定义下面几种方法

  • 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)

自己定义的类在最新的django里面需要继承MiddlewareMixin

自定义中间件

from django.utils.deprecation import MiddlewareMixin


class testMiddleware(MiddlewareMixin):

    def process_request(self, request):
        print(11)

    def process_response(self, request, response):
        print(22)
        return response

创建中间件
MIDDLEWARE = [
    \'middleware_test_1.middleware1.testMiddleware\',
    \'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\',
]

注册中间件

django缓存

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

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

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

一、配置

 # 此为开始调试用,实际内部不做任何操作
    # 配置:
        CACHES = {
            \'default\': {
                \'BACKEND\': \'django.core.cache.backends.dummy.DummyCache\',     # 引擎
                \'TIMEOUT\': 300,                                               # 缓存超时时间(默认300,None表示永不过期,0表示立即过期)
                \'OPTIONS\':{
                    \'MAX_ENTRIES\': 300,                                       # 最大缓存个数(默认300)
                    \'CULL_FREQUENCY\': 3,                                      # 缓存到达最大个数之后,剔除缓存个数的比例,即:1/CULL_FREQUENCY(默认3)
                },
                \'KEY_PREFIX\': \'\',                                             # 缓存key的前缀(默认空)
                \'VERSION\': 1,                                                 # 缓存key的版本(默认1)
                \'KEY_FUNCTION\' : default_key_func                             # 生成key的函数(默认函数会生成为:【前缀:版本:key】)
            }
        }


    # 自定义key
    def default_key_func(key, key_prefix, version):
        """
        Default function to generate keys.

        Constructs the key used by all other methods. By default it prepends
        the `key_prefix\'. KEY_FUNCTION can be used to specify an alternate
        function with custom key making behavior.
        """
        return \'%s:%s:%s\' % (key_prefix, version, key)

    def get_key_func(key_func):
        """
        Function to decide which key function to use.

        Defaults to ``default_key_func``.
        """
        if key_func is not None:
            if callable(key_func):
                return key_func
            else:
                return import_string(key_func)
        return default_key_func
# 此缓存将内容保存至内存的变量中
    # 配置:
        CACHES = {
            \'default\': {
                \'BACKEND\': \'django.core.cache.backends.locmem.LocMemCache\',
                \'LOCATION\': \'unique-snowflake\',
            }
        }

    # 注:其他配置同开发调试版本

内存


# 此缓存将内容保存至文件
    # 配置:

        CACHES = {
            \'default\': {
                \'BACKEND\': \'django.core.cache.backends.filebased.FileBasedCache\',
                \'LOCATION\': \'filetopath\',
            }
        }
    # 注:其他配置同开发调试版本

文件


# 此缓存将内容保存至数据库

    # 配置:
        CACHES = {
            \'default\': {
                \'BACKEND\': \'django.core.cache.backends.db.DatabaseCache\',
                \'LOCATION\': \'my_cache_table\', # 数据库表
            }
        }

    # 注:执行创建表命令 python manage.py createcachetable

数据库


# 此缓存使用python-memcached模块连接memcache

    CACHES = {
        \'default\': {
            \'BACKEND\': \'django.core.cache.backends.memcached.MemcachedCache\',
            \'LOCATION\': \'127.0.0.1:11211\',
        }
    }

    CACHES = {
        \'default\': {
            \'BACKEND\': \'django.core.cache.backends.memcached.MemcachedCache\',
            \'LOCATION\': \'unix:/tmp/memcached.sock\',
        }
    }   

    CACHES = {
        \'default\': {
            \'BACKEND\': \'django.core.cache.backends.memcached.MemcachedCache\',
            \'LOCATION\': [
                \'172.19.26.240:11211\',
                \'172.19.26.242:11211\',
            ]
        }
    }

Memcache缓存(python-memcached模块)


# 此缓存使用pylibmc模块连接memcache
    
    CACHES = {
        \'default\': {
            \'BACKEND\': \'django.core.cache.backends.memcached.PyLibMCCache\',
            \'LOCATION\': \'127.0.0.1:11211\',
        }
    }

    CACHES = {
        \'default\': {
            \'BACKEND\': \'django.core.cache.backends.memcached.PyLibMCCache\',
            \'LOCATION\': \'/tmp/memcached.sock\',
        }
    }   

    CACHES = {
        \'default\': {
            \'BACKEND\': \'django.core.cache.backends.memcached.PyLibMCCache\',
            \'LOCATION\': [
                \'172.19.26.240:11211\',
                \'172.19.26.242:11211\',
            ]
        }
    }

Memcache缓存(pylibmc模块)

  

二、应用

使用中间件,经过一系列的认证等操作,如果内容在缓存中存在,则使用FetchFromCacheMiddleware获取内容并返回给用户,当返回给用户之前,判断缓存中是否已经存在,如果不存在则UpdateCacheMiddleware会将缓存保存至缓存,从而实现全站缓存

    MIDDLEWARE = [
        \'django.middleware.cache.UpdateCacheMiddleware\',
        # 其他中间件...
        \'django.middleware.cache.FetchFromCacheMiddleware\',
    ]

    CACHE_MIDDLEWARE_ALIAS = ""
    CACHE_MIDDLEWARE_SECONDS = ""
    CACHE_MIDDLEWARE_KEY_PREFIX = ""

全站使用
方式一:
        from django.views.decorators.cache import cache_page

        @cache_page(60 * 15)
        def my_view(request):
            ...

    方式二:
        from django.views.decorators.cache import cache_page

        urlpatterns = [
            url(r\'^foo/([0-9]{1,2})/$\', cache_page(60 * 15)(my_view)),
        ]

单独视图缓存
a. 引入TemplateTag

        {% load cache %}

    b. 使用缓存

        {% cache 5000 缓存key %}
            缓存内容
        {% endcache %}

局部视图使用

django信号量  

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

一、内置信号

Model signals
    pre_init                    # django的modal执行其构造方法前,自动触发
    post_init                   # django的modal执行其构造方法后,自动触发
    

以上是关于Python全栈开发之21django的主要内容,如果未能解决你的问题,请参考以下文章

Python全栈开发之Django进阶

Python全栈开发之Django基础

Python全栈开发Django进阶之序列化

1Python全栈之路系列之Django初体验

4Python全栈之路系列之Django模型

3Python全栈之路系列之D