Django基础(7)_ORM单表操作

 

ORM简介                               

 对象关系映射 (Object Relational Mapping, 简称ORM). 

简单的说,ORM是通过使用描述对象和数据库之间映射的元数据,将程序中的对象自动持久化到关系数据库中。

 

 添加表记录 查询表记录 删除表记录 修改表记录

 

  • MVC或者MVC框架中包括一个重要的部分,就是ORM,它实现了数据模型与数据库的解耦,即数据模型的设计不需要依赖于特定的数据库,通过简单的配置就可以轻松更换数据库,这极大的减轻了开发人员的工作量,不需要面对因数据库变更而导致的无效劳动
  • ORM是“对象-关系-映射”的简称。(Object Relational Mapping,简称ORM)(将来会学一个sqlalchemy,是和他很像的,但是django的orm没有独立出来让别人去使用,虽然功能比sqlalchemy更强大,但是别人用不了)
  • 类对象--->sql--->pymysql--->mysql服务端--->磁盘,orm其实就是将类对象的语法翻译成sql语句的一个引擎,明白orm是什么了,剩下的就是怎么使用orm,怎么来写类对象关系语句。

查看orm与原生sql的对应关系

 

 

 

 

 ORM的优点:-不用写繁琐的SQL语句,用咱们熟悉的python代码,就能实现对数据的操作,提高开发效率;-可以平滑的操作,切换数据库。

 ORM的缺点:-ORM代码转换为SQL语句时,需要花费一定的时间,执行效率会有所降低;-长期写ORM代码,导致写SQL语句能力,会有所减弱。

 

Django 使用mysql

  手动创建数据库  

  注意:ORM无法操作到数据库级别,只能操作到数据表。

  

create datebase 数据库名称 charset utf8mb4;

 

   在settings中配置数据库

 1 DATABASES = {
 2     'default': {
 3         'ENGINE': 'django.db.backends.mysql',  # 更改为mysql引擎
 4         'NAME': "day49",                       # 数据库名称
 5         "HOST": "127.0.0.1",                   # 数据库所在ip地址
 6         'PORT': 3306,                          # 默认的端口
 7         'USER': 'root',                        # 用户名
 8         'PASSWORD': "123",                     # 密码
 9     }
10 }

 

   settings.py的同级目录下的__init__.py设置

1 import pymysql 
2 pymysql.install_as_MySQLdb()

  在app下的models.py里写上模型类(单表)

1 class Book(models.Model):
2     # id会自动创建,并且是一个主键
3     title = models.CharField(max_length=32)
4     price = models.DecimalField(max_digits=5, decimal_places=2)  # 最大值,只能是999.99
5     publish = models.CharField(max_length=64)
6     publish_date = models.DateField()

 

 choices参数的介绍

 

sex_choice = (
    (0, '女性'),
    (1, '男性'),
)

class Author(models.Model):
    name = models.CharField( max_length=32)
    age = models.IntegerField()

    sex_choice = (
        (0, '女性'),
        (1, '男性'),
    )

    sex = models.IntegerField(choices=sex_choice,default=1) #choices关键字固定的
    
       获取用户的性别
    ret = models.Author.objects.get(id=1)
    ret.get_sex_display()

 

Django Model中字段(Field)的可选项和必选项

 

字段与选项(必选项为黄色标注)

CharField() 字符字段

 

  • max_length = xxx or None

  • 如不是必填项,可设置blank = True和default = ''

  • 如果用于username, 想使其唯一,可以设置unique = True

  • 如果有choice选项,可以设置 choices = XXX_CHOICES

TextField() 文本字段

  • max_length = xxx

  • 如不是必填项,可设置blank = True和default = ''

DateField() and DateTimeField() 日期与时间字段

  • 一般建议设置默认日期default date.

  • For DateField: default=date.today - 先要from datetime import date

  • For DateTimeField: default=timezone.now - 先要from django.utils import timezone

  • 对于上一次修改日期(last_modified date),可以设置: auto_now=True

