Django(四):模型层Model

本文深入介绍了Django的ORM框架,包括模型定义、字段类型及其参数、数据操作方法如插入、删除、更新和搜索,以及数据迁移。通过模型定义在数据库中自动生成表,使用QuerySet进行数据操作,详细阐述了各种字段类型的特性和使用场景,以及如何在模型中封装数据操作逻辑。此外,还涵盖了数据迁移的过程,帮助读者全面理解Django中数据的管理方式。
摘要由CSDN通过智能技术生成


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 类型
DecimalFieldmax_digits, decimal_places一个固定精度的十进制数,内部使用 Python 的 Decimal 类型
字符串CharFieldmax_length
TextField
媒体资源(文件)FileFieldupload_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 目录下
ImageFieldupload_to 、 max_length、height_field、width_field继承 FileField 的所有属性和方法,增加 height 和 width 属性
时间DateFieldauto_now、auto_now_add内部使用Python 的 datetime.dateauto_now=True:添加和修改数据的时间
auto_now_add=True:只是添加数据的时间,修改不变
TimeFieldauto_now、auto_now_add内部使用Python 的 datetime.time
DateTimeFieldauto_now、auto_now_add内部使用Python 的 datetime.datetime
邮箱EmailFieldmax_length一个 CharField
外键ForeignKeyto
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)
deletet = Types.objects.all().delete()
t = Types.objects.get(id=1).delete()
t = Types.objects.filter(firsts=‘奶粉辅食’).delete()
updatet = 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的数据迁移

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值