Django模型层

image
Django中内嵌啦ORM框架,不需要直接编写SQL语句金喜数据库操作,而是通过定义模型类,操作模型类来完成对数据库中表的增删该查
ORM(object,relation,mapping)
O是object,也就****类对象的意思。
R是relation,翻译成中文是关系,也就是关系数据库中****数据表的意思。
M是mapping,是****映射的意思。

类:sql语句table表
类成员变量:table表中的字段、类型和约束
类对象:sql表的表记录

可以通过以下操作对Django的数据库操作

1.配置数据库连接信息
2.在models.py中定义模型类
3.生成数据库迁移文件并执行迁移文件[注意:数据迁移是一个独立的功能,这个功能在其他web框架未必和ORM一块]
4.通过模型类对象提供的方法或属性完成数据表的增删改查

配置数据库连接

在settings.py中保存啦数据库的连接配置信息,Django默认初始配置使用sqlite数据库

使用mysql前需要先安装驱动程序,官方推荐使用mysqlclient,我们这里介绍pymysql和mysqlclient

#首先介绍pymysql,在任意的Django项目中的init文件中导入pymysql
from pymysql import install_as_MySQLdb
install_as_MySQLdb() #这样写是相当于猴子补丁,把orm默认使用的数据库连接替换了pymysql

#mysqlclient #官方推荐
在ubuntu安装mysqlclient
sudo apt install libmysqlclient-dev python3-dev
pip install mysqlclient

#然后接下来在settings文件中配置数据库连接
DATABASES={
’default‘:’django.db.backends.mysql‘,
'HOST1': ’ip地址‘,
’PORT‘:3306,#端口号,如果你改了端口这里也需要改
‘USER’:‘用户’,
‘password’:‘密码’,
‘NAME’:‘库名称’,#连接那个数据库
‘CHARSET’:‘编码格式’,#utf8   or   utf8mb4
}

字段类型

image

约束选项

image
注意:null是数据库范畴的概念,blank是表单验证范畴的

makemigrations,migrate的使用

设置公共的模型类,以后生条每条记录都是有时间,可以把这个时间设置为公共类,但是遮盖公共类设置为抽象类,这样就不会和数据库中的表产生映射关系
class Basemodel(models.Model):
    create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
    update_time = models.DateTimeField(auto_now=True, verbose_name='修改时间')

    class Meta(object):
        abstract = True  # 设置当前模型为抽象类,当系统运行时,就不会认为和数据库有一一映射的关系了

from django.db import models

# Create your models here.
from .Base_model import Basemodel


class Person(Basemodel):
    name = models.CharField(max_length=30, verbose_name='username')
    pwd = models.CharField(max_length=20, verbose_name='pwd')
    gender = models.CharField(max_length=20, verbose_name='性别', default='female')
    price = models.DecimalField(max_digits=20, decimal_places=5, verbose_name='价格')

    # auto_now_add 当数据添加时,设置当前时间为默认值
    # auto_now 当数据添加/更新时,设置当前时间为默认值
    class Meta:
        # abstract = True  # 设置当前模型为抽象模型,当系统运行时,不会认为这是一个数据表对应的模型
        db_table = 'tb_person'  # 指明数据库表名,如果没有指定表名,则默认为子应用目录名
        verbose_name = '人表'  # 在admin站点中显示的名称
        verbose_name_plural = verbose_name  # 显示的复数名称

#注意:一定要在命令行窗口,并且在manage.py目录下运行,下面有详细步骤
python manage.py   makemigrations
python manage.py migrate

image

以下均为测试数据

增加数据

第一种方法:create
def test01(request): 
student=Person.objects.create(name='zhangsan',pwd='123',gender='faamle',price='6666',total='8888')
    print(student.id)
    return HttpResponse('userinfo')

第二种方法:save()
 student=Person(
        name='wangwu',
        pwd='23',
        gender='female',
        price='123456',
        total='6666666',
    )
    student.save()
    print(student.id)
    return HttpResponse('userinfo')

查询数据

all() #查询所有对象,返回queryset对象,获取模型类集合
def test01(request):
    stu=Person.objects.all()
    for i in stu:
        print(i.pk)
    return HttpResponse('userinfo')
	
