django数据库操作和中间件
数据库配置
django的数据库相关表配置在models.py文件中,数据库的连接相关信息配置在settings.py中
- models.py相关相关参数配置
from django.db import models class userinfo(models.Model):
name = models.CharField(max_length=30)
email = models.EmailField()
memo = models.TextField()
可用的字段:
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
- settings.py相关配置
数据库连接配置:
DATABASES = {
'default': {
#'ENGINE': 'django.db.backends.', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'.
'ENGINE': 'django.db.backends.sqlite3', #添加数据库引擎;选项['postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'].
'NAME': 'F:/TestPython/blog/blog/db/data.db', # 数据库文件的路径.
# The following settings are not used with sqlite3:
# 下面的配置不适用于sqlite3:
'USER': '', # 数据库登陆用户名
'PASSWORD': '', # 数据库登陆密码
'HOST': '', # Empty for localhost through domain sockets or '127.0.0.1' for localhost through TCP. # 主机名
'PORT': '', # Set to empty string for default. # 端口号
}
}
注册app:
在settings里的INSTALLED_APPS里面加上你的app名字
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'app01',
]
生成数据库表
python manage.py makemigrations
# 生成一个数据库结构migrations里面一个表
python manage.py migrate
# 根据migrations里面的表来创建数据库
将app的数据库注册到admin
在app01下面的admin.py写入以下内容:
from django.contrib import admin # Register your models here.
# 导入app01的数据库模块
from app01 import models # 注册咱们创建的类,通过他来访问
admin.site.register(models.UserInfo)
数据库相关操作
增删改查
# 插入数据:
UserInfo.objects.create(name='rain',password='',email='rain@163.com') # 删除数据:
UserInfo.objects.filter(name='rain').delete() # 修改数据:
UserInfo.objects.filter(name='rain').update(name='Rain1') # 查找数据:
UserInfo.objects.filter(name='rain')
UserInfo.objects.all()
UserInfo.objects.all()[:10]
# 切片操作,获取10个人,不支持负索引,切片可以节约内存
UserInfo.objects.get(name='rain')
#查找所有
models.UserInfo.objects.all()
#查找指定条件
models.UserInfo.objects.filter(age=18)
#查找第一个
models.UserInfo.objects.filter(age=18).first()
#查找所有并且显示出来
user_list_obj = models.UserInfo.objects.all()
for line in user_list_obj:
print(line.username,line.age)
进阶操作
- 利用双下划线将字段和对应的操作连接起来
# 获取个数 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"
- F和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()
连表操作
连表关系:
- 一对多,models.ForeignKey(ColorDic)
- 一对一,models.OneToOneField(OneModel)
- 多对多,authors = models.ManyToManyField(Author)
应用场景:
- 一对一:在某表中创建一行数据时,有一个单选的下拉框(下拉框中的内容被用过一次就消失了)。 例如:原有含10列数据的一张表保存相关信息,经过一段时间之后,10列无法满足需求,需要为原来的表再添加5列数据。
- 一对多:当一张表中创建一行数据时,有一个单选的下拉框(可以被重复选择)。 例如:创建用户信息时候,需要选择一个用户类型【普通用户】【金牌用户】【铂金用户】等。
- 多对多:在某表中创建一行数据是,有一个可以多选的下拉框。 例如:创建用户信息,需要为用户指定多个爱好。
一对多
- 数据库表:models.py UserType存放用户类型,UserInfo存放用户信息
from django.db import models
# Create your models here. class UserType(models.Model):
caption = models.CharField(max_length=32)
# 超级管理员,普通用户,游客,黑河
def __str__(self):
return self.caption class UserInfo(models.Model):
user = models.CharField(max_length=32)
pwd = models.CharField(max_length=32)
user_type = models.ForeignKey('UserType')
- 创建有外键的数据
#方法一:需要进行两次数据库操作,不推荐
UserInfo.objects.create(user='test',pwd='',user_type=UserType.objects.get(id=1))
#方法二:利用外键关系进行直接插入值,此时user_type代指的就是usertype表
UserInfo.objects.create(user='test',pwd='',user_type_id=1) >>> from app01 import models
>>> models.UserInfo.objects.create(user='test',pwd='',user_type=models.UserType.objects.get(id=1))
<UserInfo: UserInfo object>
>>> models.UserInfo.objects.create(user='asdasdadas',pwd='',user_type_id=3)
<UserInfo: UserInfo object>
- 数据: 

