当前位置: 首页 > 工具软件 > cost-model > 使用案例 >

Model 模型

孔俊捷
2023-12-01

Model 模型

一、配置数据库

settings.py文件中 默认为sqlite数据库 更改成mysql数据库

实例:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'helloworld',
        'HOST':'127.0.0.1',
        'PORT':3306,
        'PASSWORD':'123456',
        'USER':'root',
    }
}

project的init.py文件中宏 添加代码如下

import pymysql
pymysql.install_as_MySQLdb()

二、ORM

随着项目越来越大 采用原生SQl的方式 在代码中就会出现大量的SQL语句 那么就会出现如下问题:

  1. SQL语句重复利用率不高 越复杂的SQL语句条件就会越多 代码越长 会出现很多相近的SQL语句
  2. 很多SQL语句都是在业务逻辑中拼接出来的 如果有数据库需要更改 就要去修改这些逻辑 这会很容易漏掉对某些SQL语句的修改
  3. 写原生SQL语句时 胡忽略WEB安全问题 给未来造成隐患

什么是ORM?

orm中文叫做关系映射 通过ORM我们可以通过类的方式去操作数据库 而不用再去写原生的SQL语句 通过把表映射成类 把行作为实例 把字段作为属性 ORM在执行对象操作数据库的时候 最终还是会转换为操作数据库的原生SQL语句

使用ORM优点:

  1. 易用性 使用ORM做数据库的开发 可以有效的减少重复sQL语句的概率 写出来的模型也更加的直观 清晰
  2. 性能损耗小 ORM转换成底层数据库操作指令 确实会有一些开销 但从时机情况来看 这种性能损耗很小 只要不是对性能有严苛的要求 综合考虑开发效率 代码的阅读性 带来的好处要远远大于性能损耗 而且项目越大 作用就越明显
  3. 设计灵活 可以轻松的写出复杂的SQL语句
  4. 可移植性 封装了底层数据库的实现 支持多个关系数据库引擎 包括流行的sqlite MySQL等数据库 轻松切换数据库 来去自如

三、模型的字段和可选条件

(1) 字段类型

字段名称字段说明参数
AutoField一个根据实际ID自动增长的IntegerField 通常不指定(自动生成)
CharFieldvarchar类型字段max_length 存储值的最大长度
TextFieldlongtext类型长文本
IntegerFieldint类型字段 存储整形
DecimalField存储浮点型 更加精准(存储)max_digits=None 位数长度 decimal_places=None 小数的位数
FloatField存储浮点类型
BooleanField存储Bool值 True/False
NullBooleanField存储null/True/False
DateFielddate子段auto_now=False 如果对数据进行修改 则会自动保存修改的时间 auto_now_add=False 会自动保存第一次保存数据的时间 俩个参数不能同时使用
TimeFieldtime字段参数同上
DateTimeFielddatetime字段参数同上

(2) 字段选项

可选参数参数说明
null如果设置为True 则当前字段值可以为null
blank如果设置为True 则当前字段可以为空(什么值都没有)
db_column设置字段名称 不设置 字段默认名称为属性名
db_index常规索引
unique唯一索引
primary_key主键索引
default默认值

四、定义模型

(1) 模型 数学 表之间的关联

一个模型类 对应数据库中的一张表 一个类数学对应表中的一个字段

(2) 创建我们测试的模型类

models.py

from django.db import models


# Create your models here.
class Test(models.Model):
    char = models.CharField(max_length=20,default='默认值',db_index=True)
    text = models.TextField(null=True,blank=True)
    inter = models.IntegerField(db_column='inte')
    deci = models.DecimalField(max_digits=5,decimal_places=2)
    float = models.FloatField()
    bool = models.BooleanField()
    null = models.NullBooleanField()
    date = models.DateField(auto_now=True)
    time = models.TimeField(auto_now=True)
    datetime = models.DateTimeField(auto_now_add=True)
    def __str__(self):
        return self.char

注意:

blank=True 只能用在字符串的字段类型上 不能用在数值上

(3) 执行迁移 到我们的数据库中

python3 manage.py makemigrations

python3 manage.py migrate

注意:

  1. 如果在执行创建迁移文件的时候 提示没有模型改变 那么就将新建的模型在别的视图函数文件中执行导入 那么出现这个问题的原因(当前django没有检测到你所写的模型类)
  2. 默认的模型名称为 应用名_类名 App_test