filter()  # 筛选条件相匹配的对象,返回queryset对象
def test01(request):
    stu=Person.objects.filter(gender='female').filter(pk=1) #支持链式表达式,多个filter合并是and关系
    for i in stu:
        print(i)
    return HttpResponse('userinfo')

get() #返回与所给筛选条件想匹配的对象,返回结果有且只有一个,如果筛选条件的对象超过一个或者没有,都会抛出错误
def test01(request):
    stu=Person.objects.get(pk=1,gender='male')
    print(stu)
    return HttpResponse('userinfo')

first(),last() #返回第一条记录和最后一条记录
def test01(request):
    stu = Person.objects.first()
    stu1=Person.objects.last()
    print(stu,stu1)
    return HttpResponse('userinfo')

exists() #判断查询结果中是否有某个数据,有返回True,没有返回False
def test01(request):
    res=Demo_db.objects.filter(pk=101).exists()
    print(res)
    return HttpResponse('userinfo')

exclude() #筛选条件不匹配的对象(除了某个条件之外,返回剩余的),返回queryset对象
def test01(request):
    res = Demo_db.objects.exclude(pk=1)
    for i in res:
        print(i)
    print(res)
    return HttpResponse('userinfo')

order_by() #对查询结果排序
在查询字段增加减号(-)表示从大到小排序
def test01(request):
    res = Demo_db.objects.all().order_by('-age') #从大到小
    print(res)

    res1 = Demo_db.objects.all().order_by('age')
    print(res1) #从
    return HttpResponse('userinfo')

count() #统计对象的个数
def test02():
    res = Demo_db.objects.filter(sex=1).count()
    print(res)

values() #把结果集中的对象转换成字典,列表套字典,可以指定查那些字段,达到减少内存消耗,提高性能
def test02():
    res = Demo_db.objects.values('pk','name')
    for i in res:
        print(i)
values_list()  #默认结果是一个个元祖,可以指定需要那些字段
def test02():
    res = Demo_db.objects.values_list('pk','name')
    for i in res:
        print(i)

distinct()  #从返回结果中剔除重复记录,返回queryset对象
def test02():
   res=Demo_db.objects.values('age').distinct()
   print(res)

contains #模糊查询 (双下划线__)
说明:如果包含%无需转意,直接写即可
def test02():
    res = Demo_db.objects.filter(name__contains='程') #  %程%
    print(res)

startwith 
def test02():
    res = Demo_db.objects.filter(name__startswith='程')  # %程
    print(res)

endwith
def test02():
    res = Demo_db.objects.filter(name__endswith='程') # 程%
    print(res)

**以上运算符都区分大小写,在这些运算符前加上i表示不区分大小写,如iexact、icontains、istartswith、iendswith.**
def test02():
    res = Person.objects.filter(gender__icontains='MALE')
    print(res)

in  
def test02():
    res = Person.objects.filter(id__in=[1,3,5])
    print(res)

range #范围查询
def test02():
    res = Demo_db.objects.filter(pk__range=(1,10))
    print(res)

模糊查询之比较查询
def test02():
    res = Demo_db.objects.filter(pk__gt=3)   #大于
    res1=Demo_db.objects.filter(pk__gte=10)   #大于等于
    res2=Demo_db.objects.filter(pk__lt=10)    #小于
    res3=Demo_db.objects.filter(pk__lte=10)   #小于等于10
    print(res)
    print(res1)
    print(res2)
    print(res3)

模糊查询之日期查询
**year、month、day、week_day、hour、minute、second:对日期时间类型的属性进行运算。
def test02():
    res=Demo_db.objects.filter(create_time__year=2021).values_list()
    res1=Demo_db.objects.filter(create_time__month=8).values('id','name')
    res2=Demo_db.objects.filter(create_time__day=20).count()
    print(res)
    print(res1)
    print(res2)

Q查询  #多个过滤器逐个调用逻辑与关系没,同sql语句中where部分的and关键字
例如:查询年龄大于20,并且编号小于30的学生
def test02():
    res=Demo_db.objects.filter(Q(Q(age__gt=20) & Q(pk__lt=30)))
    print(res)

