python全栈开发第十六天(Django ORM对象关系映射 )

第十六天

    • Django数据库开发思维与ORM
      • 1. 配置数据库
      • 2. 安装pymysql
      • 3. 创建库
      • 4.编写第一个模型
      • 5.数据迁移 数据表结构同步
    • ORM 操作
      • 单表操作
      • 关系搭建之 一对多
      • 多对多
      • 聚合函数 Avg Sum Max Min Count
      • F对象 Q对象

Django数据库开发思维与ORM

Django鼓励开发人员进行相对独立的模块开发,这种开发模式在工作中被称为:解耦合,就是指在开发中将项目看成几个独立的模块进行开发,降低模块之间的耦合性。在这种思路下,django数据开发采用了mvc和mvt设计模式,和ORM机制

ORM对象关系映射
python全栈开发第十六天(Django ORM对象关系映射 )_第1张图片
作用:

  1. 将数据库中的表名映射为类名,将字段映射为属性,可以操作类方法,类属性快速操作数据库
  2. 可以使用我们创建好的模型,帮我们创建表
  3. 无需关心具体使用的是那种数据库

1. 配置数据库

更改数据库为mysql
在settings中

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',##引擎
        'NAME': 'stu',    ## 库名
        'USER': 'root',   ## 用户名
        'PASSWORD': '123123',
        'HOST': '127.0.0.1',
        'PORT': '3306',
    }
}

2. 安装pymysql

pip install pymysql

3. 创建库

create database stu charset=utf8;

4.编写第一个模型

python全栈开发第十六天(Django ORM对象关系映射 )_第2张图片
数据类型

CharField 字符串类型
IntegerField 整形
DecimalField  浮点型  其中5代表五位数,2代表两位小数
DateField 日期
EmailField 邮箱
TextField  文本类型
BooleanField 布尔类型 

django ORM会帮助我们自动创建一个主键

5.数据迁移 数据表结构同步

1. 在数据迁移之前,确定配置是否完成
python manage.py check

2.排错
第一个错误
python全栈开发第十六天(Django ORM对象关系映射 )_第3张图片
原因:django 模式使用python2 版本的mysql数据库模块,python3 使用的是pymsql模块

解决方法:
python全栈开发第十六天(Django ORM对象关系映射 )_第4张图片

第二个错误

python全栈开发第十六天(Django ORM对象关系映射 )_第5张图片
原因:django默认检测pymysql的版本,修改源码,去掉检测

解决办法:
python全栈开发第十六天(Django ORM对象关系映射 )_第6张图片
3.数据迁移
python manage.py makemigrations
python全栈开发第十六天(Django ORM对象关系映射 )_第7张图片
原因: python3当中 字符串没有 decode

解决方案:
python全栈开发第十六天(Django ORM对象关系映射 )_第8张图片
执行成功
python全栈开发第十六天(Django ORM对象关系映射 )_第9张图片
同步表结构
python全栈开发第十六天(Django ORM对象关系映射 )_第10张图片
数据库中

python全栈开发第十六天(Django ORM对象关系映射 )_第11张图片
app01-person表是根据我们写的类模型创建的表,默认名字是 子应用名字-模型名字

数据迁移

python manage.py makemigrations app的名字    生成一个迁移文件
python manage.py migrate  app的名字 名字可写可不写         使用迁移文件,进行表同步

创建表的时候修改默认名字
python全栈开发第十六天(Django ORM对象关系映射 )_第12张图片
python全栈开发第十六天(Django ORM对象关系映射 )_第13张图片

创建Django管理的用户 python manage.py createsuperuser

站点管理 admin
python全栈开发第十六天(Django ORM对象关系映射 )_第14张图片
安装模型类

python全栈开发第十六天(Django ORM对象关系映射 )_第15张图片
使用后台增加数据
python全栈开发第十六天(Django ORM对象关系映射 )_第16张图片

修改站点管理后台为中文:
python全栈开发第十六天(Django ORM对象关系映射 )_第17张图片
注意:在模型中修改的内容对数据库产生影响后需要重新生成迁移文件和同步表结构,如果是修改模型的内容是关于站点管理后台的内容不涉及数据库则不需要迁移文件和同步表结构。

ORM 操作

字段类型

