Django ORM 操作
Posted zhang-zi-yi
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Django ORM 操作相关的知识,希望对你有一定的参考价值。
ORM (object Relational Mapping)
对象和关系型数据库的一个映射 同过操作对象的方式操作数据库的内容
- 对应关系
类 > 表
对象 > 记录 数据行
属性 ___> 字段 - ORM的操作:
查询
1. models.Publisher.objects.all() # 查询所有的数据 ——》 QuerySet 对象列表
2. models.Publisher.objects.get() # 获取满足条件的一个对象 ——》 单独的对象
3. models.Publisher.objects.filter() # 获取满足条件的所有对象 ——》对象列表
4. models.Publisher.objects.all().order_by(‘id‘) # 排序 —— 》 对象列表
5. pub_obj.pk ——》 主键
6. pub_obj.name
7. 外键
1. book_obj.publisher ——》 关联的对象
2. book_obj.publisher_id ——》从book表中获取关联对象的ID
3. book_obj.publisher.name ——》 关联的对象的属性
8. 多对多
1. author_obj.books ——》 管理对象
2. author_obj.books.all() ——》 关联的所有的对象 对象列表
3. book_obj.author_set ——》管理对象、增加
1. models.Publisher.objects.create(name=‘xxx‘) ——》 对象
2. 外键
1. models.Book.objects.create(title=‘xxx‘,publisher=pub_obj)
2. models.Book.objects.create(title=‘xxx‘,publisher_id=pub_obj.id)
3. 多对多
1. models.Author.objects.create(name=‘xxxx‘) ——》 author_obj
2. author_obj.books.set([多个要关联对象的id,])
3. author_obj.books.set([多个要关联对象,])删除
1. models.Author.objects.get(id=1).delete()
2. models.Author.objects.filter(id=1).delete()修改
1. 1. pub_obj.name = ‘new_xxxx‘
2. pub_obj.save()
3. 外键
1. book_obj.title = ‘xxxx‘
2. book_obj.publisher = pub_obj 或者 book_obj.publisher_id = pub_obj .id
3. book_obj.save()
4. 多对多
1. author_obj.name = ‘new_name‘
2. author_obj.save()
3. author_obj.books.set([多个要关联对象,]) author_obj.books.set([多个要关联对象的id,])
具体的操作
from app01 import models
# 获取所有数据
models.User.objects.all() # > QuerySet 对象列表
# 获取单个对象 获取不到数据或者拿到多条数据就报错
models.User.objects.get(name=‘alex‘,pwd=‘111‘) # > 对象
# 获取满足条件的所有对象
models.User.objects.filter(name=‘alex‘,pwd=‘111‘) # __> QuerySet 对象列表
字段和字段的参数
1.字段和字段的参数常用的: AutoField # 自增字段 参数: primary_key=True # 主键 IntegerField # 整数类型 参数: blank=True # admin中显示 BooleanField # bool类型 参数: choices((1,‘男‘),(0,‘女‘)) 只能有两个值 0 为存储的值 男女为显示的内容 CharField # varchar 类型 参数: max_length=32 # 必填 最大长度 TextField # 文本类型 DateTimeField # 时间类型 参数: auto_new_add=True # 新增时自动保存当前时间 auto_new=True # 修改时自动保存当前时间 DecimalField # 小数类型 参数: max_digits=5 # 小数总长速度 decimal_places=2 # 小数位长度 ForeignKey(‘表名‘,) # 外键 OneTuoOneField(‘表名‘,) # 等同于外键关联自己 参数: related_name=‘books‘, # 用于反向查询 related_query_name=‘book‘ ManyToManyField(‘表名‘,) # 多对多 参数: related_name=‘books‘, # 用于反向查询 related_query_name=‘book‘ # 用于反向查询 其他参数: db_column=‘usrname‘ # 修改数据库中的列名 显示 verbose_name="用户名" # admin中文提示 black=True # 校验时可以为空 null=True # 存储时可以为空 unique=true # 字段唯一 default=‘默认值‘ # 为空时提供默认值
自定义 Char 类型
class MyCharField(models.Field):
"""
自定义的char类型的字段类
"""def __init__(self, max_length, *args, **kwargs): self.max_length = max_length super(MyCharField, self).__init__(max_length=max_length, *args, **kwargs) def db_type(self, connection): """ 限定生成数据库表的字段类型为char,长度为max_length指定的值 """ return ‘char(%s)‘ % self.max_length 使用: phone = MyCharField(max_length=11, )
class Meta:
# 写在model 类中class Meta: # 数据库中生成的表名称 默认 app名称 + 下划线 + 类名 db_table = "person" # admin中显示的表名称 verbose_name = ‘个人信息‘ # verbose_name加s verbose_name_plural = ‘所有用户信息‘ ordering = (‘id‘,) # # 联合索引 # index_together = [ # ("pub_date", "deadline"), # 应为两个存在的字段 # ] # # # 联合唯一索引 # unique_together = (("driver", "restaurant"),) # 应为两个存在的字段
2.查询的方法(13个)
返回结果是对象列表
all()
filter()
exclude()
order_by()
reverse()
values()
values_list()
distinct()返回结果是对象 get() first() last() 返回布尔值 exists() 返回数字 count()
建立 数据库查询 orm操作
modle 表结构
from django.db import modelsclass MyCharField(models.Field): """ 自定义的char类型的字段类 """ def __init__(self, max_length, *args, **kwargs): self.max_length = max_length super(MyCharField, self).__init__(max_length=max_length, *args, **kwargs) def db_type(self, connection): """ 限定生成数据库表的字段类型为char,长度为max_length指定的值 """ return ‘char(%s)‘ % self.max_length class Person(models.Model): id = models.AutoField(primary_key=True) name = models.CharField(max_length=32, db_column=‘username‘, verbose_name=‘姓名‘) age = models.IntegerField(null=True, blank=True, verbose_name=‘年龄‘) # birth = models.DateTimeField(auto_now_add=True) # 新增的时候保存当前的时间 birth = models.DateTimeField(auto_now=True) # 每次修改的时候保存当前的时间 phone = MyCharField(max_length=11, ) gender = models.BooleanField(choices=((0, ‘男‘), (1, ‘女‘))) def __str__(self): return "<Person object: {}-{}>".format(self.pk, self.name) class Meta: # 数据库中生成的表名称 默认 app名称 + 下划线 + 类名 db_table = "person" # admin中显示的表名称 verbose_name = ‘个人信息‘ # verbose_name加s verbose_name_plural = ‘所有用户信息‘ ordering = (‘id‘,) class Publisher(models.Model): name = models.CharField(max_length=32) def __str__(self): return self.name class Book(models.Model): title = models.CharField(max_length=32) price = models.DecimalField(max_digits=5, decimal_places=2) # 000.00 999.99 sale = models.IntegerField() kucun = models.IntegerField() publisher = models.ForeignKey(‘Publisher‘, related_name=‘books‘, related_query_name=‘book‘, null=True) def __str__(self): return self.title + str(self.pk) class Author(models.Model): name = models.CharField(max_length=32) books = models.ManyToManyField(‘Book‘,)
在setting 中配置 查看配置 显示查询语句
import django
django.setup()from app01 import models # all() 获取所有的数据 对象列表 ret = models.Person.objects.all() # filter() 获取所有满足条件的所有对象 对象列表 ret = models.Person.objects.filter(id=1) # get() 获取一个对象 没有或者是多个的时候报错 ret = models.Person.objects.get(id=1) # exclude 获取不满足条件的所有对象 对象列表 ret = models.Person.objects.exclude(id=1) # values 获取对象的字段名和值 [ {},{} ] # 不指定字段名 获取所有字段的名和值 # 指定字段名 获取指定字段的名和值 ret = models.Person.objects.all().values(‘name‘,‘id‘) # for i in ret: # print(i,type(i)) # values_list 获取对象的值 [ (),() ] # 不指定字段名 获取所有字段的值 # 指定字段名 获取指定字段值 ret = models.Person.objects.all().values_list(‘id‘,‘name‘) # for i in ret: # print(i,type(i)) # order_by 排序 默认升序 加- 降序 指定多个进行排序 ret = models.Person.objects.all().order_by(‘age‘,‘id‘) # reverse() 给已经排好序的结果倒叙排序 ret = models.Person.objects.all().order_by(‘age‘,‘id‘).reverse() ret = models.Person.objects.all().reverse() # distinct() 去重 # count 计数 ret = models.Person.objects.all().count() # first() last 取第一个 最后一个对象 ret = models.Person.objects.filter(id=100).first() # exists() 判断数据是否存在 ret = models.Person.objects.filter(id=1).exists()
3.单表的双下划线
import osos.environ.setdefault("DJANGO_SETTINGS_MODULE", "orm_practice.settings") import django django.setup() from app01 import models ret = models.Person.objects.filter(id=1) ret = models.Person.objects.filter(id__gt=1) # greater than ret = models.Person.objects.filter(id__gte=1) # greater than equal ret = models.Person.objects.filter(id__lt=3) # less than ret = models.Person.objects.filter(id__lte=3) # less than equal ret = models.Person.objects.filter(id__gt=1, id__lt=3) ret = models.Person.objects.filter(id__range=[1, 3]) # 范围 左右都包含 ret = models.Person.objects.filter(id__in=[1, 3]) # ret = models.Person.objects.filter(name__contains=‘alex‘) # 包含 like ret = models.Person.objects.filter(name__icontains=‘alex‘) # 包含 like ret = models.Person.objects.filter(name__startswith=‘a‘) # 以什么开头 ret = models.Person.objects.filter(name__istartswith=‘a‘) # 以什么开头 忽略大小写 ret = models.Person.objects.filter(name__endswith=‘x‘) # 以什么结尾 ret = models.Person.objects.filter(name__iendswith=‘X‘) # 以什么结尾 忽略大小写 ret = models.Person.objects.filter(birth__year=2018) ret = models.Person.objects.filter(birth__contains=‘2018-12‘)
4.外键的操作
# 基于对象的查询
# 正向 有外键的一侧 查关联的对象
book_obj = models.Book.objects.get(id=1)book_obj.publisher 关联的对象 # print(book_obj.publisher) # 关联的对象 # print(book_obj.publisher_id) # 关联的对象的id # print(book_obj.publisher.id) # 关联的对象的id # 反向查询 被关联的对象 查有外键的一侧 # pub_obj = models.Publisher.objects.get(id=1) # print(pub_obj.name) 不指定related_name pub_obj.book_set 管理对象 pub_obj.book_set.all() 指定related_name = ‘books’ pub_obj.books 管理对象 # 不指定 related_name=‘books‘ # print(pub_obj.book_set,type(pub_obj.book_set)) # print(pub_obj.book_set.all()) # 指定related_name=‘books‘ # print(pub_obj.books,type(pub_obj.books)) # print(pub_obj.books.all()) # 基于字段的查询 # ret = models.Book.objects.filter(publisher__name=‘老男孩出版社‘) # 不指定related_name # ret = models.Publisher.objects.filter(book__title=‘太亮教开车‘) # 指定related_name # ret = models.Publisher.objects.filter(books__title=‘太亮教开车‘) # 指定related_query_name=‘book‘ # ret = models.Publisher.objects.filter(book__title=‘太亮教开车‘) # 外键字段可以为null 才有remove和clear 只能写对象 pub_obj = models.Publisher.objects.get(id=1) # pub_obj.books.remove(models.Book.objects.get(id=1)) # pub_obj.books.clear() pub_obj.books.create(title=‘太亮的产后护理‘)
多对多的操作
import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "orm_practice.settings")
import django
django.setup()
from app01 import models# 基于对象的查询 # 正向 author_obj = models.Author.objects.get(id=2) # # print(author_obj.books,type(author_obj.books)) # print(author_obj.books.all()) # 反向 book_obj = models.Book.objects.get(id=1) # 不指定related_name=‘authors‘ # print(book_obj.author_set.all()) # 指定related_name=‘authors‘ # print(book_obj.authors.all()) # set 设置多对多关系 # author_obj.books.set([]) # author_obj.books.set([1,2,3]) # 要关联对象的ID [ 对象的id,对象的id] # author_obj.books.set(models.Book.objects.all()) # 要关联对象 [ 对象,对象] # add 添加多对多的关系 # author_obj.books.add(1) # 要关联对象的ID # author_obj.books.add(models.Book.objects.get(id=2)) # 要关联对象 # remove() 删除多对多的关系 # author_obj.books.remove(1) # 要关联对象的id # author_obj.books.remove(models.Book.objects.get(id=2)) # 要关联对象 # clear() # 清空当前对象的多对多的关系 # author_obj.books.clear() # create() # author_obj.books.create(title=‘太亮教抛光‘,) # update() 更新字段 # author_obj.books.update(title=‘太亮教抛光‘,) book_obj.authors.create(name=‘alex‘)
聚合 和分组
Max, Min, Sum, Avg, Count
mport osos.environ.setdefault("DJANGO_SETTINGS_MODULE", "orm_practice.settings") import django django.setup() from app01 import models from django.db.models import Max, Min, Sum, Avg, Count ret = models.Book.objects.aggregate(max=Max(‘price‘)) # { } # 统计每一本书的作者个数 ret = models.Book.objects.all().annotate(count=Count(‘author‘)).values(‘count‘) # 统计出每个出版社买的最便宜的书的价格 # 方法一 ret = models.Publisher.objects.all().annotate(Min(‘book__price‘)).values() # for i in ret: # print(i) # 方法二 ret = models.Book.objects.values(‘publisher__name‘).annotate(min=Min(‘price‘)).values(‘min‘) # for i in ret: # print(i) # 统计不止一个作者的图书 ret = models.Book.objects.annotate(count=Count(‘author‘)).filter(count__gt=1) ret = models.Book.objects.annotate(count=Count(‘author‘)).order_by(‘-count‘) print(ret) # 查询各个作者出的书的总价格 ret = models.Author.objects.annotate(Sum(‘books__price‘)).values() for i in ret: print(i)
F 和 Q
import osos.environ.setdefault("DJANGO_SETTINGS_MODULE", "orm_practice.settings") import django django.setup() from app01 import models from django.db.models import F # ret= models.Book.objects.filter(kucun__gt=F(‘sale‘)).values() # for i in ret: # print(i) # models.Book.objects.all().update(sale=F(‘sale‘)*2) # obj = models.Book.objects.filter(id=1).first() # # obj.sale = 60 # obj.save() from django.db.models import Q ret = models.Book.objects.filter(Q(~Q(id__lt=3) | Q(id__gt=5))&Q(id__lt=4)) print(ret)
事物
import osos.environ.setdefault("DJANGO_SETTINGS_MODULE", "orm_practice.settings") import django django.setup() from app01 import models from django.db import transaction try: with transaction.atomic(): models.Publisher.objects.create(name=‘新华出版社1‘) int(‘aaa‘) models.Publisher.objects.create(name=‘新华出版社2‘) models.Publisher.objects.create(name=‘新华出版社2‘) except Exception as e: print(e)
以上是关于Django ORM 操作的主要内容,如果未能解决你的问题,请参考以下文章