ORM操作

ORM简介

  • MVC或者MVC框架中包括一个重要的部分,就是ORM,它实现了数据模型与数据库的解耦,即数据模型的设计不需要依赖于特定的数据库,通过简单的配置就可以轻松更换数据库,这极大的减轻了开发人员的工作量,不需要面对因数据库变更而导致的无效劳动

创建表

在项目下的models.py中创建模型:


class Seat(models.Model):
    name = models.CharField(max_length=10)
    class Meta:
        db_table = "stat"  # 指定表名
        ordering = ['id']  # 设置排序方式
class Grand(models.Model):
    names = models.CharField(max_length=10)
    class Meta:
        db_table = "grand"  # 指定表
        ordering = ['id']  #设置排序方式
        
class Uid(models.Model):
    uid = models.IntegerField()
    # 一对一关系
    stu = models.OneToOneField(to="Student",on_delete=models.CASCADE)
    #完整写法
    stu =models.OneToOneField(to="Student",to_field="id",on_delete=models.CASCADE) 
    # to="sex" 指定表名
    # to_field="id" 指定列名
    # on_delete=models.CASCADE 设置级联删除
    
sex = ((1,),(2,))
class Student(models.Model):
    name = models.CharField(max_length=10)
    sex = models.IntegerField(choices=sex)
    # 页面展示可以使用{{ foo.get_sex_display }}
    sex = models.OneToOneField("Sex", on_delete=models.CASCADE) 
    # 一对多关系
    grand = models.ForeignKey(to="Grand", on_delete=models.CASCADE)     
    # 多对多关系
   	# 多对多关系会生成第三张表
    seat = models.ManyToManyField("Seat")
    
    class Meta:
        db_table = "student"  # 指定表名
        ordering = ['id']  #设置排序方式

表关系:

  1. OneToOneField:一对一关系
  2. ForeignKey:多对一关系(一对多)
  3. ManyToManyField:多对多关系

常见字段

  1. CharField

    字符串字段,必须要有一个参数maxlenght,用于指定该字段最大长度

  2. IntegerField

    保存一个整数

  3. DecimalField

    浮点数,必须提供两个参数,max_digits(总位数)和decimal_place(小数位数),总位数要大于小数位数

  4. AutoField

    类似于IntegerField,在添加记录时会自动增长,如果没有手动指定主键,系统会自动添加一个主键

  5. TextField

    容量很大的文本字段

  6. EmailField

    一个可以检测Email是否合法的CharField

  7. DateField

    日期字段

  8. DateTimeField

    日期时间字段

  9. ImgeField

    文件字段,检验上传对象是否是一个合法图片,当指定heigth_field和width_field时这个图片会按照提供的宽高进行保存

  10. FileField

    文件上传字段

orm字段与数据库实际字段的关系表

orm字段数据库实际字段
AutoFieldinteger AUTO_INCREMENT
BigAutoFieldbigint AUTO_INCREMENT
BinaryFieldlongblob
BooleanFieldbool
CharFieldvarchar(%(max_length)s)
CommaSeparatedIntegerFieldvarchar(%(max_length)s)
DateFielddate
DateTimeFielddatetime
DecimalFieldnumeric(%(max_digits)s, %(decimal_places)s)
DurationFieldbigint
FileFieldvarchar(%(max_length)s)
FilePathFieldvarchar(%(max_length)s)
FloatFielddouble precision
IntegerFieldinteger
BigIntegerFieldbigint
IPAddressFieldchar(15)
GenericIPAddressFieldchar(39)
NullBooleanFieldbool
OneToOneFieldinteger
PositiveIntegerFieldinteger UNSIGNED
PositiveSmallIntegerFieldsmallint UNSIGNED
SlugFieldvarchar(%(max_length)s)
SmallIntegerFieldsmallint
TextFieldlongtext
TimeFieldtime
UUIDFieldchar(32)

参数补充

  1. null

    默认为False,设置为True时,将用Null在数据库中存储空值

  2. blank

    默认为False,设置为True时,该字段允许不填

  3. default

    默认值

  4. primary_key

    设置为True时,就是将这个字段设置为主键。如果未设置主键Django会自动添加一个主键

  5. unique

    设置为True时,表示该字段是唯一的

  6. db_index

    设置为True时,表示为该字段设置数据库索引

  7. 级联删除

    on_delete=models.CASCADE

