python运维开发(二十)----models操作、中间件、缓存、信号、分页
内容目录
- select Form标签数据库操作
- models操作F/Q
- models多对多表操作
- Django中间件
- 缓存
- 信号
- 分页
select Form标签补充
在上一节中我们可以知道Form标签有两个作用,一个做用户提交数据验证,一个是生成HTML标签
在生成HTML标签中可以生成select标签,select的选项数据我们可以在数据库中查询读取到。
class UserType(models.Model):
    caption = models.CharField(max_length=16)
class UserInfo(models.Model):
    username = models.CharField(max_length=32)
    pwd = models.CharField(max_length=32)
    user_type = models.ForeignKey('UserType')
#python3 manage.py makemigrations
#python3 migrate
models生成表
from app01 import models
class IndexForm(forms.Form):
    # c = [
    #     (1,'CEO'),
    #     (2,'COO')
    # ]
    c = models.UserType.objects.all().values_list('id','caption')
    user_type_id = forms.IntegerField(widget=forms.Select(choices=c))
    def __init__(self,*args, **kwargs):
        # 父类构造方法:1、获取所有静态字段   2、fields = []
        super(IndexForm, self).__init__(*args, **kwargs)
        # print(self.fields['user_type_id'].widget.choices)
        self.fields['user_type_id'].widget.choices = models.UserType.objects.all().values_list('id','caption')
def index(request):
    # for i in range(10):
    #     models.UserType.objects.create(caption='CE'+str(i))
    # c = models.UserType.objects.all().count()
    # print(c)
    form = IndexForm()
    return render(request, 'index.html', {'form': form})
Views 代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    <h1>Index</h1>
    {{ form.user_type_id }}
</body>
</html>
前端Html
注意:普通创建完读完数据库数据之后,启动django状态,如果在向数据库中插入数据,页面不会发生变化,因为c=models.UserType.objects.all().values_list('id','caption')属于静态对象,如果要查看到更新的数据,可以重启下django就可以了,如果不想重启的话需要自定义__init__构造方法。
models F/Q操作
F:
综合查询修改字段值
temp = salary+500
models.UserInfo.objects.filter().update(salary=temp)
update userinfo set salary=salary+500 
from django.db.models import F
models.UserInfo.objects.filter().update(salary=F('salary')+500)
Q:
构造搜索条件
1、传参
models.UserInfo.objects.filter(id=123,name='jabe')
2、传字典
d = {'id': 123, 'name':'jabe'}
models.UserInfo.objects.filter(**d)
<input name='id' />
<input name='name' />
获取用户输入,并构造成字典:
models.UserInfo.objects.filter(**c)
3、传Q对象
models.UserInfo.objects.filter(Q对象)
from django.db.models import Q
# q1 = Q()
# q1.connector = 'OR'
# q1.children.append(('id', 1))
# q1.children.append(('id', 2))
# q1.children.append(('id', 3))
# models.Tb1.objects.filter(q1)
# con = Q()
#
# q1 = Q()
# q1.connector = 'OR'
# q1.children.append(('id', 1))
# q1.children.append(('id', 2))
# q1.children.append(('id', 3))
#
# q2 = Q()
# q2.connector = 'OR'
# q2.children.append(('status', '在线'))
#
# con.add(q1, 'AND')
# con.add(q2, 'AND')
#
# models.Tb1.objects.filter(con)
models多对多操作
	- 创建
		a. 方式一:
			class B2G(models.Model):
				b_id = models.ForeignKey('Boy')
				g_id = models.ForeignKey('Girl')
			class Boy(models.Model):
				username = models.CharField(max_length=16)
			class Girl(models.Model):
				name = models.CharField(max_length=16)
		b. 方式二:
			class Boy(models.Model):
				username = models.CharField(max_length=16)
				# girl_set
			class Girl(models.Model):
				name = models.CharField(max_length=16)
				b = models.ManyToManyField('Boy')
	- 操作:
		添加:
			正向
				g1 = models.Girl.objects.get(id=1)
				g1.b.add(models.Boy.objects.get(id=1))
				g1.b.add(1)
				bs = models.Boy.objects.all()
				g1.b.add(*bs)
				g1.b.add(*[1,2,3])
			反向
				b1 = models.Boy.objects.get(id=1)
				b1.girl_set.add(1)
				b1.girl_set.add(models.Girl.objects.all())
				b1.girl_set.add(*[1,2,3,4])
				...
		删除:
			g1 = models.Girl.objects.get(id=1)
			g1.b.clear() # 清空和girl ID=1所关联的所有数据
			g1.b.remove(2)
			g1.b.remove(*[1,2])
		查询:
			g1 = models.Girl.objects.get(id=1) # SQL
			g1.b.all()						   # SQL
			g1.b.filter().count()
			b1 = models.Boy.objects.get(id=1)
			b1.girl_set.all()
			models.Girl.objects.all().values('id','name', 'b__username')
			models.Boy.objects.all().values('id','username', 'girl__name')
		更新:
		ORM:
			python操作数据库模块:
				MySQLdb
				pymysql
		原生SQL
			# from django.db import connection
			# cursor = connection.cursor()
			# cursor.execute("""SELECT * from tb where name = %s""", ['Lennon'])
			# row = cursor.fetchone()