- 查找
1.根据用户,查找用类型
>>> models.UserInfo.objects.filter(user="test")[0].user_type.caption
'管理员'
此时user_type对应的就是usertype的表,所以直接使用.caption就可以拿到数据
2.根据用户类型查找用户
#方法一:先查找出用户类型对应的user_type的id,然后再去userinfo表中查找id对应的用户
>>> role_id = models.UserType.objects.get(caption='管理员').id
>>> role_id
1
>>> models.UserInfo.objects.filter(user_type=role_id).values('user','pwd')
<QuerySet [{'pwd': '', 'user': '张三'}, {'pwd': '', 'user': 'test2'}, {'pwd': '', 'user': 'test'}]> #方法二:使用双下划线进行一次连表操作
>>> models.UserInfo.objects.filter(user_type__caption="管理员")
<QuerySet [<UserInfo: UserInfo object>, <UserInfo: UserInfo object>, <UserInfo: UserInfo object>]>
>>> sql[0].user
'张三'
>>> sql[0].pwd
''
>>> sql[0].user_type.caption
'管理员'
>>> sql[0].user_type.id
1 继续封装,同时取用户的所有信息:
>>> sql = models.UserInfo.objects.filter(user_type__caption="管理员").values('user','pwd','user_type__id','user_type__caption')
>>> sql
<QuerySet [{'user_type__id': 1, 'pwd': '', 'user': '张三', 'user_type__caption': '管理员'}, {'user_type__id': 1, 'pwd': '', 'user': 'test2', 'user_type__caption': '管理员'}, {'user_type__'pwd': '123', 'user': 'test', 'user_type__caption': '管理员'}]> 打印sql语句:
>>> print(sql.query)
SELECT "app01_userinfo"."user", "app01_userinfo"."pwd", "app01_userinfo"."user_type_id", "app01_usertype"."caption" FROM "app01_userinfo" INNER JOIN "app01_usertype" ON ("app01_userinfo"."user_type_id" = "app01_usertype"."id") WHERE "app01_usertype"."caption" = 管理员
跨多张表进行操作,如果UserType表中还有外键指向另一张表的主键,怎么查呢?
新的表结构如下:
from django.db import models
# Create your models here. class UserType(models.Model):
caption = models.CharField(max_length=32) # 超级管理员,普通用户,游客,黑河
s = models.ForeignKey('something')
def __str__(self):
return self.caption class UserInfo(models.Model):
user = models.CharField(max_length=32)
pwd = models.CharField(max_length=32)
user_type = models.ForeignKey('UserType') class something(models.Model):
name = models.CharField(max_length=32)
查询:
models.UserInfo.objects.filter(user_type__s__name="一些条件值"
这是跨两张表,跨三张表、四张表都这样
多对多
- 表结构: 一个girl表、一个boy表,还一个boy_girl的关系表
class Girl(models.Model):
name = models.CharField(max_length=32)
b = models.ManyToManyField('Boy') class Boy(models.Model):
name = models.CharField(max_length=32)
PS:多对多关系需要三张表,两张数据表,一张关系表,但是在django 中如果使用ManyToManyField的话,不需要在指定第三张表,默认django会创建。当然,如果不使用该字段的话,也可以手动指定第三张表,然后使用models.ForeignKey做外键关联
- 添加数据
添加数据到关系表:
女孩跟男孩建立关系 正向操作
>>> G = models.Girl.objects.get(id=1)
>>> g = models.Girl.objects.get(id=1)
>>> girl = models.Girl.objects.get(id=1)
>>> boy = models.Boy.objects.get(id=3)
>>> girl.name
'fuzj3'
>>> boy.name
'fuzj2' #使用对象建立关系 >>> girl.b.add(boy) #此时的b时多对多的字段
>>> bs = models.Boy.objects.all() #获取男孩的所有对象,返回数组
>>> g.b.add(*bs) #批量将关系插入到关系表 #使用主键值建立关系
>>> girl = models.Girl.objects.get(id=3)
>>> girl.b.add(3)
>>> bs_list = [1,4,5]
>>> girl.b.add(*bs_list) 男孩跟女孩建立关系 反向操作 >>> boy = models.Boy.objects.get(id=1)
>>> boy
<Boy: Boy object>
>>> boy.girl_set.add(3)



删除
remove() 删除
clear() 清空
>>> g1 = models.Girl.objects.get(id=1) #获取一个女孩对象
>>> g1.b.remove(2) #单个删除一个关系
>>> g1.b.remove(*[3,4]) #批量删除多个关系
>>> g1.b.clear() #清空本对象对应的所有关系
查询
支持all() filer()等操作
1.通过女孩查找男孩(正向查找)
>>> models.Girl.objects.filter(name='fuzj2').values('id','name','b__name')
<QuerySet [{'name': 'fuzj2', 'id': 3, 'b__name': 'fuzj'}, {'name': 'fuzj2', 'id': 3, 'b__name': 'fuzj2'}, {'name': 'fuzj2', 'id': 3, 'b__name': 'fuzj3'}, {'name': 'fuzj2', 'id': 3, 'b__name': None}]> 'b__name'中 b此时代指的关系表,所以b__name 就是跨到了boy表,。此时相当于直接跨了两张表
2. 通过男孩查找女孩(反向查找)
>>> models.Boy.objects.filter(name='fuzj').values('id','name','girl__name')
<QuerySet [{'name': 'fuzj', 'id': 1, 'girl__name': 'fuzj2'}]> 'girl__name' 中,girl是boy表中隐藏的字段,代指的是和girl的关系表,所以girl__name就跨到了girl表
修改
默认django不支持修改操作,如果实现修改操作,只能是先删除,然后再创建,显然这个效率不是很高。所以,我们可以通过原生的sql语句进行操作
from django.db import connection
cursor = connection.cursor()
cursor.execute("update tbname set girl_id = '3' where boy_id = %s",[3])
中间件
中间件定义:
中间件是一个、一个的管道,如果相对任何所有的通过Django的请求进行管理都需要自定义中间件
中间件可以对进来的请求和出去的请求进行控制
中间件是一类。

由上图可知,中间件是位于wsgi和路由系统中间的环节。用户请求和和回应请求都会经过中间件。
看下面的代码在settings里中间件的类:
MIDDLEWARE_CLASSES = [
'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',
]
当有请求过来的时候,默认从上倒下执行!然后在返回的时候从下面在返回回去
自定义中间件
中间件中可以定义四个方法,分别是:
- process_request(self,request)
- process_view(self, request, callback, callback_args, callback_kwargs)
- process_exception(self, request, exception) 这个方法只有在出现错误的时候才会触发
- process_response(self, request, response)
- process_template_response(self,request,response) 这个方法只有在返回对象中有render方法的时候才执行,如render_to_response('/index/')
以上方法的返回值可以是None和HttpResonse对象,如果是None,则继续按照django定义的规则向下执行,如果是HttpResonse对象,则直接将该对象返回给用户。

- 创建中间件脚本
在django的的project目录下创建一个middleware目录,并创建一个md.py的脚本,内容如下:
class Testmiddle:
def process_request(self,request):
print 'Testmiddle process_request'
def process_view(self, request, callback, callback_args, callback_kwargs):
print 'Testmiddle process_view'
def process_exception(self, request, exception):
pass
def process_response(self, request, response):
print 'Testmiddle process_response'
return response class Nextmiddle:
def process_request(self,request):
print 'Nextmiddle process_request'
def process_view(self, request, callback, callback_args, callback_kwargs):
print 'Nextmiddle process_view'
def process_exception(self, request, exception):
pass
def process_response(self, request, response):
print 'Nextmiddle process_response'
return response
- 注册中间件
修改settings.py文件,在MIDDLEWARE_CLASSES中添加我们创建的中间件
MIDDLEWARE_CLASSES = [
'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',
'middleware.middle.Testmiddle',
'middleware.middle.Nextmiddle',
]
- 设置url 略
- 测试:
Testmiddle process_request
Nextmiddle process_request
Testmiddle process_view
Nextmiddle process_view
This app01 Views.index
Nextmiddle process_response
Testmiddle process_response
从输出结果可以看出:
他是先执行Testmiddle 的request 方法又执行了Nextmiddle的 process_request方法, 然后在执行Testmiddle的view方法,Nextmiddle的view方法
注意:django版本1.10以后,会报如下错误:

解决如下:
from django.utils.deprecation import MiddlewareMixin
class Testmiddle(MiddlewareMixin):
def process_request(self,request):
print 'Testmiddle process_request'
def process_view(self, request, callback, callback_args, callback_kwargs):
print 'Testmiddle process_view'
def process_exception(self, request, exception):
pass
def process_response(self, request, response):
print 'Testmiddle process_response'
return response class Nextmiddle(MiddlewareMixin):
def process_request(self,request):
print 'Nextmiddle process_request'
def process_view(self, request, callback, callback_args, callback_kwargs):
print 'Nextmiddle process_view'
def process_exception(self, request, exception):
pass
def process_response(self, request, response):
print 'Nextmiddle process_response'
return response
注意:
* 老版本中在中间件中如果某个中间件类的方法返回的不是none,则后面的中间件不会再处理请求,也不会到达路由系统,而是直接到第一个process_response,开始所有的process_response处理
* 新版本中在中间件中如果某个中间件类的方法返回的不是none,则后面的中间件不会再处理请求,也不会到达路由系统,而是直接到最后一个process_response处理,然后返回给客户端
django数据库操作和中间件的更多相关文章
- 从命令行运行django数据库操作
从命令行运行django数据库操作,报错: django.core.exceptions.ImproperlyConfigured: Requested setting DEFAULT_INDEX_T ...
- Django数据库操作(增删改查)
Django数据库操作(增删改查) 创建数据库中的一个表 class Business(models.Model): #自动创建ID列 caption = models.CharField(max_l ...
- Django 数据库操作
Django 数据库操作 Django运算表达式与Q对象/F对象 1 模型查询 概述: 1 查询集:表示从数据库中获取的对象的集合 2 查询集可以有多个过滤器,通过 逻辑运算符连接 3 过滤器就是一个 ...
- Django数据库操作
刚学到Django的数据库操作,把它记录下来,方便以后查看: 在Django中定义数据库表,并使用Django提供的方法来对数据库进行操作(增.删.改.查) 1.定义3个数据库表: class Gro ...
- 11.Django数据库操作(查)
django.db.models.query.QuerySet1.可迭代2.可切片 官方文档:https://docs.djangoproject.com/en/1.9/ref/models/quer ...
- django 数据库操作详解
Django配置使用mysql数据库 修改 settings.py 中的 DATABASES 注意:django框架不会自动帮我们生成mysql数据库,所以我们需要自己去创建. DATABASES ...
- Python Django 数据库操作
1. 建立app 在自己的工程项目目录下输入: python manage.py startapp myapp(你想建立的app名称) 建立一个叫myapp的app 这样,在你的工程项目目录下会出现一 ...
- Django 数据库操作进阶F和Q操作
Model中的F F 的操作通常的应用场景在于:公司对于每个员工,都涨500的工资.这个时候F就可以作为查询条件 1 2 3 from django.db.models import F models ...
- Python菜鸟之路:Django 数据库操作进阶F和Q操作
Model中的F F 的操作通常的应用场景在于:公司对于每个员工,都涨500的工资.这个时候F就可以作为查询条件 from django.db.models import F models.UserI ...
随机推荐
- JqueryDataTable的使用(.Net平台)
上一篇随笔提到了MvcPager,最近用到了一款前端JQ插件------DataTable(简称DT),很好用. DT是一款前端插件,和后端完全分离开,就这点来看,我就特别喜欢. 一.使用DT,需要以 ...
- 在xampp中配置dvwa
DVWA主要是用于学习Web的常见攻击,比如SQL注入.XSS等的一个渗透测试系统,下面我将结合XAMPP来说明它的安装过程. 一.环境 OS:Windows 10 XAMPP:5.6.24 DVWA ...
- UIViewControllerTransitioningDelegate, UIViewControllerAnimatedTransitioning
#import "ModelAnimationDelegate.h" #import <UIKit/UIKit.h> #import "MapVC.h&quo ...
- UITableview delegate dataSource调用探究
UITableview是大家常用的UIKit组件之一,使用中我们最常遇到的就是对delegate和dataSource这两个委托的使用.我们大多数人可能知道当reloadData这个方法被调用时,de ...
- 使用vscode访问和修改远程计算机文件
使用vscode访问和修改远程文件,分三步实现:在远程linux机器上安装rmate:在本地windows上安装openssh:在vscode中安装扩展remote vscode. 1. 在远程lin ...
- Mellanox 8亿美元收购EZchip
http://www.iccsz.com/site/cn/News/2015/10/08/20151008003916131771.htm Mellanox 8亿美元收购EZchip 目标电信运营商 ...
- Shell命令和流程控制
Shell命令和流程控制 在shell脚本中可以使用三类命令: 1)Unix 命令: 虽然在shell脚本中可以使用任意的unix命令,但是还是由一些相对更常用的命令.这些命令通常是用来进行文件和文字 ...
- js获取页面url中的各项值
一. 通过window.location获取各项参数 1.获取页面完整的url url = window.location.href; 2.获取页面的域名 host = window.location ...
- SQL必知必会 14-22(完)
博主依然不想打字,又向你仍来了一堆代码... 13(续) 在SELECT中用COUNT()以及联合 mysql> SELECT customers.cust_id,COUNT(orders.or ...
- wamp下Apache配置vhost
1.由于后面虚拟机中需要用到Rewrite所以先编辑Apache的conf目录下的httpd.conf文件.(我的文件位置是:D:\Program Files\wamp\bin\apache\apac ...