EmailField() 邮件字段

 

  • 如不是必填项,可设置blank = True和default = ''

  • 一般Email用于用户名应该是唯一的,建议设置unique = True

IntegerField(), SlugField(), URLField(),BooleanField()

  • 可以设置blank = True or null = True

  • 对于BooleanField一般建议设置defautl = True or False

FileField(upload_to=None, max_length=100) - 文件字段

  • upload_to = "/some folder/"

  • max_length = xxxx

ImageField(upload_to=None, height_field=None, width_field=None, max_length=100,)

  • upload_to = "/some folder/"

  • 其他选项是可选的.

ForeignKey(to, on_delete, **options) - 单对多关系

 

  • to必需指向其他模型,比如 Book or 'self' .

  • 必需指定on_delete options(删除选项): i.e, "on_delete = models.CASCADE" or "on_delete = models.SET_NULL" .

  • 可以设置"default = xxx" or "null = True" .

  • 如果有必要,可以设置 "limit_choices_to = ",如下面例子。

  • staff_member = models.ForeignKey( User, on_delete=models.CASCADE, limit_choices_to={'is_staff': True}, )

  • 可以设置 "related_name = xxx" 便于反向查询。

ManyToManyField(to, **options) - 多对多关系

 

  • to 必需指向其他模型,比如 User or 'self' .

  • 设置 "symmetrical = False " if 多对多关系不是对称的

  • 设置 "through = 'intermediary model' " 如果需要建立中间模型来搜集更多信息

  • 可以设置 "related_name = xxx" 便于反向查询。

  •  

  在命令行执行数据迁移的命令

1 python3 manage.py makemigrations   # 把models.py的变更记录记录下来
2 python3 manage.py migrate          # 把变更记录的操作同步到数据库中

 

关于同步指令的执行简单原理: 

1 在执行 python manager.py magrations 时django 会在相应的 app 的migration文件夹下面生成 一个python脚本文件 
2     在执行 python manager.py migrte 时 django才会生成数据库表,那么django是如何生成数据库表的呢,
3     django是根据 migration下面的脚本文件来生成数据表的
4     每个migration文件夹下面有多个脚本,那么django是如何知道该执行那个文件的呢,django有一张django-migrations表,表中记录了已经执行的脚本,那么表中没有的就是还没执行的脚本,则 执行migrate的时候就只执行表中没有记录的那些脚本。
5     有时在执行 migrate 的时候如果发现没有生成相应的表,可以看看在 django-migrations表中看看 脚本是否已经执行了,
6     可以删除 django-migrations 表中的记录 和 数据库中相应的 表 , 然后重新 执行

 

单表数据的增删改查

添加表记录

  • 方式一: 新增 直接模型类实例化对象
1 def result(request):
2     # 增 方法一
3     book_obj = models.Book(title='三毛流浪记', price=122, publish='小树出版社', publish_date='1999-06-17')
4     book_obj.save()
5     return HttpResponse('ok')
  • 方法二: 调用orm提供的API (推荐)
1 def result(request):
2     # 增 方法二
3     book_obj = models.Book.objects.create(title='红楼梦', price=12, publish='人民出版社', publish_date=datetime.datetime.now())
4     print(book_obj)  # Book object
5     return HttpResponse('ok')

 

  • 批量添加
 1     obj_list = []
 2     for i in range(10):
 3         book_obj = models.Book(
 4             title=f'少年阿宾{i}',
 5             price=10 + i,
 6             pub_date=f'2022-04-1{i}',
 7             publish='32期红浪漫出版社'
 8 
 9         )
10         obj_list.append(book_obj)
11 
12     models.Book.objects.bulk_create(obj_list)  #bulk_create 批量添加

 

 