表记录的增删改查

增加

单表增加

方式一:

from app1 import models
def index(request):
    obj = models.UserInfo(id = 1,name="张三",sex=1,birthday="2000-11-12")
    obj.save() # 翻译成sql语句,然后由pymysql发送到服务端
    return HttpResponse("123")

方式二:

 from app1 import models
def index(request):
    ret = models.UserInfo.object.creat(id = 1,name="张三",sex=1,birthday="2000-11-12")
    print(ret) # 得到一个model对象
    print(ret.name)
    return HttpResponse("123")

批量添加

book_list = []
    for i in range(10):
        bk_obj = models.Book(name='张%s'%i,addr='北京%s'%i)
        book_list.append(bk_obj)
    models.Book.objects.bulk_create(book_list) #批量插入,速度快

多表添加

一对一关系

sea = models.Seat.objects.filter(name="座位2").first() # 查询座位2对应的对象
obj = models.Student.objects.create(
    grade_id=1, # 第一种方式,通过表字段名直接设置值
    seat=sea # 第二种方式,通过模型内变量名赋值一个对象
    ) 

多对多关系

obj = models.Student.objects.get(pk=1)
# 方式一:通过给定值方式添加
obj.teacher.add(*[1,1]) 
obj.teacher.add(1,1)
# 方式二:通过给定对象方式添加
obj.teacher.add(对象1,对象2)
obj.teacher.add(*[对象1,对象2])

删除

单表删除

models.UserInfo.objects.filter(id=1).delete() # 由queryset对象调用delete
models.UserInfo.objects.filter(id=1)[0].delete() # 由model对象调用delete

多表删除

一对一关系

models.Seat.objects.filter(name="座位1").delete()

一对多关系

models.Grade.objects.filter(name="座位2").delete()

多对多关系

# models无法控制多对多关系生成的第三张表,需要通过使用含有关系列的对象进行调用
obj = models.Student.objects.get(id=1) 
obj.teacher.remove(1) # 删除关系表中学生id为1,教师id为1的数据不影响其他表,
obj.teacher.clear() # 清空所有学生id为1的数据
obj.teacher.set([1,2]) # 先清空再加入

修改

单表修改

models.UserInfo.objects.filter(id=1).update(id = 2, name = "李四",sex = "女")
# model对象不能调用update方法通过返回的对象进行修改
ret = models.UserInfo.objects.filter(id=1)[0]
ret.name = "李四"
ret.sex = "女"

多表修改

models.Student.objects.filter(pk=3).update(
    name = "李四",
    grade_id = 2,
    seat_id = 1)
# 修改多对多关系生成第三张表时可以借用多表删除中的set方法

查找

单表查找

models.UserInfo.objects.all()

常见查找方法:

  1. all
    查找全部,结果为queryset类型

    models.UserInfo.objects.all()
    # 结果:
    <QuerySet [<Student: Student object>, <Student: Student object>, <Student: Student object>, <Student: Student]>
    
  2. filter

    条件查询,如果查找不到数据时不会报错,返回一个空的queryset,<QuerySet []>,如果没有查询条件会查询全部数据,queryset类型数据可以继续调用filter

    models.Student.objects.filter(sex=1,name="张1")
    
  3. get

    get可以得到且只能得到一个model对象,当查不到数据时会报错,查询结果多余一个时也会报错

    models.Student.objects.get(name="张三")
    
  4. exclude

    排除匹配的项object和quereyset类型数据都能进行调用

    models.Student.objects.exclude(name="张三")
    models.Student.objects.all().exclude(name="张三")
    
  5. order_by

    排序

    models.Student.objects.all().order_by("id") # 正序
    models.Student.objects.all().order_by("-id") # 倒序
    models.Student.objects.all().order_by("-id","price") # 先按id排序如果id相同再按price排序
    models.Student.objects.all().order_by("id").reverse() # 反转排序结果,需要先排序
    
  6. count

    计数,返回结果的数量

    models.Student.objects.all().count()
    
  7. first

    获取查询结果中的第一条数据,得到一个model对象

    models.Student.objects.all().first()
    
  8. last

    获取查询结果中的最后一条条数据,得到一个model对象

    models.Student.objects.all().last()
    
  9. exists

    判断返回结果有无数据,得到布尔类型

    models.Student.objects.filter(id="999").exists()
    
  10. values

    返回queryset类型,其中数据是字典类型

    models.Student.objects.all().values()
    '''结果
    <QuerySet [{'id': 1, 'name': '张三', 'sex': 1, 'grand': 1, 'seat': 1}, {'id': 2, 'name': '张1', 'sex': 1, 'grand': 1, 'seat': 1}]
    '''
    
  11. values_list

    返回queryset类型,其中数据是数组类型

    models.Student.objects.all().values_list()
    '''结果
    <QuerySet [(1, '张三', 1, 1, 1), (2, '张1', 1, 1, 1)]
    '''
    
  12. distinct

    去重,需要配合values或values_list使用

    models.Student.objects.all().values("sex")
    