CharField   varchar类型,需要指定长度
IntegerField     整形
DecimalField     浮点型  需要指定最大长度和小数点位数
DateField      日期   datetime
ForeignKey    做外键
	# to 设置关联表
	# to_field 关联表要关联的键名,默认为关联表中的id,可以不写
	# on_delete 当删除关联表中的数据的时候,从表做什么行为,
		# CASCADE  当关联表中数据删除的时候,外键所在表中的数据也会被删除
		# SET_NULL  当关联表中数据删除的时候,外键所在表中的外键设置为空
		# SET_DEFAULT  当关联表中数据删除的时候,外键所在表中的外键设置一个默认值
		# PROTECT 关联保护,当关联表的数据被删除的时候,报异常,
		# DO_NOTHING  当关联表中数据删除的时候,外键所在的表不做任何事情

字段属性

max_length 最大长度
verbose_name  备注,站点管理中用于显示字段为中文
max_digits   浮点型最大长度
decimal_places  小数点位数
auto_now = True 获取的是当前时间
null = True    可为空,默认是不为空

元数据

class Meta:

	db_table 修改表的名字
	verbose_name  备注,站点管理中用于显示模型名字为中文,会出现s
	verbose_name_plural  显示复数名称
	ordering= ['-age']  指定排序

单表操作

增加

  • save 方法
    python全栈开发第十六天(Django ORM对象关系映射 )_第18张图片
  • create方法
    python全栈开发第十六天(Django ORM对象关系映射 )_第19张图片

查询

1.all()

  • 返回一个 queryset 一个列表
  • 返回符合条件的所有数据
    # all 方法
    date = Person.objects.all()
    # print (date)
    # print (date[0].name)
    # print (date[0].age)
    # print (date[0].height)
    for one in date:
        print (one.height)
        print (one.name)

2 .get方法

  • 返回是一个 对象
  • 返回结果有且只有一条,get后面的条件常用主键
   # get 方法
    data = Person.objects.get(id=1)
    print (data.name)
    print (data.age)

3 .filter 方法(类似于sql中的 where)

  • 返回值: queryset
  • 使用遍历或者下标提取属性的值
    # filter 方法
    data = Person.objects.filter(name="zhangsan")
    print (data)

4 .first方法 和last 方法

  • first 返回一个对象,返回符合条件的第一条数据(对象)

  • last 返回一个对象,返回符合条件的最后一条数据(对象)

    data = Person.objects.filter(name="zhangsan").first()
    print (data.age)

    data = Person.objects.filter(name="zhangsan").last()
    print(data.age)

5 . order_by 排序

    # 升序
    # data = Person.objects.all().order_by("age")
    # 降序
    data = Person.objects.all().order_by("-age")
    for one in data:
        print (one.age)
    data = Person.objects.all().order_by("age","-name")

6 .exclude()

  • 返回一个quertset,查询集,包含了跟给定条件不符合的所有数据

    data = Person.objects.exclude(name="zhangsan")
    for one in data:
        print (one.name)

7 .values ,count ,exists,切片

     values   queryset [duixiang,duixiang,duixiang]
     返回的是一个queryset 内容不是实力对象,而是具体数据的字典
     data = Person.objects.filter(name="zhangsan").values()
     print (data)
     
     count 返回的是符合当前条件的数据的条数
     data = Person.objects.filter(name="zhangsan").count()
     print (data)

     exists 返回一个 True或者Flase  判断是否存在
     data = Person.objects.filter(name="libai").exists()
     print (data)
    
    切片  
    data = Person.objects.order_by("id")[2:5]
    print (data)

8 .双下换线查询

    __lt 小于
    data = Person.objects.filter(id__lt=3)
    print (data)
    
    __gt  大于
    data = Person.objects.filter(id__gt=3)
    print (data)
    
    __gte 大于等于
    data = Person.objects.filter(id__gte=3)
    print (data)
    
    __in 包含  select * from stu where id in (1,2,3,4);
    data = Person.objects.filter(id__in = [1,2,3])
    print (data)
    
    exclude 不包含
    order_info=OrderInfo.objects.filter(order_id=1).exclude(status__in=[0,4]).first()
    
    __range 范围
    data = Person.objects.filter(id__range = [1,5])
    print (data)
    
    __startswith   像 like j%   endswith  像 %j
    data = Person.objects.filter(name__startswith="j")
    print (data)
    __endswith

    __contains 包含  大小写敏感
    data = Person.objects.filter(name__contains="w")
    print (data)
    
    __icontains  包含,大小写不敏感
    data = Person.objects.filter(name__icontains="w")
    print(data)

注意:
Queryset:查询集,不是python列表,也叫结果集,表示从数据库中获取的一个对象集合
使用如下的方法的时候返回:

  • all()
  • filter()
  • order_by()
  • exclude()
  • values 特殊的queryset
  • 切片

