模型model

django的ORM系统

ORM概念:对象关系映射(Object Relational Mapping,简称ORM)
ORM的优势:不用直接编写SQL代码,只需像操作对象一样从数据库操作数据。

  • 模型类必须都写在app下的models.py文件中
  • 模型如果需要映射到数据库,所在的app必须被安装
  • 一个数据表对应一个模型类,表中的字段,对应模型中的类属性

 配置数据库

1.在settingss.py里面配置DATABASSES

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',  # 数据库引擎
        'NAME': 'mydb',  #数据库名称
        'USER': 'admin',    # 链接数据库的用户名
        'PASSWORD': 'Root110qwe',   # 链接数据库的密码
        'HOST': '127.0.0.1',  # mysql服务器的域名和ip地址
        'PORT': '3306',  # mysql的一个端口号,默认是3306
    }
}

2.设置连接器

需要安装pymysql,安装方法不再赘述

在主目录下创建 __init__.py 文件,写入如下两行代码

import pymysql
pymysql.install_as_MySQLdb()  #将pymysql作为连接器

 

一、模型数据表的创建

 1.在对应的APP目录的 models.py定义模型类,即建表

#创建一个数据表
class Demo(models.Model):
    id = models.AutoField(primary_key=True)  #设置为主键
    name = models.CharField(max_length=30)  #添加一个name的字段
    age = models.IntegerField()  #添加一个age的字段

2.映射数据库

法一

找到 Tools 下面的 Run manage.py Task 

生成文件映射 makemigrations ,后跟APP名,如果不指定,则全部添加;

将映射提交到数据库 migrate 

法二

在SSH里执行命令 python manage.py makemigration 和 python manage.py migrate  

3.检查

 

可以看到,里面成功创建了 db_test_demo ( 数据库表名 = APP名_模型类名 )的数据表,其他的是django自带

看一下设计结构

 

二、数据的常规操作

以下数据的操作是使用视图函数,通过访问url来调用函数,视图函数和路由配置不再赘述,只展示视图函数的函数体部分

1.插入

 法一

Chancey = Demo(name='Chancey',age=18)
Chancey.save()

法二

Chancey = Demo()
Chancey.name = 'Chancey'
Chancey.age = 18
Chancey.save()

 

法三

Demo.objects.create(name='Chancey',age=18)

法四

Demo.objects.get_or_create(name='Chancey',age=18)

这时,在访问URL的时候报错

大致意思是,什么什么三个了,回到数据库看一下

发现也没有成功插入数据

这是因为该方法不会重复添加相同的数据,这里随便改一下

Demo.objects.get_or_create(name='Make',age=20)

成功添加

 

2.查询

查询之前需要添加一个 __str__ 的魔术方法,以格式化输出

def __str__(self):
    return 'Demo<id=%s,name=%s,age=%s>'%(self.id,self.name,self.age)

法一(get)

rs = Demo.objects.get(name='Make')
print(rs)

这里返回的是一个实例对象,且get方法查找只能查找条件唯一的数据

法二(filter)

rs = Demo.objects.filter(name='Chancey')
print(rs)

控制台可以看到 <QuerySet [<Demo: Demo<id=1,name=Chancey,age=18>>, <Demo: Demo<id=2,name=Chancey,age=18>>, <Demo: Demo<id=3,name=Chancey,age=18>>]> ,这是一个类似于集合的Query_Set对象,该对象可迭代、可被构造、可过滤、可切片、可被作为参数传递。

法三(all)

rs = Demo.objects.all()
print(rs)

查询所有,不再赘述

 

3.更改

法一

rs = Demo.objects.get(name='Make') #获取类的属性
rs.name = 'Mary'  #修改类的属性
rs.save()  #记得保存

 

法二

Demo.objects.filter(name='Mary').update(name='Make')   #最容易理解

法三

添加新的字段可以在定义模型类里面添加,这会改变表的结构

添加之后重新生成映射文件并且提交到数据库

 

4.删除

Demo.objects.filter(name='Chancey').delete()

 

三、常用的查询

常用的查询方法

  1. 获取所有记录 rs = Demo.objects.all() 
  2. 获取第一条数据 rs = Demo.objects.first() last亦然,即最后一条数据
  3. 指定条件 rs = Demo.objects.filter(name='Make',age=20) 
  4. 指定条件 rs = Demo.objects.get(name='Chancey') 和filter的区别就是get指定的条件只能是唯一的
  5. 排除条件  rs = Demo.objects.exclude(name='Chancey') 
  6. 排序 rs = Demo.objects.order_by('age') #按照指定条件进行排序,反向前加'-'即可 
  7. 将返回的对象转换成字典 rs = Demo.objects.all().values() 既然Sery_Set对象可跌,转换成字典意义不大
  8. 获取当前查询的总数量 rs = Demo.objects.count() 

常用的查询条件

内容非常简单,不再详述其用法 

 

四、常用字段及参数

常用的字段类型对应到mysql的关系

 

1. IntegerField : 整型,映射到数据库中的int类型。

2. CharField: 字符类型,映射到数据库中的varchar类型,通过max_length指定最大长度。

