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

#

数据迁移:在数据库中生成表

🔗Django的数据迁移

Logo

GitCode 天启AI是一款由 GitCode 团队打造的智能助手,基于先进的LLM(大语言模型)与多智能体 Agent 技术构建,致力于为用户提供高效、智能、多模态的创作与开发支持。它不仅支持自然语言对话,还具备处理文件、生成 PPT、撰写分析报告、开发 Web 应用等多项能力,真正做到“一句话,让 Al帮你完成复杂任务”。

更多推荐