查询表记录 

  • 查询API 
 1 <1> all():                  查询所有结果,结果是queryset类型
 2   
 3 <2> filter(**kwargs):       它包含了与所给筛选条件相匹配的对象,结果也是queryset类型 Book.objects.filter(title='linux',price=100) #里面的多个条件用逗号分开,并且这几个条件必须都成立,是and的关系,or关系的我们后面再学,直接在这里写是搞不定or的
 4   
 5 <3> get(**kwargs):          返回与所给筛选条件相匹配的对象,不是queryset类型,是行记录对象,返回结果有且只有一个,
 6                             如果符合筛选条件的对象超过一个或者没有都会抛出错误。捕获异常try。  Book.objects.get(id=1)
 7   
 8 <4> exclude(**kwargs):      排除的意思,它包含了与所给筛选条件不匹配的对象,没有不等于的操作昂,用这个exclude,返回值是queryset类型 Book.objects.exclude(id=6),返回id不等于6的所有的对象,或者在queryset基础上调用,Book.objects.all().exclude(id=6)
 9                  
10 <5> order_by(*field):       queryset类型的数据来调用,对查询结果排序,默认是按照id来升序排列的,返回值还是queryset类型
11                   models.Book.objects.all().order_by('price','id') #直接写price,默认是按照price升序排列,按照字段降序排列,就写个负号就行了order_by('-price'),order_by('price','id')是多条件排序,按照price进行升序,price相同的数据,按照id进行升序
12         
13 <6> reverse():              queryset类型的数据来调用,对查询结果反向排序,返回值还是queryset类型
14   
15 <7> count():                queryset类型的数据来调用,返回数据库中匹配查询(QuerySet)的对象数量。
16   
17 <8> first():                queryset类型的数据来调用,返回第一条记录 Book.objects.all()[0] = Book.objects.all().first(),得到的都是model对象,不是queryset
18   
19 <9> last():                queryset类型的数据来调用,返回最后一条记录
20   
21 <10> exists():              queryset类型的数据来调用,如果QuerySet包含数据,就返回True,否则返回False
22                    空的queryset类型数据也有布尔值True和False,但是一般不用它来判断数据库里面是不是有数据,如果有大量的数据,你用它来判断,那么就需要查询出所有的数据,效率太差了,用count或者exits
23                  例:all_books = models.Book.objects.all().exists() #翻译成的sql是SELECT (1) AS `a` FROM `app01_book` LIMIT 1,就是通过limit 1,取一条来看看是不是有数据
24 
25 <11> values(*field):        用的比较多,queryset类型的数据来调用,返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一系列
26                             model的实例化对象,而是一个可迭代的字典序列,只要是返回的queryset类型,就可以继续链式调用queryset类型的其他的查找方法,其他方法也是一样的。
27 <12> values_list(*field):   它与values()非常相似,它返回的是一个元组序列,values返回的是一个字典序列,加个salt=True参数可以获取值列表
28  
29 <13> distinct():            values和values_list得到的queryset类型的数据来调用,从返回结果中剔除重复纪录

 

 

简单使用

 1 def book_list(request):
 2     # all 查询所有    返回QuerySet类型
 3     books = models.Book.objects.all()  # QuerySet类型 类似于list, 里面是一个个对象
 4     # 类似与sql: select * from app01_book;
 5 
 6     # filter 过滤    返回QuerySet类型
 7     books = models.Book.objects.filter(pk=3)  # QuerySet 类似于list, 满足条件的对象集
 8     books = models.Book.objects.filter(price=200)
 9     books = models.Book.objects.filter(publish='少林出版社', price=200)  # 多个条件时,是使用and关系