3. TextField: 文本类型,映射到数据库中的text类型。

4. BooleanField: 布尔类型,映射到数据库中的tinyint类型,在使用的时候,传递True/False进去。如果要可以为空,则用NullBooleanField。

5. DateField: 日期类型,没有时间。映射到数据库中是date类型, 在使用的时候,可以设置DateField.auto_now每次保存对象时,自动设置该字段为当前时间。设置DateField.auto_now_add当对象第一次被创建时自动设置当前时间。

6. DateTimeField: 日期时间类型。映射到数据库中的是datetime类型, 在使用的时候,传递datetime.datetime()进去。

 

常用的参数

primary_key: 指定是否为主键。

unique: 指定是否唯一。

null: 指定是否为空,默认为False。

blank: 等于True时form表单验证时可以为空,默认为False。

default: 设置默认值。

DateField.auto_now: 每次修改都会将当前时间更新进去,只有调用,QuerySet.update方法将不会调用。这个参数只是Date和DateTime以及TimModel.save()方法才会调用e类才有的。

DateField.auto_now_add: 第一次添加进去,都会将当前时间设置进去。以后修改,不会修改这个值

 

五、表关系

Django里面已经封装好了诸多方法,只需要调用即可

举个例子,现在需要实现如下表关系,对于mysql层面上的表关系不太理解的可以去数据库栏目里

可以点击下载附件

分析以上表关系,可以总结出

现在映射到模型

建表

实现一对多(即学院信息表和学生信息表)

#创建学院信息表
class Department(models.Model):
    d_id = models.AutoField(primary_key=True)
    d_name = models.CharField(max_length=30)

    def __str__(self):
        return 'Department<d_id=%s,d_name=%s>'%(self.d_id,self.d_name)

#创建学生信息表
class Student(models.Model):
    s_id = models.AutoField(primary_key=True)
    s_name = models.CharField(max_length=30)
    department = models.ForeignKey('Department',on_delete=models.CASCADE)  #这里的on_delete是级联删除
    
    def __str__(self):
        return 'Student<s_id=%s,s_name=%s>'%(self.s_id,self.s_name)

之后还是原来的套路,即 makemigrations 和 migrate 

可以看到,直接用 models.ForeignKey 即可完成外键关联

再来数据库里面看看

 

查看下表结构

 实现一对一(创建学生详情表,和学生信息表一对一)

class Student_detail(models.Model):
    student = models.OneToOneField('Student',on_delete=models.CASCADE)  #一对一的关系,主从不影响
    gender = models.BooleanField(default=True)
    height = models.IntegerField()
    wight = models.IntegerField()

查看表结构

实现多对多(创建课程表,和学生信息表多对多)

class Course(models.Model):
    c_id = models.AutoField(primary_key=True)
    c_name = models.CharField(max_length=30)
    student = models.ManyToManyField('Student')

查看数据库

不难发现,这里多出来了 db_test_course 和 db_test_course_student 

这里不用自行创建中间信息表,Django会自动创建中间信息表

看下两张表的结构

 

六、表关联对象的访问

 一对多关系

先给 department 表插入数据(只写函数体部分,这种方法是通过视图函数来使用,所以必须分配路由并返回response对象)

 

    Department.objects.create(d_name='信息工程')
    Department.objects.create(d_name='经济管理')
    Department.objects.create(d_name='纺织服装')
    Department.objects.create(d_name='艺术传媒')
    Department.objects.create(d_name='商务外语')

 

查询

d1 = Department.objects.get(d_id=1)
s1 = Student.objects.get(s_id=1)
print(s1.department.d_name)  #正向查询,查该生的所属学院
print(d1.student_set.all())   #反向查询,用_set做管理器,查这个学院的学

可以在定义时设置related_name 参数来覆盖foo_set 的名称

  • 1.d1.student的管理器有add的方法.
  • 2.例子中的s2能添加成功是因为设置了student表中department字段允许为空了

一对一关系

    std = Student_detail.objects.get(id=2)
    print(std.student.s_name)  #正向查询,查这个学生的名字
    print(s1.student_detail.age)  #反向查询,查年龄

注意对于所有类型的关联字段,add()、create()、remove()和clear()都会马上更新数据库。换句话说,在关联的任何一端,都不需要再调用save()方法

 

八、多表查询

    print(Student.objects.filter(department_id=2))  #查询学院的所有学生
    print(Student.objects.filter(course__c_id=1))  #查询选该课程的所有学生
    print(Department.objects.filter(student__s_name__contains=''))  #查询名字里包含‘何字’的学生的学院
    print(Course.objects.filter(student__s_id=1.all()))  #查询学号为1的学生所选的课程
    print(Student.objects.filter(course__c_id=1).all())  #查询课程1报名的同学
    print(Department.objects.filter(student__course__c_id=1))  #查询报名了某课程的学生的学院

Django 提供一种强大而又直观的方式来“处理”查询中的关联关系,它在后台自动处理JOIN。 若要跨越关联关系,只需使用关联的模型字段的名称,并使用双下划线分隔,直至你想要的字段

posted @ 2019-01-10 15:51  ChanceySolo  阅读(490)  评论(0编辑  收藏  举报