filter双下划线查询:

  1. gt

    大于

    models.Student.objects.filter(id__gt=4)
    
  2. gte

    大于等于

    models.Student.objects.filter(id__gte=4)
    
  3. lt

    小于

    models.Student.objects.filter(id__lt=4)
    
  4. lte

    小于等于

    models.Student.objects.filter(id__lte=4)
    
  5. range

    区间,大于第一个值小于第二个值

    models.Student.objects.filter(id__range=[3,6])
    
  6. contains

    模糊查询,匹配所有指定列包含指定值的数据

    models.Student.objects.filter(name__contains="张")
    
  7. icontains

    不区分大小写查找

    models.Student.objects.filter(name__icontains="ab")
    
  8. startswitch

    匹配以什么开头

    models.Student.objects.filter(name__startswith="张")
    
  9. date

    匹配日期

    models.Student.objects.filter(publish_date="2000-01-01")
    

    匹配指定年、月、日

    models.Book.objects.filter(publish_date__year='2019',publish_date__month='8',publish_date__day='1')
    
  10. isnull

    匹配指定字段为空的数据

    models.Book.objects.filter(hoby__isnull=True)
    

跨表查找

obj = models.Student.objects.filter(id=3)[0]
print(obj.seat.name) # 正向查询
obj = models.Seat.objects.filter(name="座位4")[0]
print(obj.student.name) # 逆向查询
obj = models.Grade.objects.filter(id=2)[0]
print(obj.student_set.all()) # 值为多个时使用_set标注

基于双下划线的跨表查询

一对多关系

# 正向查询 按字段:press
obj = models.Book.objects.filter(press__name="黄山书社").values("name")
# 反向查询 按表名:book
obj = models.Press.objects.filter(name="黄山书社").values("book__name")

多对多关系

# 正向查询
obj = models.Book.objects.filter(name="论语").values("writer__name") 
# 逆向查询
obj = models.Writer.objects.filter(book__name="论语").values("name")

一对一关系

# 正向查询
ret=Author.objects.filter(name="王五").values("authordetail__telephone")
# 反向查询
ret=AuthorDetail.objects.filter(author__name="yuan").values("telephone")

聚合查询

from django.db.models import Avg, Sum, Max, Min, Count
obj = models.Book.objects.all().aggregate(a=Max("price"),m=Min("price"))

分组查询

obj = models.Book.objects.values("press_id").annotate(a=Avg("price")) # 通过book表的press_id查询
obj = models.Book.objects.values("press__id").annotate(a=Avg("price")) # 通过press表的id查询
obj = models.Press.objects.annotate(a=Avg("book__price")).values("name","a") # 反向查询

F查询

from django.db.models import F
# 查询评论数大于喜欢数的书
obj = models.Book.objects.filter(comment__gt=F("like"))
for i in obj:
    print(i.name)
# 每本书价格加100
obj = models.Book.objects.all().update(
    price=F("price")+100
)

Q查询

obj = models.Book.objects.filter(Q(like__gt=10)&Q(comment__lt=900)).values("name") # 与
obj = models.Book.objects.filter(Q(like__gt=10)|Q(comment__lt=900)).values("name") # 或
obj = models.Book.objects.filter(~Q(like__gt=10)).values("name") # 非

动态q查询条件

q = Q()
for product_model_id in product_model_ids:
    q.add(Q(product_model_id=product_model_id), Q.OR)
business_visit = models.BusinessDaily.objects.filter(q)

执行原生sql

models.Book.object.raw('select * from Book')

models.Book.objects.select_for_update().filter(id=1)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值