数据库中表结构

mysql> desc test;
+----------+--------------+------+-----+---------+----------------+
| Field    | Type         | Null | Key | Default | Extra          |
+----------+--------------+------+-----+---------+----------------+
| id       | int(11)      | NO   | PRI | NULL    | auto_increment |
| char     | varchar(20)  | NO   | MUL | NULL    |                |
| text     | longtext     | YES  |     | NULL    |                |
| inte     | int(11)      | NO   |     | NULL    |                |
| deci     | decimal(5,2) | NO   |     | NULL    |                |
| float    | double       | NO   |     | NULL    |                |
| bool     | tinyint(1)   | NO   |     | NULL    |                |
| null     | tinyint(1)   | YES  |     | NULL    |                |
| date     | date         | NO   |     | NULL    |                |
| time     | time(6)      | NO   |     | NULL    |                |
| datetime | datetime(6)  | NO   |     | NULL    |                |
+----------+--------------+------+-----+---------+----------------+

(4) 元选项

在模型类中定义一个Meta类

class Test(models.Model):
	...
    class Meta:
        db_table = 'test'  # 修改表名为test 默认名称为App_test
        ordering = ['id']  # 查询出来的数据 按照id升序
        ordering = ['-id'] # 查询出来的数据 按照id降序

当对模型进行了修改 则需要再次进行上一步3的操作

五、测试数据库

(1) 进入到Pythonshell进行测试

python3 manage.py shell

(2) 添加数据

from django.shortcuts import render,HttpResponse
from App.models import Test  # 导入Test模型类

# 添加数据
def insert(req):
    # 第一种添加数据的方式
    """
    t = Test()
    t.char = 'char'
    t.text = 'text'
    t.inter = 1
    t.deci = 1.234
    t.float = 1.11
    t.bool = True
    t.null = None
    t.save()
    """
    # 第二种在实例化的时候传递关键词参数
    t = Test(char='char',text='text',inter=1,deci=1.222,float=1.1,bool=False,null=True)
    t.save()
    return HttpResponse('添加数据')

(3) 查询数据

# 查询数据
def select(req):
    # 查询主键为1的数据 pk也就是primary_key的缩写
    t = Test.objects.get(pk=1)
    # print(t)
    # 根据属性获取出想要的数据
    print(t.char)
    print(t.deci)
    print(t.float)
    return HttpResponse('查询')

(4) 修改

# 数据的修改
def update(req):
    # 修改主键为1的数据
    t = Test.objects.get(pk=1)
    t.char = 'lucky'
    t.save()
    return HttpResponse('数据的修改')

(5) 删除

# 数据的删除
def delete(req):
    # 删除id为2 的数据
    t = Test.objects.get(pk=2)
    t.delete()
    return HttpResponse('删除')

六、模型成员

类属性

(1) objects

是Manager类的一个对象 作用是与数据库进行交互

当定义模型的时候 没有指定模型管理器 则Django会默认为当前模型类创建一个名为objects的管理器

(2) 自定义模型管理器名称

class Test(models.Model):
	# 自定义模型管理器名称
	testobj = models.Manager()

注意:

当自定义模型管理器的名称为testobj的时候 则默认的objects模型管理器不存在了

视图函数中使用

# 查询数据
def select(req):
    # 查询主键为1的数据 pk也就是primary_key的缩写
    t = Test.testobj.get(pk=1)
    # print(t)
    # 根据属性获取出想要的数据
    print(t.char)
    print(t.deci)
    print(t.float)
    return HttpResponse('查询')

(3) 自定义 模型管理器功能Manage类

概述:

模型管理器是django模型与数据库进行交互的接口 一个模型可以有多个模型管理器

作用:

  1. 向管理器类中添加额外的方法
  2. 修改管理器返回的原始查询集
  3. 重写get_query_set 方法

实例

模型类中

from django.db import models


class UserManager(models.Manager):
    def get_queryset(self):
        return super().get_queryset().filter(sex=True)


