Python

Django模型层的扩展

2018-11-26  本文已影响0人  义焃

创建一个Django工程及app

PS D:\test> django-admin startproject modelExplore 
PS D:\test> cd modelExplore 
PS D:\test\modelExplore> python manage.py startapp modelExample 
PS D:\test\modelExplore>

添加app 到settings.py文件中的INSTALLED_APPS配置项中

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'modelExample',
]

配置数据库

使用默认的数据库:sqlite3

数据库的配置方法我在 [Django介绍与框架整合,并使用MySQL实现增删改查] 这篇文章中有过介绍。

模型

Django为了对各种数据库提供支持,因此抽象出一种模型的概念,并提供一套统一的调用API。这样你就可以根据业务需求去选择数据库,而不需要面对因数据库的变更而修改代码,极大地减轻了开发人员的工作量。

在学习模型前,我们先了解ORM(Object Relational Mapping:对象关系映射)的概念:

用于实现面向对象编程语言里不同类型系统的数据之间的转换。从效果上说,它其实是创建了一个可在编程语言里使用的“虚拟对象数据库”。简单理解,就是根据对象的类型生成表结构,将对象、列表操作转换为sql语句,将sql语句查询到的结果转换为对象、列表。

模型实现的就是一种对象关系映射,那么模型、属性、表、字段他们又有哪些不为人知的秘密呢?

Django根据属性的类型确定以下信息。

属性命名限制

定义模型

我们在modelExample这个目录下的models.py定义模型,定义模型需要引入django.db中的models,模型类要继承models.Model类,一个模型就是一个类。定义属性时,需要字段类型,字段类型被定义在django.db.models.fields目录下,为了方便使用,我们将整个django.db.models导入,我们以创建一个简单的用户表为例:

from django.db import models 


# Create your models here. 

class User(models.Model): 
    acocunt = models.CharField(max_length=20) 
    name = models.CharField(max_length=20) 
    passwd = models.CharField(max_length=16) 
    email = models.CharField(max_length=50) 
    sex = models.BooleanField(max_length=1, choices=((0, '男'),(1, '女'),),default=0)

说明:不需要定义主键,在生成表时自动添加。

关系

分类:

用一访问多

用一访问一

访问id

属性类型

Django会为表增加自动增长的主键列,每个模型只能有一个主键列,如果使用选项设置某属性为主键列后,则Django不会再生成默认的主键列。

使用Python的Decimal实例表示的十进制的浮点数 参数说明: DecimalField.max_digits:位数总数 DecimalField.decimal_places:小数点后的数字位数

使用Python的datetime.date实例表示的日期 参数说明: DateField.auto_now:每次保存对象时,自动设置该字段为当前时间,用于“最后一次修改“的时间戳,他总是使用当前日期,默认为False DateField.auto_now_add:当前对象第一次被创建时设置当前时间,用于创建的时间戳,他总是使用当前日期,默认为False 说明: 该字段默认对应的表单控件是一个TextInput。在管理员站点添加了一个JavaScript写的日历控件,和一个Today的快捷按钮,包含了一个额外的invalid_date错误信息键 注意: Auto_now_add,auto_now and default 这些设置是相互排斥的,他们之间的任何组合将会发生错误的结果。

from django.db import models 

class Grades(models.Model): 
    class_name = models.CharField(max_length=20) 
    headteacher = models.CharField(max_length=20) 
    students_count = models.IntegerField(2)

class student(models.Model): 
    student_num = models.CharField(max_length=20)
    student_name = models.CharField(max_length=20) 
    student_sex = models.BooleanField(max_length=1, choices=((0, '男'),(1, '女'),),default=0)
    student_birth = models.DateField(auto_now_add=true)
    student_grade = models.ForeignKey('Grades')

属性选项

  1. 通过属性选项,可以实现对属性的约束
  2. 在属性对象通过关键字参数指定

元选项:在模型类定义中定义Meta类,用于设置元信息

Class Stucent(models.Model):
    # someField
    Class Meta:
        db_table = 'stucents' # 定义数据表名,推荐使用小写字母,如果不写,数据表名默认为项目名小写_类名小写
        ordering=['id']  # 对象的默认排序字段,获取对象的列表时使用。
        # ordering = ['id']:升序;ordering = ['-id']:降序
        # 注意:排序会增加数据库的开销。

生成迁移文件并执行迁移

在以往的开发模式中,我们通常都是设计好数据库表后,将其创建出来,然后通过sql来进行查询,而在Django中,我们可以省去数据库表的设计和创建步骤,我们定义模型其实就是对表的设计,执行迁移就是创建数据库表。修改模型后只需要再迁移即可

第一步:生成迁移文件

在我们的工程目录下执行以下命令:python manage.py makemigrations

PS D:\modelExplore> python manage.py makemigrations 
Database version : 5.5.53 
Migrations for 'firstApp': firstApp\migrations\0001_initial.py 
- Create model User 
PS D:\modelExplore>

如果控制台会打印出类似以上的内容,此时会在modelExample app目录下的migrations目录下生成一个迁移文件,但是现在还没有在数据库中创建表。

第二步:执行迁移

在执行完上一步后,只是生成了一个迁移文件,此时还没有在数据库中创建表,我们需要执行以下命令来生成数据表:python manage.py migrate

PS D:\modelExplore> python manage.py migrate 
Database version : 5.5.53 
Operations to perform: Apply all migrations: admin, auth, contenttypes, firstApp, sessions Running migrations: 
Applying firstApp.0001_initial... OK 
PS D:\modelExplore>