实例操作
from django.db import models
class Boy(models.Model):
    username = models.CharField(max_length=16)
class Girl(models.Model):
    name = models.CharField(max_length=16)
    b = models.ManyToManyField('Boy')
models
    url(r'^add_user_type/', views.add_user_type),
    url(r'^add_boy/', views.add_boy),
    url(r'^add_girl/', views.add_girl),
    url(r'^boy_to_girl/', views.boy_to_girl),
url路由配置
def add_user_type(request):
    q =  request.GET.get('q',None)
    if q:
        models.UserType.objects.create(caption=q)
    return HttpResponse(q)
# http://127.0.0.1:8000/add_user_type/?q=COO
def add_boy(request):
    boy = request.GET.get('v',None)
    if boy:
        models.Boy.objects.create(username=boy)
    return HttpResponse(boy)
def add_girl(request):
    girl = request.GET.get('v',None)
    if girl:
        models.Girl.objects.create(name=girl)
    return HttpResponse(girl)
def boy_to_girl(request):
    #
    # #增加数据
    # g1 = models.Girl.objects.get(id=1)
    # print('女',g1.name)
    # # g1.b 是多对多字段
    # #g1.b.add(男)
    # b1 = models.Boy.objects.get(id=1)
    # print('男',b1.username)
    # g1.b.add(3)
    # #第三张表:1 1
    #查询数据
    # g1 = models.Girl.objects.get(id=1)
    # ret = g1.b.all()#获取第三张表中girl_id = 1 的所有数据
    # # ret = g1.b.all().values_list('id','boy')
    # print(ret)
    #删除关系数据
    g1 = models.Girl.objects.get(id=1)
    # g1_name = models.Girl.objects.filter(id=1).values('name')
    # print(g1_name)
    b1 = models.Boy.objects.get(id=1)
    # g1.b.clear()
    # g1.b.add(*[1,2,3,4])
    # g1.b.remove(*[2,3])
    # b1.girl_set.add(*[1,2,3,4])
    boy_list = g1.b.all()
    girl_list = b1.girl_set.all().values('name')
    # print(boy_list.query)#查询sql语句
    # print(boy_list)
    # print(girl_list)
    #多表关联查询
    # ret = models.Girl.objects.all().values('id','name','b__username')
    ret = models.Boy.objects.all().values('id','username','girl__name')
    print(ret)
    return HttpResponse('ok')
views
Django中间件
django 中的中间件(middleware),在django中,中间件其实就是一个类,在请求到来和结束后,django会根据自己的规则在合适的时机执行中间件中相应的方法。
在django项目的settings模块中,有一个 MIDDLEWARE_CLASSES 变量,其中每一个元素就是一个中间件,如下图。

中间件中可以定义四个方法,分别是:
- 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)
以上方法的返回值可以是None和HttpResonse对象,如果是None,则继续按照django定义的规则向下执行,如果是HttpResonse对象,则直接将该对象返回给用户。

配置文件: MIDDLEWARE_CLASSES 写类: process_request process_view process_exception process_response 1.10 配置文件: MIDDLEWARE = 原版本: 如果process_request中有return, 则所有的process_response执行一遍
自定义中间件
1、创建中间件类
class RequestExeute(object):
    def process_request(self,request):
        pass
    def process_view(self, request, callback, callback_args, callback_kwargs):
        i =1
        pass
    def process_exception(self, request, exception):
        pass
    def process_response(self, request, response):
        return response
2、注册中间件
MIDDLEWARE_CLASSES = [
    'md.zhongjian.M1',
    'md.zhongjian.M2',
    'django.middleware.security.SecurityMiddleware',
    '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',
]
缓存
Django中默认支持Session,其内部提供了5种类型的Session供开发者使用:
- 数据库(默认)
- 缓存
- 文件
- 缓存+数据库
- 加密cookie
信号
Django中提供了“信号调度”,用于在框架执行操作时解耦。通俗来讲,就是一些动作发生的时候,信号允许特定的发送者去提醒一些接受者。
1、Django内置信号
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内置的信号,仅需注册指定信号,当程序执行相应操作时,自动触发注册函数:
  from django.core.signals import request_finished
    from django.core.signals import request_started
    from django.core.signals import got_request_exception
    from django.db.models.signals import class_prepared
    from django.db.models.signals import pre_init, post_init
    from django.db.models.signals import pre_save, post_save
    from django.db.models.signals import pre_delete, post_delete
    from django.db.models.signals import m2m_changed
    from django.db.models.signals import pre_migrate, post_migrate
    from django.test.signals import setting_changed
    from django.test.signals import template_rendered
    from django.db.backends.signals import connection_created
    def callback(sender, **kwargs):
        print("xxoo_callback")
        print(sender,kwargs)
    xxoo.connect(callback)
    # xxoo指上述导入的内容