# Create your models here.
class User(models.Model):
    username = models.CharField(max_length=20,db_index=True,default='lucky')
    sex = models.BooleanField(default=True)
    age = models.IntegerField(default=18)
    info = models.CharField(max_length=20,default='我是帅气的lucky老师')
    createtime = models.DateTimeField(auto_now_add=True)
    userobj = UserManager()  # 添加了过滤查询集的方法
    objects = models.Manager()
    def __str__(self):
        return self.username
    class Meta:
        db_table = 'user'

视图函数中使用

# 查询
def showData(req):
    # all 查询所有
    # u = User.objects.all()
    u = User.userobj.all()
    return render(req,'show_data.html',{'data':u})

(4) 创建对象

目的:
向数据库中添加数据

注意:

不能够在自定义的模型中 使用init构造方法 原因是已经在父类中models.Model中使用了

实例:

models.py

class User(models.Model):
   ...

    @classmethod
    def addUser(cls,username='lucky',sex=True,age=18,info='我是帅气的lucky老师'):
        obj = cls(username=username,sex=sex,age=age,info=info)
        return obj

视图函数中使用

# 测试使用类方法添加数据  如果全部都给值 会更加方便
def my_add(req):
    u = User.addUser('lucky',False,18)
    u.save()
    return HttpResponse('自定义类方法进行数据的添加')

七、模型查询

概述:

  1. 查询集表示从数据库拿到的对象的集合
  2. 查询机可以有多个过滤器
  3. 过滤器是一个函数 根据所给的参数 限制返回的查询集
  4. 从sql角度来说 查询集合和select语句等价 过滤器就是sql语句的where条件

(1) 操作原生SQL语句

# 原生查询
# 注意Linux下严格区分大小写
u = User.objects.raw('select * from user')
# 支持索引和切片操作
u = User.objects.raw('select * from user')[0:5]
u = User.objects.raw('select * from user')[0]
u = User.objects.raw('select * from user limit 5')

(2) all() 返回查询集中的所有数据

类名.objects.all()

切片操作 可以节约内存

实例

u = User.objects.all()
u = User.objects.all()[:5]

实现分页案例

# 实现分页
try:
    page = int(req.GET.get('page',1))
except:
    page = 1
u = User.objects.all()[(page-1)*3:page*3]

(3) filter() 将符合条件的数据进行返回

类名.objects.filter(属性名=值…)

如果参数为多个 那么为and操作

实例:

u = User.objects.filter(sex=True)
# 查询性别为True 并且名字包含力的数据
u = User.objects.filter(sex=True,username__contains='力')
# 等同于上面的写法
u = User.objects.filter(sex=True).filter(username__contains='力')

(4) exclude() 过滤掉符合条件的数据

类名.objects.exclude(属性名=值)

实例

# 查询性别不为True的数据
u = User.objects.exclude(sex=True)
# 查询性别不为True 并且名字不包含力的数据
u = User.objects.exclude(sex=True, username__contains='力')
# 等同于上面的写法
u = User.objects.exclude(sex=True).exclude(username__contains='力')

(5)order_by() 排序

  1. 升序

    order_by(‘id’)

  2. 降序

    order_by(’-id’)

实例:

# 按照年龄升序查询
u = User.objects.order_by('age')
# 按照年龄降序查询
u = User.objects.order_by('-age')
# 可以使用filter或exclude 对数据进行筛选过滤后再次排序
u = User.objects.filter().order_by('-age')
return render(req,'show_data.html',{'data':u})

(6) reverse() 反转

对order_by的反转

实例:

# 按照年龄降序查询
u = User.objects.order_by('age').reverse()
# 按照年龄升序查询
u = User.objects.order_by('-age').reverse()

(7) values() 返回一个列表 每条数据是一个字典

类名.objects.values()

实例:

u = User.objects.values()
# 只返回字段为id username age的值
u = User.objects.values('id','username','age')

结果:

  1. <QuerySet [{‘username’: ‘张力’, ‘info’: ‘我是张力的简介’, ‘id’: 1, ‘age’: 44, 'createtime…},{…}]
  2. <QuerySet [{‘age’: 44, ‘username’: ‘张力’, ‘id’: 1}, {‘age’: 72, '…

(8) values_list() 得到一个元祖格式的数据 只有值

类名.objects.values_list()

实例:

u = User.objects.values_list()

结果:

<QuerySet [(1, ‘张力’, True, 44, ‘我是张力的简介’, …

返回一条数据(一个对象)

 类似资料: