Djano-orm

orm

1. 配置环境

  1. 在项目的setting中配置数据库的相关信息

    DATABASES = {
          
          
    	'default':{
          
          
    		'ENGINE':'...mysql',
    		'NAME':'库名',
    		'HOST':'127.0.0.1',  
    		'PORT':3306,
    		'USER':'root',
    		'PASSWORD':'123'
    	}
    
    }
    
  2. 在项目的init文件中配置

    import pymysql
    pymysql.install_as_MySQLdb()
    
  3. 创建表

    1. 创建完项目后,我们进入app,进入models.py创建我们的模型(数据库
      1. (注意) 期中id为自增字段并且为主键(如果不写主键字段默认id为主键字段)
  4. 数据库同步指令(在terminal中输入以下命令)

    #创建一个记录告诉Django我要创建一个表
    python manage.py makemigrations
    #执行上一个记录
    ptthon manage.py migrate
    

2. 用orm进行(简单的)增删改查

增(create)

  1.  	#实例化要添加的记录(对象)
        student_obj = models.Student(
            name='dazhaung',
            age=23,
        )
        #存储到数据库
        student_obj.save()
    
  2. #期中参数也可以写成    **{'name':'xx','age':6}  的格式
    new_obj = models.Student.objects.create(name='xiaozhuang2',age=6)
    
    #点属性,可以获取对应字段的数据
    print(new_obj.name)  
    print(new_obj.age)
    
  3. #进行批量创建
    objs_list = []
        for i in range(100,3000000):
            obj = models.Student(
                name='xiangxixxx',
                age = 10,
            )
            objs_list.append(obj)
    #先存到内存,最后只进行一次磁盘io
    models.Student.objects.bulk_create(objs_list)
    
  4. #有就更新,没有就创建
    models.Student.objects.update_or_create(
        #先找到对应的字段
            name='红旭妹妹2',
        	
        #进行更新或增加
            defaults={
          
          
                'age':38,
            }
        )
    

删(delete)

  1. #delete  queryset 和model对象都可以调用
    
    #model对象来调用的delete方法
    models.Student.objects.get(id=3).delete()
    
    #queryset对象来调用的delete方法
    models.Student.objects.filter(name='红旭妹妹').delete()
    
    #删除所有
     models.Student.objects.all().delete()
    

改(update)

  1. #update方法 只能queryset对象能调用更新方法
    models.Student.objects.filter(name='红旭妹妹').update(age=38)
    

查(filter)

  1. 查询所有的数据(.all())

    1. #返回queryset对象
      all_objs = models.Student.objects.all()
      
  2. 条件查询 (.filter())

    1. #返回queryset对象
      #查询不到内容,不会 报错,返回一个<QuerySet []>空的queryset
      objs = models.Student.objects.filter(id=2)
      
  3. 条件查询(.get())

    1.  #返回model对象
       #而且get方法有且必须只有1个结果否者报错
       obj = models.Student.objects.get(id=3)
      

3. 查询接口

all():

 	1. 查询所有结果,结果是queryset类型

filter(**kwargs):

  1. 它包含了与所给筛选条件相匹配的对象,结果也是queryset类型

  2. 期中多个参数之间用逗号隔开是and的关系

    Book.objects.filter(title='linux',price=100)
    
  3. queryset类型可以调用fitler在过滤

    models.Student.objects.all().filter(id=7)  
    

get(**kwargs):

  1. 返回model对象类型

  2. get方法有且必须只有1个结果否者报错

    Book.objects.get(id=1)
    

exclude(**kwargs):

  1. 排除的意思

  2. 它包含了与所给筛选条件不匹配的对象

  3. 返回值是queryset类型

    #返回id不等于6的所有的对象
    Book.objects.exclude(id=6)
    
    #在queryset基础上调用
    Book.objects.all().exclude(id=6)
    

order_by(*field):

  1. 对查询结果排序

  2. queryset类型的数据来调用

  3. 默认是按照id来升序排列的

  4. 返回值还是queryset类型

    #直接写price,默认是按照price升序排列
    #多条件排序,按照price进行升序,price相同的数据,按照id进行升序
    models.Book.objects.all().order_by('price','id') 
    
    #按照字段降序排列,就写个负号就行了order_by('-price')
    
    
    

reverse():

  1. 对查询结果反向排序

  2. queryset类型的数据来调用

  3. 返回值还是queryset类型

    query = models.Student.objects.all().order_by('id').reverse()
    

count():

  1. queryset类型的数据来调用,返回数据库中匹配查询(QuerySet)的对象数量。

first():

  1. queryset类型的数据来调用,返回第一条记录

    Book.objects.all()[0] = Book.objects.all().first()
    
  2. 得到的是model对象

last():

  1. 同上----返回最后一条记录

exists():

  1. queryset类型的数据来调用,如果QuerySet包含数据,就返回True,否则返回False。

    #翻译成的sql是SELECT (1) AS `a` FROM `app01_book` LIMIT 1,就是通过limit 1,取一条来看看是不是有数据
    all_books = models.Book.objects.all().exists() 
    

values(*field):

  1. queryset类型的数据来调用
  2. 返回一个ValueQuerySet——一个特殊的QuerySet(可迭代的字典序列)

values_list(*field):

  1. 它与values()非常相似,它返回的是一个元组序列,values返回的是一个字典序列

distinct():

  1. values和values_list得到的queryset类型的数据来调用

  2. 从返回结果中剔除重复纪录,结果还是queryset

    query = models.Student.objects.all().values('age').distinct()
    

总结:

接口名 作用 调用类型 结果类型
all() 查询所有结果 objects QuerySet
filter 条件查询 objects QuerySet
get 条件查询,但只返回一条数据 objects Model(行记录对象)
exclude 匹配非条件的对象 objects QuerySet
order_by 查询结果进行排序 QuerySet QuerySet
reverse 对查询结果反向排序 QuerySet QuerySet
count 返回匹配查询的对象数量 QuerySet int
first 返回第一条记录 QuerySet Model
last 返回最后一条记录 QuerySet Model
exists 判断QuerySet是否包含数据 QuerySet bool(True、False)
values 以字典方式返回 QuerySet ValueQuerySet
values_list 以元组方式返回 QuerySet dic
distinct 去重 values和values_list得到的queryset类型 queryset

4.模糊查询

#price值等于这三个里面的任意一个的对象
Book.objects.filter(price__in=[100,200,300]) 

#大于,大于等于是price__gte=100,别写price>100,这种参数不支持
Book.objects.filter(price__gt=100)  

#小于,小于等于是price__lte=100
Book.objects.filter(price__lt=100)

#sql的between and,大于等于100,小于等于200
Book.objects.filter(price__range=[100,200])

 #title值中包含python的
Book.objects.filter(title__contains="python") 

#title值中包含python的---不区分大小写
Book.objects.filter(title__icontains="python") 

#以什么开头,istartswith  不区分大小写
Book.objects.filter(title__startswith="py") 

#找2012年的所有书籍
Book.objects.filter(pub_date__year=2012)

#找大于2012年的所有书籍
models.Book.objects.filter(pub_date__year__gt=2012)

总结:

模糊查找类型 表示方法
任意包含某个值 xx__in=[100,200,300
大于某个值 xx__gt=100
小于某个值 xx_lt=100
介于某个值之间 xx_range=[100,200]
包含某个字符 xx_contains=‘python’
不区分大小写 xx_icontains=‘python’
以什么开头 xx_startswith=‘py’
查询某一年 xx_year=2012
大于某一年 xx_year_gt=2012

5. 外部文件操作django的models

#外部文件使用django的models,需要配置django环境
import os

if __name__ == '__main__':
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "singletablehw.settings")
    import django
    django.setup()

    from app01 import models
    import datetime
    
    #批量创建
    obj_list = []
    for i in range(1,10):
        obj = models.Book(
            title='葵花宝典第%s式'%i,
            price=20 + i,
            pub_date='198%s-11-11 00:00:00'%i,
            # pub_date=datetime.datetime.now(),

            publish= '吴老板出版社' if i < 5 else '太白出版社',

        )
        obj_list.append(obj)

    models.Book.objects.bulk_create(obj_list)

6. url反向解析

url中:
#name='abook'  别名
url(r'^add_book/', views.add_book,name='abook'), 

#name=‘delete_book’   有一个数字参数
url(r'^delete_book/(\d+)/', views.delele_book,name='delete_book'),

视图中:
from django.urls import reverse
reverse('abook')     ---代表解析了无参数的别名

#/delete_book/71/ 带参数的
reverse('delete_book',args=(71,))


模板
   {
    
    % url 'abook' %}  无参数的
   {
    
    % url 'delete_book' book.id %}  无参数的

7. 一对一,一对多,多对多关系

1. 创建表

  1. 一对一

    1. #to_field可以不写,默认是关联到另一张表的主键
      #on_delete=models.CASCADE------进行级联删除
      xx = models.OneToOneField(to='表名',to_field='字段名',on_delete=models.CASCADE)
      
    2. 例子:

      #一对一到AuthorDetail表  生成为表字段之后,数据库会自动变为authorDetail_id这样有一个名称
      authorDetail=models.OneToOneField(to='AuthorDetail')
      
  2. 一对多

    1. xx = models.ForeignKey(to='表名',to_field='字段名',on_delete=models.CASCADE)
      
    2. 例子:

       #数据库会自动变为publishs_id这样有一个名称
          publishs=models.ForeignKey(to="Publish")
      
  3. 多对多

    1. xx = models.ManyToManyField(to='另外一个表名') #这是自动创建第三表
      
    2. 例子:

      authors=models.ManyToManyField(to='Author',)
      
      
      #手动创建第三张表,暂时忽略
      # class BookToAuthor(models.Model):
      #     book_id = models.ForeignKey(to='Book')
      #     author_id = models.ForeignKey(to='Author')
      

2. 增加数据

  1. 一对一
  #方式1
    new_author_detail = models.AuthorDetail.objects.create(
        birthday='1979-08-08',
        telephone='138383838',
        addr='黑龙江哈尔滨'
    )
    
    models.Author.objects.create(
         name='王涛',
         age='40',
         authorDetail=new_author_detail,
     )
    
   # 方式2  常用
    
    obj = models.AuthorDetail.objects.filter(addr='山西临汾').first()
    
     models.Author.objects.create(
         name='王涛',
         age='40',
   	     authorDetail_id=obj.id,
     

  1. 一对多

    #方式1
    
     obj = models.Publish.objects.get(id=2)
        
     models.Book.objects.create(
         title = '李帅的床头故事',
         publishDate='2019-07-22',
         price=3,
         
         # publishs=models.Publish.objects.get(id=1),
         
         publishs=obj,
    
     )
    
    # 方式2 常用
     obj = models.Publish.objects.get(id=2)
     models.Book.objects.create(
         title='李帅的床头故事2',
         publishDate='2019-07-21',
         price=3.5,
         
         # publishs=models.Publish.objects.get(id=1),
         
         #publishs_id为存到数据库的名字
         publishs_id=obj.id
    
     )
  1. 多对多
  # 方式1   常用
    
    #先寻找增加那个对象
     book_obj = models.Book.objects.get(nid=1)
     #add增加
     book_obj.authors.add(*[1,2])
        
        
    # 方式2
     author1 = models.Author.objects.get(id=1)
     author2 = models.Author.objects.get(id=3)
    #第五本书是id为1 和id为3 的作者写的
     book_obj = models.Book.objects.get(nid=5)
     book_obj.authors.add(*[author1,author2])

3. 删除数据

  1. 一对一,一对多(是一样的删除方式)

    # 表一外键关联到表二,表一删除,不影响表2,表2删除会影响表1
    
    	#一对一
    	# models.AuthorDetail.objects.get(id=2).delete()
        # models.Author.objects.get(id=3).delete()
    
        # 一对多
        # models.Publish.objects.get(id=1).delete()
        # models.Book.objects.get(nid=1).delete()
    
  2. 多对多关系删除

    	#找到要删除的对象 
        book_obj = models.Book.objects.get(nid=6)
        #通过进行多对多联系的字段删除
         book_obj.authors.remove(6)
        #删除多条数据
         book_obj.authors.remove(*[5,6])
        #清空book nid=6的数据
         book_obj.authors.clear()
            
         book_obj.authors.add(*[1,])
        #删除然后更新
         book_obj.authors.set('1')
         book_obj.authors.set(['5','6']) 
    

4. 更新数据

	 #一对一
     models.Author.objects.filter(id=5).update(
         name='崔老师',
         age=16,
         # authorDetail=models.AuthorDetail.objects.get(id=5),
         authorDetail_id=4,
     )
    #一对多
     models.Book.objects.filter(pk=4).update(
         title='B哥的往事2',
         # publishs=models.Publish.objects.get(id=3),
         publishs_id=3,
     )

5.(基于对象的跨表查询)

正向查询和反向查询(关系属性(字段)写在哪个类(表)里面,从当前类(表)的数据去查询它关联类(表)的数据叫做正向查询,反之叫做反向查询)

  1. 一对一

    1. 正向查询

      1. 正向查询靠对象,取到数据对象后,通过操作符对外键操作,就能拿到外键的对象,从而取到内容

        author_obj = models.Author.objects.filter(name='admin').first()
        result = author_obj.authorDetail.telephone
        
    2. 反向查询

      1. 查到对象后,通过小写的表名来获取另一个表的属性

        author_detail_obj = models.AuthorDetail.objects.get(telephone='213')
        result = author_detail_obj.author.name
        
  2. 一对多

    1. 正向查询

      1. 与一对一较为类似

        book_obj = models.Book.objects.get(title='第二本书')
        result = book_obj.publishs.name
        
    2. 反向查询

      1. 注意对象调用的是加_set的方法,然后all()即可取出全部内容

        publish_obj = models.Publish.objects.get(name="老男人出版社")
        result = publish_obj.book_set.all()
        
  3. 多对多

    1. 正向查询

      1. book_obj = models.Book.objects.get(title='第一本书')
        result = book_obj.authors.all()
        
    2. 反向查询

      1. auth_obj = models.Author.objects.get(name='admin')
        result = auth_obj.book_set.all()
        

6. 基于双下划綫的跨表查询

  1. 一对一

    1. 正向查询
    #obj为model对象    通过model对象的一对一对应的键 查看 其对应的键
    obj = models.Author.objects.filter(name='崔老师').values('authorDetail__telephone')
    
    1. 反向查询
    #values可以不写,则去除能拿到的全部数据。filter中的双下划线表示联表
    result=models.AuthorDetail.objects.filter(author__name='admin').values('telephone')
    
    
  2. 一对多

    1. 正向查询

      result = models.Book.objects.filter(title='第一本书').values("publishs__name")
      
    2. 反向查询

      result = models.Publish.objects.filter(book__title='第一本书').values('name')
      
  3. 多对多

    1. 正向查询
    obj = models.Book.objects.filter(publishs__name='老男人出版社').values('title')
    
    1. 反向查询
    obj = models.Publish.objects.filter(name='老男人出版社').values("book__title")
    

7.进阶查询

  1. 查询老男人出版社出版的书的名字和作者的名字
#三表联查

obj = models.Book.objects.filter(publishs__name='老男人出版社').values('title','authors__name')

#'book__authors__name'是通过book表的外键进行查询
obj = models.Publish.objects.filter(name='老男人出版社').values('book__title','book__authors__name')

8.反向查询代理

  1. 在创建表是外键字段添加参数related_name
class Book(models.Model):
    nid = models.AutoField(primary_key=True)
    title = models.CharField( max_length=32)
    publishDate=models.DateField()
    price=models.DecimalField(max_digits=5,decimal_places=2)  #decimal(16,2)
    publishs=models.ForeignKey(to="Publish",related_name='xx')
    authors=models.ManyToManyField(to='Author',)

9.聚合函数

 from django.db.models import Avg,Max,Min,Sum,Count

    # 计算所有图书的平均价格
    obj = models.Book.objects.all().aggregate(a=Avg('price'),m=Max('price')) 			#aggregate()是QuerySet 的一个终止子句,得到的是个字典.
    # print(obj['m'] - 2) #{'price__avg': 2.833333}

10.分组

  1. models.Publish.objects.annotate(a=Avg('book__price')).values('a')
    
  2. obj = models.Book.objects.values('publishs_id').annotate(a=Avg('price'))
    ## select avg (price) from app01_ book GROUP BY publishs_ id;
    

11.F和Q查询

  1. F查询(针对自己表中的数据进行查询)

    1. from django.db.models import F,Q
      
      #good和comment都是book的字段
      models.Book.objects.filter(good__gt=F('comment')*2)
      
      #对一列price字段都加一
      models.Book.objects.all().update(price=F('price')+1)
      
  2. Q查询

    1. # 与&  或|  非~
      
      
      filter(Q(xx=11)|Q(ss=22)&Q(oo=33))
      filter(Q(Q(xx=11)|Q(ss=22))&Q(oo=33))  &优先级高
      filter(Q(Q(xx=11)|Q(ss=22))&Q(oo=33),name='dd')  
      

bjects.annotate(a=Avg(‘book__price’)).values(‘a’)


2. ```python
obj = models.Book.objects.values('publishs_id').annotate(a=Avg('price'))
## select avg (price) from app01_ book GROUP BY publishs_ id;

11.F和Q查询

  1. F查询(针对自己表中的数据进行查询)

    1. from django.db.models import F,Q
      
      #good和comment都是book的字段
      models.Book.objects.filter(good__gt=F('comment')*2)
      
      #对一列price字段都加一
      models.Book.objects.all().update(price=F('price')+1)
      
  2. Q查询

    1. # 与&  或|  非~
      
      
      filter(Q(xx=11)|Q(ss=22)&Q(oo=33))
      filter(Q(Q(xx=11)|Q(ss=22))&Q(oo=33))  &优先级高
      filter(Q(Q(xx=11)|Q(ss=22))&Q(oo=33),name='dd')  
      

猜你喜欢

转载自blog.csdn.net/CSDNzhaojiale/article/details/104196455
Orm