Django模型
Django对各种数据库提供了很好的支持,包括:PostgreSQL、MySQL、SQLite、Oracle。Django为这些数据库提供了统一的调用API,可按需选择不同数据库。
Django模型使用自带的ORM(对象关系映射Object Relational Mapping)用于实现面向对象编程语言里不同类型系统的数据之间的转换。
ORM
ORM 在业务逻辑层和数据库层之间充当了桥梁的作用。ORM 是通过使用描述对象和数据库之间的映射的元数据,将程序中的对象自动持久化到数据库中。
ORM解析过程:
- ORM将Python代码转换成SQL语句
- SQL语句通过pymysql传送到数据库服务端
- 在数据库中执行SQL语句并将结果返回
- 使用ORM优点:提高开发效率、不同数据库可以平滑切换。
- 使用ORM缺点:ORM代码转换为SQL语句时,需花费一定时间,执行效率会有所降低; 长期写ORM代码,会降低编写SQL语句的能力。
类实例 ---------> 表中的一条记录
然后通过对类,类属性,类实例的各种操作,达到操作数据库的功能,底层是生成原生的sql进行数据操作。
安装数据库
创建数据库的docker命令
docker run --name ck10_mariadb --restart=always -d -v ck10_mariadb:/var/lib/mysql -e MARIADB_ROOT_PASSWORD=pythonvip -p 4002:3306 -e MARIADB_DATABASE=lemontest mariadb:latest
django配置数据库
安装驱动
mysql,mariadb,django官方推荐的驱动程序mysqlclient
。
windows环境
在网站https://www.lfd.uci.edu/~gohlke/pythonlibs/#mysqlclient
下载与python版本对应的mysqlclient
本地安装文件,再使用pip命令安装,例如:
pip install mysqlclient‑1.4.6‑cp38‑cp38‑win_amd64.whl # py3.8 64位
mac环境
依赖mysql客户端
$ brew install mysql-client
$ echo 'export PATH="/usr/local/opt/mysql-client/bin:$PATH"' >> ~/.bash_profile
$ source .bash_profile
$ pip install mysqlclient
Linux环境
linux环境下需要对应的依赖,根据环境不同依赖有所不同,下面的只是基本的步骤,不能保证在所有的环境上都有效。
Debian/Ubuntu
$ sudo apt-get install python3-dev default-libmysqlclient-dev build-essential
$ pip install mysqlclient
Red Hat /CentOS
sudo yum install python3-devel mysql-devel
pip install mysqlclient
连接配置
在settings.py中修改如下配置:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'lemontest',
'USER': 'root',
'PASSWORD': 'pythonvip',
'HOST': 'www.hhxpython.com',
'PORT': '4002'
}
}
模型
django中的模型准确且唯一的描述了数据。它包含存储数据的重要的字段和行为。一般来说,每一个模型都映射一个张数据库表。
基础:
- 每个模型都是一个python的类,这些类都要继承
django.db.models.Model
- 模型类的每个属性都相当于数据库的一个字段
- 利用这些,Django提供了一个自动生成访问数据库的API
创建模型
设计一张学生表tb_student
,表结构如下:
id int not null auto_increment primarykey
name varchar(20) not null
age tinyint default null
sex tinyint default null
qq varchar(20) default null unique
phone varchar(20) defautl null unique
c_time datetime not null
跟视图一样,django中模型一般定义在应用目录下的models.py
模块下:
from django.db import models
class Student(models.Model): # 必须继承
name = models.CharField('姓名', max_length=20, help_text='姓名')
age = models.SmallIntegerField('年龄', null=True, blank=True, help_text='年龄')
sex = models.SmallIntegerField('性别', default=1, help_text='性别')
qq = models.CharField('qq号码', max_length=20, null=True, blank=True, unique=True, help_text='qq号码')
phone = models.CharField('手机号码', max_length=20, null=True, blank=True, unique=True, help_text='手机号码')
c_time = models.DateTimeField('创建时间', auto_now_add=True)
#模型类里面输出字段,如果是int类型的要加str(),不然查询后获取会报错
def __str__(self):
"""定义每个数据对象的显示信息"""
return str(self.name)
class Meta:
db_table = 'tb_student' # 设置创建表示的表名
verbose_name = '学生信息'
verbose_name_plural = verbose_name # django admin中显示模型的说明
表的字段类型和字段参数
每一个字段由一个字段类的实例表示。每个字段实例的名称,类属性名,就是字段的名称,数据库也会以它为列名。
字段类型:
- models.AutoField 自增列=int(11) 如果没有的话,默认会生成一个名称为id的列,如果要显示为一个自定义自增列,必须将列设置为主键 primary_key=True
- models.CharField 字符串字段,必须给max_length参数
- models.TextField 字符串=longtext
- models.BlooleanField 布尔型字段=tinyint(1) 不能为空,blank=True
- models.NullBooleanField 允许为空的布尔类型
- models.CommaSeparatedIntegerField 用逗号分割的数字=varchar。继承CharField,所以必须给max_length参数
- models.DateField 日期类型date,参数:auto_now=True则每次都会更新这个时间;auto_now_add=True则是第一次创建添加,之后的更新不会改变
- models.DateTimeField 日期类型datetime,同DateField的参数
- models.TimeField 时间 HH:MM:[ss[.uuuuuu]]
- models.EmailField 字符串类型(正则表达式邮箱)=varchar 对字符串进行正则表达式
- models.URLField 字符串,地址正则表达式
- models.FloatField 浮点类型=double
- models.IntegerField 整型(-2147483648,2147483647)
- models.BigIntegerField 长整型(-9223372036854775808, 9223372036854775807)
- models.SmallIntegerField 数字(-32768,32767) 数据库中的字段有:tinyint、smallint、int、bigint
- models.PositiveIntegerField 正Integer(0,32767)
- models.PositiveSmallIntegerField 正smallInteger(0, 2147483647)
- models.SlugField 减号、下划线、字母、数字
- models.IPAddressField 字符串类型(ip4正则表达式)
- models.GenericIPAddressField 字符串类型(ip4和ip6是可选的)。参数:protocol可以是:'both' 'ipv4' 'ipv6' 验证时会根据设置报错
- models.DecimalField 十进制小数类型=decimal。必须指定整数位max_digits和小数位decimal_places
- models.BinaryField 二进制
- models.ImageField 图片
- models.FileField 文件
字段参数:
-
null=True 数据库中字段是否可以为空
-
blank=True django的Admin中添加数据时是否可以允许空值
-
primary_key=False 主键,对AutoField设置主键后,就会代替原来的自增id列
-
auto_now=True 自动创建—无论添加或修改,都是当前操作时间
-
auto_now_add=True 自动创建—永远是创建时的时间
-
choice
选项框,定义一个元组变量,参数值取该变量
GENDER_CHOICE = ((u'M',u'Male'),(u'F',u'Female')) gender= models.BigIntegerField(choices=GENDER_CHOICE)
-
max_length
-
default 默认值
-
verbose_name Admin中字段的现实名称
-
db_column 数据库中的字段名称
-
unique=True 不允许重复
-
db_index=True 数据库索引
-
editable=True 在Admin里是否可编辑
-
error_messages=None 错误提示
-
auto_created=False 自动创建
-
help_text 在Admin中提示帮助信息
-
validators=[]
-
upload-to
自主设置 主键primary_key 例子:
django的models新增数据库表时,如果不设置主键,会默认新增一个id为主键,想自己设置一个字段为主键,需加个参数primary_key=True
from django.db import models
#新增产品表,设置产品名称为主键,让产品名不重复
class Prouct(models.Model):
product_name = models.CharField(max_length=20,primary_key=True)
person_email = models.EmailField(max_length=30)
激活模型
安装应用
把应用添加到项目中,在配置文件中设置:
INSTALLED_APPS = [
...
'crm.apps.CrmConfig'
]
生成迁移记录
在命令行运行如下命令:
python manage.py makemigrations crm
会在应用的migrations
目录下生成迁移记录文件。
通过运行makemigrations
命令,django会检测你对模型文件的修改(修改了模型,修改了字段),并把修改的部分存储为一次迁移。
数据迁移
django有一个自动执行数据库迁移并同步管理数据库结构的命令migrate
。
通过命令sqlmigrate
可以看到你要迁移的sql。
python manage.py sqlmigrate crm 0001
那么就会输出对应迁移文件要执行的sql。
运行命令
python manage.py migrate
第一次迁移时,django会在数据库中创建一个特殊的表django_migrations
用来记录和跟踪执行过哪些迁移。
改变模型的时候需要三步:
- 编辑models.py文件,改变模型
- 运行
python mange.py makemigrations
为模型的改变生成迁移文件 - 运行
python mange.py migrate
应用数据库迁移
数据库操作
django会自动给予一条数据库抽象API。
为了方便调试,我们通过下面的命令进入交互式python命令行:
python mange.py shell
这个命令会导入当前项目的django环境。
默认的python解释器,没有补全和高亮功能,推荐安装ipython
pip install ipython
新增数据
from django.http import HttpResponse
from models import Student
# 数据库操作
def add_user(request):
test1 = Student(name='叶凡' ,age=1000)
test1.save()
return HttpResponse("数据库Student用户添加成功")
查询数据
-
通过objects这个模型管理器的 all() 获取所有数据行,相当于SQL中的select * from
a = Student.objects.all()
-
filter() 相当于SQL中的where,可设置条件过滤结果, 结果为list
b = Student.objects.filter(name='小明')
-
get() 获取单个对象
c = Student.objects.get(name='小兰')
-
索引 限制返回的数据,相当于SQL中的offset 0 limit 2; 如下返回2条
d = Student.objects.order_by('name')[0:2]
-
order_by()查询结果排序
e = Student.objects.order_by('id')
-
上面的方法可以连着使用
d = Student.objects.filter(name='小红').order_by('id')[0:2]
更新数据
from django.http import HttpResponse
from models import Student
# 更新数据方法
def update_user(request):
# 方法一:通过objects模型管理器的get()获取指定数据行,修改再save,相当于SQL中的update
test2 = Student.objects.get(name='无始')
test2.age = '120000'
test2.save()
# 方法二:通过objects模型管理器的filter()获取id=2的数据行,再update指定字段
Student.objects.filter(id=2).update(age='3000')
# 修改所有行: 通过objects模型管理器的all()获得所有数据行,相当于SQL中的SELECT * FROM,
Student.objects.all().update(age='100')
return HttpResponse("<p>年龄修改成功</p>")
删除数据
from django.http import HttpResponse
from models import Student
# 更新数据方法
def delete_user(request):
# 方法一:通过objects模型管理器的get()获取name='小凡'的数据行,再delete该行
test3 = Student.objects.get(name='小凡')
test3.delete()
# 方法二:通过objects模型管理器的filter()获取id=1的数据行,再delete该行
Student.objects.filter(id=1).delete()
# 删除所有数据:通过objects模型管理器的all()获取所有数据行,再delete
Student.objects.all().delete()
return HttpResponse("<p>数据删除成功</p>")
查询表结果详解
django查询数据库的方法很多,不同的方法返回的结果也不太一样,以下13个查询方法:
- 返回对象是对象列表的:all() filter() exclude() order_by() reverse() values() values_list() distince()
- 返回结果是对象的:get() first() last()
- 返回结果是布尔值的:exists()
- 返回结果是数字的:count()
准备数据(之前的Student**表)
get() 从数据看取得唯一一个匹配的结果,返回一个对象。调用者是objects管理器,返回查询到model对象(查询结果有且只有一个才执行)。
查询结果有多个,会报错MultipleObjectsReturned,如果查询结果有0个,会报错DoesNotExist。
r = Student.objects.get(name='叶凡').age()
ret = Student.objects.get(name='叶凡')
r = ret.name + str(ret.age)
first() 和 last() 返回第一条记录和返回最后一条记录,返回的是一个对象。调用者是queryset,返回model对象
#同 fir = Student.objects.all().orderby('age')[0]
fir = Student.objects.all().order_by("age").first()
f = fir.age
fir = Student.objects.all().order_by("age").first().age
las = Student.objects.all().order_by("age").last().age
exists() 如果queryset包含数据,就返回True,否则返回False。调用者是queryset,返回布尔值
is_exist = Student.objects.all().exists()
count() 数数,由queryset对象调用,返回int
ret = Student.objects.all().count()
可迭代对象queryset all()
查询整张表sql:select * from Student;
django里查询数据库不需写sql语句,而是objects模型管理器,ret=Student.objects.all() 返回的是整个表的内容,这里返回的是可迭代对象queryset,要取出数据,需要用for循环读取。
from django.http import HttpResponse
from helloApp.models import Student
def select_all(request):
ids,names,ages = '',"",""
ret = Student.objects.all()
for i in ret:
ids += " " + str(i.id)
names += " " + i.name
ages += " " + str(i.age)
return HttpResponse("<p>查询id结果:%s</p><p>查询name结果:%s</p><p>查询age结果:%s</p>"%(ids,names,ages))
筛选条件 filter()
类似SQL中的where语句:select * from Student where id=7 and name='小凡';
filter()查询结果也是可迭代对象,如果只有一个,可以通过下标取值。找不到的时候给个默认值null。
HelloWorld/ HelloWorld /testdb.py setting.py同级
from django.http import HttpResponse
from helloApp.models import Student
def filter_user(request):
r = ""
ret = Student.objects.filter(id=7,name='叶凡')
try:
r = ret[0].age
except:
r = "null"
return HttpResponse("<p>查询结果:%s</p>" %r)
可迭代的字典序列 values()
all()和filter()返回的都是可迭代的queryset序列,平常我们习惯获取字典的对象,可用values()方法获取。
Student.objects.all().values(“id”,”name”) 类似于SQL语句:select id,name from Student
from django.http import HttpResponse
from helloApp.models import Student
def values_user(request):
r = ''
ret = Student.objects.all().values("id","name","age")
for i in ret:
r += str(i)
return HttpResponse("<p>查询结果:%s</p>" %r)
其他可迭代对象:
exclude() 它包含了与所给筛选条件不匹配的对象。由objects管理器调用,返回queryset。
#查找用户名不是“叶凡”的数据:
ret = Student.objects.exclude(name="叶凡")
order_by() 对查询结果排序。由queryset对象调用,返回值是queryset。默认是降序,在前面加 – 是代表降序。
# 查询所有数据,按age字段排序,默认升序
ret = Student.objects.all().order_by("age")
# 查询name='曹雨生'的数据,按age字段降序排序
ret = Student.objects.filter(name='曹雨生').order_by("-age")
reverse() 对查询结果反向排序。由queryset对象调用,返回值是queryset
# 查询所有数据,按age排序,默认升序,再反向排序,功能与-age一样
ret = Student.objects.all().order_by('age').reverse()
#查询name='曹雨生'的数据,再反向排序
ret = Student.objects.filter(name='曹雨生').reverse()
values_list() 和values()差不多,返回是元组。由queryset对象调用,返回值是queryset
ret = Student.objects.all().values_list("id","name")
distinct() 从返回结果中剔除重复记录。由queryset对象调用,返回值是queryset。 和SQL中的distinct去重一样。
ret = Student.objects.all().values("id","name","age").distinct()
数据库查询延伸
django对数据库进行条件查询格式:字段名+两个下划线+查询方法。这些查询方法get和filter都可以使用,但get每次返回的值是惟一的否则报错。
- all 返回全部数据,为queryset对象 Person.objects.all()
- lt 返回小于目标值的queryset; lte 返回小于等于目标值的queryset。 Person.objects.filter(idlt=5) Person.objects.filter(idlte=5)
- gt 返回大于目标值的queryset; gte 返回大于等于目标值的queryset。 Person.objects.filter(idgt=4) Person.objects.filter(idgte=4)
- 包含:contains区分大小写; icontains不区分大小写。 Person.objects.filter(namecontains=’ab’) Person.objects.filter(nameicontains=’ab’)
- 精确匹配:exact区分大小写;iexact不区分大小写。 Person.objects.filter(nameexact=’Dog’) Person.objects.filter(nameiexact=’Dog’)
- 起始匹配:startswith区分大小写;istartswith不区分大小写。 Person.objects.filter(namestartswith=’At’) Person.objects.filter(nameistartswith=’At’)
- 末尾匹配:endswith区分大小写;iendswith不区分大小写。 Person.objects.filter(nameendswith=’by’) Person.objects.filter(nameiendswith=’by’)
- startswith、endswith混合:Person.objects.filter(namestartswith=’A’,nameendswith=’y’)
- in:同时查找多个符合条件的数据,相当于批量的精确查找。 Person.objects.filter(id__in=[101,102,103])
- range:取范围内的值(两边都是闭合,两侧包含)只要是包含这个范围内的值否返回。 Person.objects.filter(id__range=[220,290])
- isnull:返回是空值的数据,True为空,False非空。 Person.objects.filter(idisnull=True) # 返回[] Person.objects.filter(idisnull=False) # 返回非空数据
- Q:多条件联合查询,使用前需导入Q模块 from django.db.models import Q
q1 = Q(create_time__year__in=[2018,2019])
q2 = Q(create_time__month=2)
blogs = BologModel.objects.filter(q1,q2)
使用Q()传入相应条件,然后把Q传入查询的函数中,可以传多个Q然后进行查询。q1,q2中间是逗号时取交集,中间是 | 时取并集。
标签:name,models,数据库,Django,filter,objects,Student,django,模型 From: https://www.cnblogs.com/chenxdnote/p/17223102.html