def test02():
    # res=Demo_db.objects.filter(Q(Q(age__gt=20) & Q(pk__lt=30)))
    # res = Person.objects.filter(Q(Q(price__gt=10000) | Q(gender='male')))
    res = Demo_db.objects.filter(Q(Q(age__lt=19) | Q(age__gt=20))).all()
    print(res)

Q对象左边可以使用~操作符,表示非not。
def test02():
    res = Person.objects.filter(~Q(pk=5))
    print(res)

F #查询
两个字段的值比较,更新,过滤字段
def test02():
    res = Demo_db.objects.filter(pk=1).update(age=F('age') + 10, create_time=F('create_time'))
    print(res)

聚合查询

raw:执行原生SQL语句
执行原生SQL返回一个对象:<RawQuerySet: select * from test_tb where age > 20>
def test02():
    res=Demo_db.objects.raw('select * from test_tb where age > %s',(20,))
    for i in res:
        print(i)
    print(res)

使用aggregate()过滤器调用聚合函数,聚合函数包括:
Avg:平均
Count:数量
Max:最大
Min:最小
Sum:求和
ps:
def test02():
    # res1 = Person.objects.aggregate(total_avg=Avg('total'))
    # res=Person.objects.aggregate(my_sum=Sum('price'))
    res2 = Demo_db.objects.aggregate(my_age=Max('age'))
    res3 = Demo_db.objects.aggregate(my_age=Min('age'))
    res4 = Demo_db.objects.aggregate(my_pk=Count('pk'))
    print(res2)
    print(res3)
    print(res4)

修改记录

save() #修改 性能查,不推荐使用
def test02():
    res = Person.objects.first()
    res.gender = 'male'
    res.save()
    print(res)

update() #修改,推荐使用,基于queryset对象,返回影响的行数
#使用时请务必加上条件,否则影响的是全局,亲测
def test02():
    #
    # res = Person.objects.filter(pk=1).update(name='tany')
    res1 = Person.objects.filter(pk=2).update(
        name='tank',
        pwd=123,
        gender='male',
        price=66,
        total=10000,
    )
    print(res1)

删除记录

!删除记录时一定要加上条件,否则就变成清空表了

def test02():
    res=Demo_db.objects.filter().delete() #清空表,谨慎操作
    print(res)

delete #有两种方法
def test02():
    res = Person.objects.filter(pk=1).delete() #返回一个元组,第一个可以理解为删除的记录数,第二个是影响的函数
    print(res)

#下面这种方式删除返回删除记录的名字
def test02():
    res = Person.objects.get(pk=2)
    res.delete()
    print(res)

创建关联关系

在设置外键时,需要通过on_delete选项指明主表删除数据时,对于外键引用表数据如何处理,在django.db.models中包含类可选常量:
CASCADE #级联,删除主表数据时连通一起删除外键表中数据
PROTECT #保护,通过抛出***ProtectedError异常,来阻止删除主表中被外键应用的数据
SET_NULL #设置为NULL,近在该字段设置了默认值时可用
SET_DEFAULT #设置为默认值,仅在该字段设置类默认值时可用
SET()  #设置特定值或者调用特定方法

一对一(内部的关联关系)
class Employee(Basemodel):
    name = models.CharField(max_length=32, verbose_name='公司部门')
    address = models.CharField(max_length=100, verbose_name='公司地址')

    parent = models.ForeignKey('self', on_delete=models.SET_NULL, null=True, verbose_name='所属部门')

    class Meta:
        db_table = 'employee'
        verbose_name = '部门表'

**一对多**
#正向查询按字段
#反向查询类名小写+_set
class Employee(Basemodel):
    name = models.CharField(verbose_name='员工姓名', max_length=20, unique=True)
    job = models.CharField(verbose_name='员工职位', max_length=2, choices=Jobchoices.choices, default=Jobchoices.CE)
    entry_date = models.DateField(verbose_name='入职日期', default=date.today())
    sal = models.IntegerField(verbose_name='薪资级别')
    bonus = models.IntegerField(verbose_name='津贴', default=0)
    is_leave = models.BooleanField(verbose_name='是否离职', default=False)
    # 允许为空,且为空字符
    dept = models.ForeignKey('Deptmodel',
                             verbose_name='员工所属的部门',
                             on_delete=models.SET_NULL,
                             null=True,
                             blank=True)

    class Meta:
        db_table = 't_emp'
        verbose_name = '员工表'

    def __str__(self):
        return f'当前员工是:{self.name},当前职位是:{self.job}'