from django.core.signals import request_finished
from django.dispatch import receiver
@receiver(request_finished)
def my_callback(sender, **kwargs):
    print("Request finished!")
2、自定义信号
a. 定义信号
import django.dispatch pizza_done = django.dispatch.Signal(providing_args=["toppings", "size"])
b. 注册信号
def callback(sender, **kwargs):
    print("callback")
    print(sender,kwargs)
pizza_done.connect(callback)
c. 触发信号
from 路径 import pizza_done pizza_done.send(sender='seven',toppings=123, size=456)
由于内置信号的触发者已经集成到Django中,所以其会自动调用,而对于自定义信号则需要开发者在任意位置触发。
分页
一、Django内置分页
二、自定义分页
分页功能在每个网站都是必要的,对于分页来说,其实就是根据用户的输入计算出应该在数据库表中的起始位置。
1、设定每页显示数据条数
2、用户输入页码(第一页、第二页...)
3、根据设定的每页显示条数和当前页码,计算出需要取数据表的起始位置
4、在数据表中根据起始位置取值,页面上输出数据
需求又来了,需要在页面上显示分页的页面。如:[上一页][1][2][3][4][5][下一页]
1、设定每页显示数据条数
2、用户输入页码(第一页、第二页...)
3、设定显示多少页号
4、获取当前数据总条数
5、根据设定显示多少页号和数据总条数计算出,总页数
6、根据设定的每页显示条数和当前页码,计算出需要取数据表的起始位置
7、在数据表中根据起始位置取值,页面上输出数据
8、输出分页html,如:[上一页][1][2][3][4][5][下一页]
总结,分页时需要做三件事:
- 创建处理分页数据的类
- 根据分页数据获取数据
- 输出分页HTML,即:[上一页][1][2][3][4][5][下一页]
#!/usr/bin/env python
# _*_coding:utf-8_*_
from django.utils.safestring import mark_safe
class PageInfo(object):
    def __init__(self,current,totalItem,peritems=5):
        self.__current=current
        self.__peritems=peritems
        self.__totalItem=totalItem
    def From(self):
        return (self.__current-1)*self.__peritems
    def To(self):
        return self.__current*self.__peritems
    def TotalPage(self):  #总页数
        result=divmod(self.__totalItem,self.__peritems)
        if result[1]==0:
            return result[0]
        else:
            return result[0]+1
def Custompager(baseurl,currentPage,totalpage):  #基础页,当前页,总页数
    perPager=11
    #总页数<11
    #0 -- totalpage
    #总页数>11
        #当前页大于5 currentPage-5 -- currentPage+5
            #currentPage+5是否超过总页数,超过总页数,end就是总页数
        #当前页小于5 0 -- 11
    begin=0
    end=0
    if totalpage <= 11:
        begin=0
        end=totalpage
    else:
        if currentPage>5:
            begin=currentPage-5
            end=currentPage+5
            if end > totalpage:
                end=totalpage
        else:
            begin=0
            end=11
    pager_list=[]
    if currentPage<=1:
        first="<a href=''>首页</a>"
    else:
        first="<a href='%s%d'>首页</a>" % (baseurl,1)
    pager_list.append(first)
    if currentPage<=1:
        prev="<a href=''>上一页</a>"
    else:
        prev="<a href='%s%d'>上一页</a>" % (baseurl,currentPage-1)
    pager_list.append(prev)
    for i in range(begin+1,end+1):
        if i == currentPage:
            temp="<a href='%s%d' class='selected'>%d</a>" % (baseurl,i,i)
        else:
            temp="<a href='%s%d'>%d</a>" % (baseurl,i,i)
        pager_list.append(temp)
    if currentPage>=totalpage:
        next="<a href='#'>下一页</a>"
    else:
        next="<a href='%s%d'>下一页</a>" % (baseurl,currentPage+1)
    pager_list.append(next)
    if currentPage>=totalpage:
        last="<a href=''>末页</a>"
    else:
        last="<a href='%s%d'>末页</a>" % (baseurl,totalpage)
    pager_list.append(last)
    result=''.join(pager_list)
    return mark_safe(result)   #把字符串转成html语言
