文章目录
ORM
Django内置的ORM框架:是一套对各种数据库的统一的API接口。
支持的数据库有:MySQL、Sqlite3、Oracle、PostgreSQL、MongoDB、SQL Server。
其它数据库要安装第三方包。
定义模型
开发者不再在数据库中创建数据表,而是在Django项目的models.py中定义模型,通过执行数据迁移,在数据库中自动生成表。
models.py
from django.db import models
class 模型名(models.Model):
字段1 = models.字段类型(字段选项)
字段2 = models.字段类型(字段选项)
# 重写函数,模型的返回值,如 print(模型的实例化对象)。只允许返回字符串
def __str__(self):
return str(self.xxx)
# 设置模型的属性
class Meta:
verbose_name = verbose_name_plural = 'xxx' # 模型在admin后台的名称显示,verbose_name_plural优先显示
定义字段
字段 = models.字段类型(字段选项)
字段类型 models.xxxField、字段类型的特殊参数
🔗Django.model和MySQL数据库数据类型对应关系
分类 | 字段类型 | 该字段类型的特殊参数 | 说明 | 举例 |
---|---|---|---|---|
自增 | AutoField | 一个 IntegerField,自增。如果没有定义id 且 整个模型没有定义主键,django自动定义id且设置为主键。 | ||
数字 | IntegerField | |||
FloatField | 内部使用 Python 的 float 类型 | |||
DecimalField | max_digits, decimal_places | 一个固定精度的十进制数,内部使用 Python 的 Decimal 类型 | ||
字符串 | CharField | max_length | ||
TextField | ||||
媒体资源(文件) | FileField | upload_to 、 max_length | 一个文件的路径(相对于 MEDIA_ROOT ) | setting.py中MEDIA_ROOT 设置为 ‘/home/media’,models.py中...=models.FileField(upload_to=r'photos/%Y/%m/%d',...) ,则文件保存在 /home/media/photos/2007/01/15 目录下 |
ImageField | upload_to 、 max_length、height_field、width_field | 继承 FileField 的所有属性和方法,增加 height 和 width 属性 | ||
时间 | DateField | auto_now、auto_now_add | 内部使用Python 的 datetime.date | auto_now=True :添加和修改数据的时间auto_now_add=True :只是添加数据的时间,修改不变 |
TimeField | auto_now、auto_now_add | 内部使用Python 的 datetime.time | ||
DateTimeField | auto_now、auto_now_add | 内部使用Python 的 datetime.datetime | ||
邮箱 | EmailField | max_length | 一个 CharField | |
外键 | ForeignKey | to on_delete | = models.ForeignKey('app2.MyModel2', on_delete=) |
所有字段类型的可选参数
字段类型的可选参数 | 说明 | 举例 |
---|---|---|
verbose_name | 字段的人可读名称(详细字段名),admin后台网站中字段显示的名称。如果没有给定,django 会使用字段名自动创建,并将下划线转换为空格 | |
primary_key | 字段设置为主键 | primary_key =True |
unique | 字段的值唯一 | |
null | 是否允许值为NULL,与数据库相关 | |
blank | 是否允许空字符串,与验证相关 | blank=False :表单验证中,该字段为必填字段 |
default | ||
editable | 是否是可编辑的 | editable =False :不会在管理或任何其他 ModelForm 中显示,在 模型验证 中也会跳过 |
choices | 默认为空列表,元素为二元组(实际值,人类可读名称) | STATUS = [ (0,‘审核’), (1,'通过'), (2,'拒绝'), ] ...=...(choices=STATUS, ...) |
db_column | 实际数据表的列名称,默认为model中的字段名 | |
db_index | 字段设置为索引 | db_index =True |
str()
# 重写函数,模型的返回值,如 print(模型的实例化对象)。只允许返回字符串
def __str__(self):
return str(self.xxx)
class Meta
# 设置模型的属性
class Meta:
verbose_name = verbose_name_plural = 'xxx' # 模型在admin后台的名称显示,verbose_name_plural优先显示
数据操作:封装到model中
🔗 @staticmethod和@classmethod的作用与区别
将view.py中的 xxxModel.objects.all()
封装到model中,步骤如下:
models.py
class xxxModel(models.Model):
... # 其他代码
@classmethod
def get_all(cls):
return cls.objects.all()
view.py
def index(request):
x = xxxModel.get_all()
QuerySet:操作数据
数据操作CRUD逻辑封装到model中,不要到view中用QuerySet。
仅仅测试一下,看看结果:python manage.py shell
假设例子的model为:Types、PersonInfo、Vocation
models.py:
class Types(models.Model):
id = models.AutoField(primary_key=True)
firsts = models.CharField('一级类型', max_length=100)
seconds = models.CharField('二级类型', max_length=100)
def __str__(self):
return str(self.id)
class Meta:
verbose_name = verbose_name_plural = '商品类型'
class PersonInfo(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=20)
age = models.IntegerField()
hireDate = models.DateField()
def __str__(self):
return self.name
class Meta:
verbose_name = verbose_name_plural = '人员信息'
class Vocation(models.Model):
id = models.AutoField(primary_key=True)
job = models.CharField(max_length=20)
title = models.CharField(max_length=20)
payment = models.IntegerField(null=True, blank=True)
name = models.ForeignKey(PersonInfo, on_delete=models.CASCADE, related_name='ps')
def __str__(self):
return str(self.id)
class Meta:
verbose_name = verbose_name_plural = '职业信息'
小结
两种创建model实例的写法
# 两种
t = Types() # Types类,需要加t.save()
t = Types.objects.xxx # QuerySet类,推荐
分类 | QuerySet方法 |
---|---|
insert 单条 | t = Types.objects.create(**dict) |
t = Types.objects.get_or_create(**dict) | |
t = Types.objects.update_or_create(**dict) | |
insert 批量 | t = Types.objects.bulk_create(list) |
delete | t = Types.objects.all().delete() |
t = Types.objects.get(id=1).delete() | |
t = Types.objects.filter(firsts=‘奶粉辅食’).delete() | |
update | t = Types.objects.filter(id=1).update(**dict) |
insert
单条新增:
from .models import Types
# 方法1:创建实例
t = Types()
t.firsts = '奶粉辅食'
t.seconds = '营养品'
t.save()
#
t = Types(firsts = '奶粉辅食', seconds = '营养品')
t.save()
# 方法2:create():若已存在,则报错
# 与方法1 等效
t = Types.objects.create(firsts = '奶粉辅食', seconds = '营养品')
#
d = dict(firsts='奶粉辅食', seconds='营养品')
t = Types.objects.create(**d)
# 方法3:get_or_create():若已存在,则返回结果
d = {'firsts':'奶粉辅食', 'seconds':'营养品')
t = Types.objects.get_or_create(**d)
# 方法4:update_or_create():若已存在,则更新
d = dict(firsts='奶粉辅食', seconds='营养品')
t = Types.objects.update_or_create(**d)
批量新增:
from .models import Types
# bulk_create()
t1 = Types(firsts='奶粉辅食', seconds='营养品')
t2 = Types(firsts='奶粉辅食', seconds='麦片')
obj_list = [t1, t2]
Types.objects.bulk_create(obj_list)
from index.models import *
t1 = PersonInfo(name= 'Lucy', age= '20', hireDate='2018-09-18')
t2 = PersonInfo(name= 'Tim', age= '18', hireDate='2018-09-18')
t3 = PersonInfo(name= 'Tom', age= '22', hireDate='2018-08-18')
t4 = PersonInfo(name= 'Mary', age= '24', hireDate='2018-07-10')
t5 = PersonInfo(name= 'Tony', age= '25', hireDate='2018-01-18')
obj_list = [t1, t2, t3, t4, t5]
PersonInfo.objects.bulk_create(obj_list)
t1 = Vocation(job= '软件工程师', title= 'Python开发', payment=10000, name_id=2)
t2 = Vocation(job= '文员', title= '前台文员', payment=5000, name_id=1)
t3 = Vocation(job= '网站设计', title= '前端开发', payment=8000, name_id=4)
t4 = Vocation(job= '需求分析师', title= '系统需求设计', payment=9000, name_id=3)
t5 = Vocation(job= '项目经理', title= '项目负责人', payment=12000, name_id=5)
obj_list = [t2, t3, t4, t5]
Vocation.objects.bulk_create(obj_list)
delete
from .models import Types
# 最后.delete()
# 删除某个表的全部数据
Types.objects.all().delete()
# 删除一条数据
Types.objects.get(id=1).delete()
Types.objects.filter(firsts='奶粉辅食').delete()
若表中有外键:
update
单个新增:
from commodity.models import Types
# 更新表的某个列所有数据
Types.objects.update(firsts='奶粉辅食')
# 更新一条数据
t = Types.objects.get(id=1)
t.firsts = '奶粉辅食'
t.save()
#
Types.objects.filter(id=1).update(firsts='奶粉辅食')
#
d = {'seconds':'奶粉辅食'}
Types.objects.filter(id=1).update(**d)
# 更新:数据自增自减
from django.db.models import F
t = Types.objects.filter(id=1)
t.update(id=F('id')+100)
search
order_by().all()
values().filter().distinct()
filter().order_by()
from index.models import *
# SELECT * FROM index_vocation
v = Vocation.objects.all() # QuerySet类列表,每个元素是Vocation类
v
v[0].id
# SELECT * FROM index_vocation LIMIT 3
v = Vocation.objects.all()[:3]
# SELECT job FROM index_vocation
v = Vocation.objects.values('job') # 列表元素为字典
#
v = Vocation.objects.values_list('job') # 列表元素为元组
# SELECT DISTINCT job FROM index_vocation
v = Vocation.objects.values('job').distinct()
# SELECT * FROM index_vocation WHERE id=2
v = Vocation.objects.get(id=2) # 只能返回一个Vocation对象,若结果0条或多于2条,都报错
v
# SELECT * FROM index_vocation WHERE job='文员'
v = Vocation.objects.filter(job='文员') # QuerySet类列表,每个元素是Vocation类,结果可为多条或 0条
# SELECT * FROM index_vocation WHERE id=2 AND job='文员'
v = Vocation.objects.filter(job='文员', id=2)
#
d = dict(job='文员', id=2)
v = Vocation.objects.filter(**d)
# SELECT * FROM index_vocation WHERE id=2 OR job='文员'
from django.db.models import Q
v = Vocation.objects.filter(Q(job='文员')|Q(id=2))
# SELECT * FROM index_vocation WHERE job!='文员'
# SELECT * FROM index_vocation WHERE job not in ('文员')
v = Vocation.objects.filter(~Q(job='文员'))
#
v = Vocation.objects.exclude(job='文员')
# SELECT * FROM index_vocation ORDER BY payment DESC, id
v = Vocation.objects.order_by('-payment', 'id')
# SELECT Count(*) FROM index_vocation
# SELECT Count(*) FROM index_vocation WHERE job='文员'
v = Vocation.objects.all().count()
#
v = Vocation.objects.filter(job='文员').count()
#