class Deptmodel(Basemodel):
    name = models.CharField(max_length=32, verbose_name='部门名字')
    address = models.CharField(max_length=100, verbose_name='公司地址')

    parent = models.ForeignKey('self', on_delete=models.SET_NULL, null=True, verbose_name='所属部门')

    class Meta:
        db_table = 't_dept'
        verbose_name = '部门表'

    def __str__(self):
        return f'当前的部门是:{self.name}'

一对一 #外键在查询较多的一方
class IDcard(Basemodel):
    number = models.CharField(verbose_name='身份证号', max_length=32)
    start_time = models.DateField(verbose_name='起始时间', null=True, blank=True)
    end_time = models.DateField(verbose_name='结束时间', null=True, blank=True)

    class Meta:
        db_table = 't_IDcard'
        verbose_name = '身份证'

class Employee(Basemodel):
    name = models.CharField(verbose_name='员工姓名', max_length=20, unique=True)
    job = models.CharField(verbose_name='员工职位', max_length=2, choices=Jobchoices.choices, default=Jobchoices.CE)
    entry_date = models.DateField(verbose_name='入职日期', default=date.today())
    sal = models.IntegerField(verbose_name='薪资级别')
    bonus = models.IntegerField(verbose_name='津贴', default=0)
    is_leave = models.BooleanField(verbose_name='是否离职', default=False)
    # 允许为空,且为空字符
    idcard = models.OneToOneField('IDcard', on_delete=models.CASCADE, null=True, blank=True)

多对多 #总的来说还是一对多或者多对一的情况
class Role(Basemodel):
    name = models.CharField(verbose_name='权限的名称', unique=True, max_length=20)

    class Meta:
        db_table = 't_role'
        verbose_name = '权限表'

class Deptmodel(Basemodel):
    name = models.CharField(max_length=32, verbose_name='部门名字')
    address = models.CharField(max_length=100, verbose_name='公司地址')

    parent = models.ForeignKey('self', on_delete=models.SET_NULL, null=True, verbose_name='所属部门')

    class Meta:
        db_table = 't_dept'
        verbose_name = '部门表'

class Employee(Basemodel):
    name = models.CharField(verbose_name='员工姓名', max_length=20, unique=True)
    job = models.CharField(verbose_name='员工职位', max_length=2, choices=Jobchoices.choices, default=Jobchoices.CE)
    entry_date = models.DateField(verbose_name='入职日期', default=date.today())
    sal = models.IntegerField(verbose_name='薪资级别')
    bonus = models.IntegerField(verbose_name='津贴', default=0)
    is_leave = models.BooleanField(verbose_name='是否离职', default=False)
    # 允许为空,且为空字符
    dept = models.ForeignKey('Deptmodel',
                             verbose_name='员工所属的部门',
                             on_delete=models.SET_NULL,
                             null=True,
                             blank=True)
    idcard = models.OneToOneField('IDcard', on_delete=models.CASCADE, null=True, blank=True)

    roles = models.ManyToManyField('Role', verbose_name='权限', related_name='t_emp_role', db_table='t_emp_role',
                                   null=True, blank=True)

# r1 = Role.objects.create(name='销售人员')
    # r2 = Role.objects.create(name='出库人员')
    # r1 = Role.objects.create(name='财务人员')

    emp = Employee.objects.get(pk=8)
    emp1 = Employee.objects.get(pk=7)
    r1 = Role.objects.get(pk=1)
    r2 = Role.objects.get(pk=2)
    r3 = Role.objects.get(pk=3)

    # 正向查询按字段
    # emp.roles.add(r1, r2, r3)  # 给员工为1增加权限销售人员,一个员工拥有多个权限
    # emp.save()
    r1.t_emp_role.add(emp, emp1)  # 多个员工拥有一个权限
    r1.save()
posted @   家购诗  阅读(3)  评论(0编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
点击右上角即可分享
微信分享提示