10 
11     # get 获取一个对象
12     books = models.Book.objects.get(pk=4)  # 直接获取出对象  注意: 当查询条件不存在或者查询出结果有多个值时,会报错。
13     books = models.Book.objects.get(pk=18)  # 直接获取出对象
14     books = models.Book.objects.get(price=200)  # 直接获取出对象
15 
16     # exclude   # 排除满足条件的结果    返回QuerySet类型
17     
18     # first()与last() 获取的是对象
19     books = models.Book.objects.filter(pk=4).first()
20     books = models.Book.objects.filter(pk=4).last()
21 
22     books = models.Book.objects.exclude(publish='少林出版社', price=200)  # not 排除满足条件的对象。剩下的取出来即可。
23 
24     books = models.Book.objects.order_by("price")  # 默认是升序
25     books = models.Book.objects.order_by("-price")  # 默认是降序
26 
27     # reverse
28     books = models.Book.objects.order_by("-price").reverse()  # 默认是降序
29 
30     # count
31     books = models.Book.objects.all().count()  # 统计数量
32 
33     # exists
34     books = models.Book.objects.filter(pk=18).exists()  # 返回值为布尔值
35 
36     # values    # 返回QuerySet类型 里面类似于字典. 
37     books = models.Book.objects.filter(price=200).values("title", "price")  # QuerySet   {'title': '易经', 'price': Decimal('200.00')}
38 
39     # values_list    # 返回QuerySet类型 里面类似于元组
40     books = models.Book.objects.filter(price=200).values_list("title", "price")  # QuerySet   ('易经', Decimal('200.00')),
41 
42     # distinct()  # 去重
43     books = models.Book.objects.filter(price=200).values_list("price").distinct()
44     return HttpResponse("查询成功!")

 

models.py的__str__的写法: 

from django.db import models

# Create your models here.

class Book(models.Model):
    id = models.AutoField(primary_key=True)
    title = models.CharField(max_length=32)
    price = models.DecimalField(max_digits=8,decimal_places=2,)
    pub_date = models.DateTimeField() #必须存这种格式"2012-12-12"
    publish = models.CharField(max_length=32)
    def __str__(self): #后添加这个str方法,也不需要重新执行同步数据库的指令
        return self.title #当我们打印这个类的对象的时候,显示title值

 

  • 基于双下划线的模糊查询  
 1 def book_list(request):
 2     books = models.Book.objects.filter(price__in=[100,200,300])   # 在... 里
 3     books = models.Book.objects.filter(price__gt=100)              # 大于
 4     books = models.Book.objects.filter(price__gte=100)            # 大于等于
 5     books = models.Book.objects.filter(price__lt=100)              # 小于
 6     books = models.Book.objects.filter(price__range=[100, 200])   # 包含后面的数字  左闭右闭
 7     books = models.Book.objects.filter(title__contains="")      # 包含...
 8     books = models.Book.objects.filter(title__icontains="python") # 不区分大小写
 9     books = models.Book.objects.filter(title__startswith="p")       # 以...开头 (区分大小写)
10     books = models.Book.objects.filter(title__iendswith='P')      # 以...结尾 (不区分大小写)
11     books = models.Book.objects.filter(pub_date__year=2018)          # 通过年份过滤
12     return HttpResponse("查询成功!")

 

 

 

删除表记录

  • 方式一 调用 QuerySet的delete方法

  会模仿 SQL 约束 ON DELETE CASCADE 的行为,换句话说,删除一个对象时也会删除与它相关联的外键对象。

1 def del_book(request): 
2     pk =request.GET.get('pk')
3     books = models.Book.object.filter(pk=pk).delete()
4     return HttpResponse('删除成功!')

 

  • 方式二 obj.delete()

  运行时立即删除对象而不返回任何值

1 def del_book(request):
2     pk = request.GET.get("pk")
3     books = models.Book.objects.filter(pk=pk).first()
4     books.delete()
5     return HttpResponse("删除成功!")

 

 

修改表记录

  • 方式一:  调用QuerySet的 update()方法 
1 def edit_book(request):
2     pk = request.GET.get("pk")
3     books = models.Book.objects.filter(pk=pk).update(price=280)
4     books = models.Book.objects.filter(pk=pk).update(price=290,publish='华山出版社')
5     return HttpResponse("编辑成功!")

update()方法对于任何结果集(QuerySet)均有效,这意味着你可以同时更新多条记录update()方法会返回一个整型数值,表示受影响的记录条数

  • 方式二: obj更改属性值, 必须要save() 同步到数据库
1 def edit_book(request):
2     pk = request.GET.get("pk")
3     books = models.Book.objects.filter(pk=pk).first()
4     books.price = 189
5     books.save()
6     return HttpResponse("编辑成功!")

 

posted @ 2020-11-25 10:48  死里学  阅读(92)  评论(0)    收藏  举报