执行以上的命令相当于执行SQL语句创建了数据表。看到类似于上文的结果表示成功,可以去数据库中查看是否已经创建了这张表。表名是你的appName_modelName连接在一起的,当然了,表名也是可以自定义的(在元选项中有过说明)。

模型成员

类属性: objects,他是Manager类型的一个对象,作用是与数据库进行交互。当定义模型类时,没有指定管理器则Django默认为模型创建一个名为objects的管理器。

自定义模型管理器:

class student(models.Model): 

    stuObj = models.Manager() # 自定义模型管理器,此时再去使用objects就会报错了

    student_num = models.CharField(max_length=20)
    student_name = models.CharField(max_length=20) 
    student_sex = models.BooleanField(max_length=1, choices=((0, '男'),(1, '女'),),default=0)
    student_birth = models.DateField(auto_now_add=true)
    student_grade = models.ForeignKey('Grades')

当模型指定模型管理器。Django就不在为模型类生成objects模型管理器了。模型管理器可以创建多个。

自定义管理器Manager类: 模型管理器是Django的模型进行与数据库进行交互的接口,一个模型类可以有多个模型管理器

作用:

实例:

Class StudentsManager(models.Manager): 
    get_queryset(self): 
        return super(StudentsManager,self).getqueryset().filter(isDelete=False)


class student(models.Model): 

    # 为对象创建一个模型管理器
    stuObj = objects_new = StudnetsManager()

    student_num = models.CharField(max_length=20)
    student_name = models.CharField(max_length=20) 
    student_sex = models.BooleanField(max_length=1, choices=((0, '男'),(1, '女'),),default=0)
    student_birth = models.DateField(auto_now_add=true)
    student_grade = models.ForeignKey('Grades')

创建对象:

目的:向数据库中添加数据 当创建对象时,Django不会对数据库进行读写操作,当调用save()方法时才与数据库交互,将对象保存到数据库。

注意:__init__方法已经在基类(父类)中使用,在自定义的模型中无法使用

方法:

此处乱七八糟的呢

@classmethod 
def createStudents(cls,name,age , gender, contend…): 
    student = cls(sname = name , sage = age…) 
    return student 

stu.createStudents(…) 

# 在自定义管理器中添加一个方法 在StudentsManager中创建一个方法 
def createStudents(self,name,age , gender, contend…): 
    # 可以直接创建一个对象,但是这种方式不通用,限制了这个管理器。 
    stu = Students()

# 在通常情况下,我们使用以下的方法创建,这样什么对象调用就是什么对象 
stu2 = self.model() 
stu2.sname = name … Print(type(stu2)) 
student = cls(sname = name , sage = age…) 
return student stu.obj.createStudents
# 定义一个类方法创建对象,此方法要创建在Students类中

模型查询

查询集:

查询集是表示从数据库中获取的对象的集合,查询集可以有多个过滤器,过滤器就是一个函数,基于所给的参数限制查询集结果。从sql角度来说,查询集合select语句等价,过滤器就像where条件。

1在管理器上调用过滤器方法返回结果集
2查询集经过过滤器筛选后返回新的查询集,所以我们可以写成链式调用
3惰性执行:创建查询集不会带来任何数据库的访问,直到调数据时,才会访问数据库
4直接访问数据的情况:
迭代:
序列化:
与if合用:
5返回查询集的方法称为过滤器
all():返回查询集中的所有数据
filter():返回符合条件的数据 :

8查询集的缓存
概述:每个查询集都包含一个缓存,来最小化的对数据库访问
在新建的查询集中,缓存首次为空,第一次对查询集求值,会发生数据缓存。,django会将查询出来的数据做缓存,并返回查询结构,以后的查询直接使用查询缓存的方式查询。
9字段查询
概述:
1实现了SQL中的where语句作为方法filter()、exclude()、get()的参数
2语法:属性名称比较运算符=值
3外键:属性名id
4转义:类似SQL中的like语句中使用%为了匹配占位。
例:filter(sname__contains=”%”)
比较运算符:
1exact判断,大小写敏感,例filter(isDelete=False)
2contailns:是否包含,大小写敏感:例:student.objects.filter(sname__contains=’于’)
3startswith/endswith:以value开头或结尾,大小写敏感
以上四个在前面加上一个I,就表示不区分大小写:iexact/icontains/istartswith
4isnull/isnotnull :是否为空;filter(sname__isnull=False)
5in : 是否包含。filter(pk__in=[2,4,6,8,])
6gt/gte/lt/lte : 大于/大于等于/小于/小于等于;filter(sage__gt=50)
7year/month/day/week_day/hour/minute/second : 日期 filter(last_time__year = 2018)
8跨关联查询:
处理join语句:
语法:模型类名
属性名
_比较运算符
# 描述中带有小白兔关键字的数据属于哪个班级
Grades.objects.filter(Students__scontend__contains=’小白兔’)
9快速查询:pk:代表的主键
聚合函数:使用aggregate()函数返回聚合函数的值
1Avg:
2Count
3Max/Min/Sum
from django.db.model import Max
Students.objects.aggregate(Max(‘sage’))
F对象:可以使用模型的A属性与B属性进行比较
from django.db.model import F
Grades.objects.filter(ggirlnum__gt=F(‘gboynum’) + 20)
支持F对象算数运算和时间运算
Q对象
概述:过滤器的方法中的关键字参数,条件为and方式
需求:进行or查询
解决:使用Q对象
from django.db.model import Q
Students.objects.filter(Q(pk__lt=3) | Q(sage__gt=50))
# 只有一个Q的时候,与没有Q相同
Students.objects.filter(Q(pk__lt=3))
# 在Q前加一个~,表示取反
Students.objects.filter(~Q(pk__lt=3))

上一篇 下一篇

猜你喜欢

热点阅读