分页实例应用
python运维开发(二十)----models操作、中间件、缓存、信号、分页的更多相关文章
- python运维开发(二十二)---JSONP、瀑布流、组合搜索、多级评论、tornado框架简介
		内容目录: JSONP应用 瀑布流布局 组合搜索 多级评论 tornado框架简介 JSONP应用 由于浏览器存在同源策略机制,同源策略阻止从一个源加载的文档或脚本获取或设置另一个源加载的文档的属性. ... 
- python运维开发(二十五)---cmdb开发
		内容目录: 浅谈ITIL CMDB介绍 Django自定义用户认证 Restful 规范 资产管理功能开发 浅谈ITIL TIL即IT基础架构库(Information Technology Infr ... 
- python运维开发(二十四)----crm权限管理系统
		内容目录: 数据库设计 easyUI的使用 数据库设计 权限表Perssion 角色表Role 权限和角色关系表RoleToPermission 用户表UserInfo 用户和角色关系表UserInf ... 
- python运维开发(二十三)---tornado框架
		内容目录: 路由系统 模板引擎 cookie 加密cookie 自定义api 自定义session 自定义form表单验证 异步非阻塞 web聊天室实例 路由系统 路由系统其实就是 url 和 类 的 ... 
- python运维开发(二十一)----文件上传和验证码+session
		内容目录: 文件上传 验证码+session 文件和图片的上传功能 HTML Form表单提交,实例展示 views 代码 HTML ajax提交 原生ajax提交,XMLHttpRequest方式上 ... 
- Python运维开发基础09-函数基础【转】
		上节作业回顾 #!/usr/bin/env python3 # -*- coding:utf-8 -*- # author:Mr.chen # 实现简单的shell命令sed的替换功能 import ... 
- Python运维开发基础08-文件基础【转】
		一,文件的其他打开模式 "+"表示可以同时读写某个文件: r+,可读写文件(可读:可写:可追加) w+,写读(不常用) a+,同a(不常用 "U"表示在读取时, ... 
- Python运维开发基础07-文件基础【转】
		一,文件的基础操作 对文件操作的流程 [x] :打开文件,得到文件句柄并赋值给一个变量 [x] :通过句柄对文件进行操作 [x] :关闭文件 创建初始操作模板文件 [root@localhost sc ... 
- Python运维开发基础05-语法基础【转】
		上节作业回顾(讲解+温习90分钟) #!/usr/bin/env python # -*- coding:utf-8 -*- # author:Mr.chen import os,time Tag = ... 
随机推荐
- Ubuntu下给Sublime Text 3添加用python3运行文件
			Ubuntu14.04: 菜单栏:Tools-Build System-New Build System { "cmd": ["python3", " ... 
- iframe和response.sendRedirect使用的问题
			一.iframe下使用response.sendRedirect的问题 一般使用filter过滤用户是否登录,如果用户没有登陆则转向登陆页面,这时候可以使用response.sendRedirect( ... 
- 正则匹配<img src="xxxxxx" alt="" />标签的相关写法
			1.(<img\ssrc[^>]*>) 2.content.replace(/<img [^>]*src=['"]([^'"]+)[^>]*&g ... 
- 猎豹上市(猎豹的广告收入中有70%来自BAT三家公司,总收入中有58%来自BAT)
			发表日期: 2014 年 5 月 9 日 From 网易专题 文/赵楠 村里那点儿事 猎豹移动上市之夜,我挺激动. 激动除了因为有好朋友在这家公司外,也因为猎豹移动在历史上的几次起承转合非常不易,在巨 ... 
- windows下wchar_t*  转char*
			这个在windows下很常见,常用,留个档. 一般用这个函数: size_t wcstombs( char *mbstr, const wchar_t *wcstr, size_t count ); ... 
- VC运行库版本不同导致链接.LIB静态库时发生重复定义问题的一个案例分析和总结
			转帖:http://blog.csdn.net/whygosofar/article/details/2821875 MSDN中对于在不同的配置下Link的LIB作了说明: C Runtime Lib ... 
- windows phone之获取当前连接WIFI的SSID
			public string GetSSIDName() { foreach (var network in new NetworkInterfaceList()) { if ( (network.In ... 
- js相对定位
			效果图: 
- python高级编程(第12章:优化学习)3
			#微观剖析 ''' 当找到速度很慢函数时,有时还需要做到测试某个部分函数剖析工作,这需要通过手动对一部分代码速度测试完成 ''' """ import tempfile, ... 
- tiny210(s5pv210)移植u-boot(基于 2014.4 版本号)——NAND 启动
			我们知道 s5pv210启动方式有非常多种,sd卡和nand flash 启动就是当中的两种,前面我们实现的都是基于sd卡启动,这节我们開始实现从nand flash 启动: 从 NAND 启动 u- ... 