特性:

  • 惰性
    • 创建好查询集之后不会立即执行,在使用的时候才会进行数据的查询,
  • 缓存
    • 使用一个查询集,第一次使用进行查询,然后将数据进行缓存,之后再使用该查询集不会再次发起查询,而是将查询到的结果缓存了下来

使用如下方法返回对象

  • get
  • first()
  • last()

修改

    save  注意:拿到的结果是对象还是查询集合
    #  先查询到数据,然后进行重新赋值,然后执行save 进行保存
    data = Person.objects.get(id=2)
    data.name = "python"
    data.save()
    
    data = Person.objects.filter(name="wangwu").all()
    for one in data:
        if one.id == 4:
            one.age=21
        else:
            one.age = 23
        one.save()
      
      
      update
      Person.objects.filter(id=2).update(name="java")

删除

delete方法
Person.objects.filter(id=7).delete()

关系搭建之 一对多

关系表
python全栈开发第十六天(Django ORM对象关系映射 )_第20张图片
模型
python全栈开发第十六天(Django ORM对象关系映射 )_第21张图片
增加

 # 增加出版社
    # Publish.objects.create(name='清华出版社',address = '北京')
    # Publish.objects.create(name='中国出版社',address = '北京朝阳')
    # Publish.objects.create(name='河南出版社',address = '洛阳')

    # 增加书
    # Book.objects.create(name='python入门',publish_id = 1)

    # publish = Publish.objects.get(name='中国出版社')
    # Book.objects.create(name='python入门', publish_id=publish.id)
    # 第二种方法
    # Book.objects.create(name='python核心编程',publish = Publish.objects.get(name='中国出版社'))
    # 第三种方法
    # 正向操作    从外键所在的表到主表叫正向
    book = Book()
    book.name= '笨办法学python'
    book.publish = Publish.objects.get(name='河南出版社')
    book.save()
    # 反向操作  从主表到从表 叫反向
    publish_obj = Publish.objects.get(name="中国出版社")
    publish_obj.book_set.create(name='pythonWeb开发')

查询

 # 查询的第一种方法
    # publish = Publish.objects.get(name="中国出版社")
    # book = Book.objects.filter(publish_id=publish.id).all()
    # for x in book:
    #     print (x.name)

    # 查询第二种方法
    # 正向查询  从外键所在的表到主表叫正向
    # 查询  pythonWeb开发 属于哪一个出版社
    # book = Book.objects.filter(name='pythonWeb开发').first()
    # print (book.name)
    # print (book.publish.name)

    # 查询第三种方法
    # 反向查询 从主表到从表  叫 反向查询     _set
    publish = Publish.objects.get(name='中国出版社')
    book = publish.book_set.all()
    print (book)

修改

1.save
book = Book.objects.get(id=1)
book.publish = Publish.objects.get(name='中国出版社')
book.save()

2.update 
Book.objects.filter(name='java').update(publish = Publish.objects.get(name='清华出版社'))

publish_obj = Publish.objects.get(name='清华出版社')
Book.objects.filter(name='python核心编程').update(publish=publish_obj)

3.set反向
public = Publish.objects.get(name='河南出版社')
book = Book.objects.get(id=4)
book1 = Book.objects.get(id=3)
public.book_set.set([book,book1])   

删除
先删除外键所在的表,在删除关联表

Book.objects.get(id=2).delete()
Publish.objects.get(name='清华出版社').delete()

多对多

关系表
python全栈开发第十六天(Django ORM对象关系映射 )_第22张图片
创建模型

class Person(models.Model):
    # id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32,verbose_name="姓名")
    age = models.IntegerField(verbose_name="年龄")
    height = models.DecimalField(max_digits=5,decimal_places=2,verbose_name="身高",null=True)
    birthday = models.DateField(verbose_name="生日",auto_now=True)

    def __str__(self):
        return str(self.name)

    class Meta:
        db_table = 'person'
        verbose_name = "用户"
        verbose_name_plural = verbose_name
        # ordering= ['-age','id','name']

class Teacher(models.Model):
    name = models.CharField(max_length=32)
    age = models.IntegerField(default=0)
    gender = models.CharField(max_length=8)
    person = models.ManyToManyField(to=Person)
    class Meta:
        db_table = 'teacher'

查看数据库
python全栈开发第十六天(Django ORM对象关系映射 )_第23张图片
增加
增加老师数据
python全栈开发第十六天(Django ORM对象关系映射 )_第24张图片

 # 新学员  秦秦 想学 laozhang 课  create  正向操作
    # teacher_obj = Teacher.objects.filter(name='laozhang').first()
    # teacher_obj.person.create(name="秦秦",age=16,height=192)
    # 老学员张三  想学 laowang 的课  创建关系的操作   正向操作
    # teacher_obj = Teacher.objects.filter(name='laowang').first()
    # person_obj = Person.objects.filter(name="zhangsan").first()
    # teacher_obj.person.add(person_obj)

    ## 反向操作
    teacher_obj = Teacher.objects.filter(name="laoliu").first()
    person_obj = Person.objects.filter(name="秦秦").first()
    person_obj.teacher_set.add(teacher_obj)

查询

def manytomanyget(request):
    ## 正向  反向
    
    ## 正向查询
    #  查到老师信息,寻找这个老师教的所有学生
    # teacher_obj = Teacher.objects.filter(name='laoliu').first()
    # person = teacher_obj.person.all()
    # print (person)
    ## 查到学生的信息,寻找该学生的老师
    ## 反向查询
    person_obj = Person.objects.filter(name='秦秦').first()
    teacher_obj = person_obj.teacher_set.all().values()
    print (teacher_obj)

    return HttpResponse("多对多查询")

更改

def manytomanyupdate(request):
    # 修改老刘交的学生    10 3   改成  老刘只交id为 1 2 3 4 5 学生
    # 正向  从外键所在表 -》 关联表    teacher -》 person
    # 第一种
    # teacher_obj = Teacher.objects.filter(name="laoliu").first()
    # teacher_obj.person.set([1,2,3,4,5])
    # 第二种
    # teacher_obj = Teacher.objects.filter(name="laoliu").first()
    # person1 = Person.objects.filter(name="java").first()
    # person2 = Person.objects.filter(name="秦秦").first()
    # ## set 后面要放一个 列表,列表中可以是id 还可以是 对象
    # teacher_obj.person.set([person1,person2])

    ## 反向修改
    # 第一种
    # person_obj = Person.objects.filter(name='java').first()
    # person_obj.teacher_set.set([2])
    # 第二种   放对象   
    person_obj = Person.objects.filter(name='java').first()
    teacher1 = Teacher.objects.filter(name="laoliu").first()
    teacher2 = Teacher.objects.filter(name="laowang").first()
    person_obj.teacher_set.set([teacher1,teacher2])

删除

 # remove() 解除对象之间的关系
    # 正向操作
    # 秦秦同学 不学老张的课了
    # person_obj = Person.objects.filter(name='秦秦').first()
    # teacher_obj = Teacher.objects.filter(name="laozhang").first()
    # teacher_obj.person.remove(person_obj)

    # 反向操作
    # teacher_obj = Teacher.objects.filter(name="laoliu").first()  ## 查询教师数据
    # person_obj = Person.objects.filter(name='zhangsan').first()  ## 查询学生数据
    # person_obj.teacher_set.remove(teacher_obj)

    # delete() 删除对象数据,以及对象之间的关系
    # laoliu 离职
    # Teacher.objects.filter(name="laoliu").first().delete()

    #  java 同学 退学了
    Person.objects.filter(name="java").first().delete()

聚合函数 Avg Sum Max Min Count

通过aggregate调用聚合函数

aggregate () 是一个queyset的方法,意思是:返回一个包含数据的键值对的字典

键名:聚合值的表示符号,值:聚合函数计算的结果。

def jttest(request):
    data = Person.objects.all().aggregate(Avg("age"))
    print(data)
    data = Person.objects.all().aggregate(avg_age = Avg("age"),sum_age = Sum("age"))
    print (data)

    return HttpResponse("集合查询")
    

F对象 Q对象

F对象: 用于比较同一个模型中的两个字段的值
python全栈开发第十六天(Django ORM对象关系映射 )_第25张图片
Q对象: 用于处理多条件中的逻辑关系 and or not

def Qtest(request):

    ###   and
    data = Book.objects.filter(num=10,salled=100).all()
    print (data)
    # and 关系
    data = Book.objects.filter(Q(num__gt=10)&Q(salled=100)).all()
    print(data)
    ## or
    data =Book.objects.filter(Q(num__gt=10)|Q(salled=100)).all()
    print (data)
    ## not
    data = Book.objects.filter(~Q(num=10)|~Q(salled=100)).all()
    print (data)

    return HttpResponse("Q obj test")

你可能感兴趣的:(python全栈开发)