Django的orm中get和filter的不同


Django的orm框架对于业务复杂度不是很高的应用来说还是不错的,写起来很方面,用起来也简单。对于新手来说查询操作中最长用的两个方法get和filter有时候一不注意就会犯下一些小错误。那么今天就来小节下这两个方法使用上的不同。

 

首先对比下两个函数文档上的解释。

get

Returns the object matching the given lookup parameters, which should be in the format described in Field lookups.

get() raises MultipleObjectsReturned if more than one object was found. The MultipleObjectsReturned exception is an attribute of the model class.

get() raises a DoesNotExist exception if an object wasn’t found for the given parameters. This exception is also an attribute of the model class

 

filter

Returns a new QuerySet containing objects that do not match the given lookup parameters.

The lookup parameters (**kwargs) should be in the format described in Field lookups below. Multiple parameters are joined via AND in the underlying SQL statement, and the whole thing is enclosed in a NOT().

 

总结分析

  • 输入参数
    get 的参数只能是model中定义的那些字段,只支持严格匹配
    filter 的参数可以是字段,也可以是扩展的where查询关键字,如in,like等

  • 返回值
    get 返回值是一个定义的model对象
    filter 返回值是一个新的QuerySet对象,然后可以对QuerySet在进行查询返回新的QuerySet对象,支持链式操作
    QuerySet一个集合对象,可使用迭代或者遍历,切片等,但是不等于list类型(使用一定要注意)

  • 异常
    get 只有一条记录返回的时候才正常,也就说明get的查询字段必须是主键或者唯一约束的字段。当返回多条记录或者是没有找到记录的时候都会抛出异常
    filter 有没有匹配的记录都可以

     

    一.先说下django的get方法:

    1django的get方法是从数据库的取得一个匹配的结果,返回一个对象,如果记录不存在的话,它会报错。
    比如我数据库里有一条记录,记录的author的值是oldboy的话,我用b=Book.objects.get(author="oldboy"),
    返回的是一个记录对象,你可以通过b . _ _ dict _ _来查看,它返回的是一个字典的形式,{’key’:valeus},key是字段的名称,而values是值的内容。
    而如果我用get方法来查询一个数据库里不存在的记录,程序会报错。
    比如:b=Book.objects.get(name='老王'),你自己可以运行看下。
    2如果你用django的get去取得关联表的数据的话,而关键表的数据如果多于2条的话也会报错。

    比如我的student表里有一个记录:

    d name age
    1 python 24
    
    book表:
    
    id student_id
    1 1
    2 1

    使用

    student = Student.objects.get(name='python')
    book = Book.objects.get(student)

    它也会报错,因为book表有2条记录和student表相匹配。

     

    二.再说下django filter:


    1django的filter方法是从数据库的取得匹配的结果,返回一个对象列表,如果记录不存在的话,它会返回[]。
    比如我数据库里有一条记录,记录的name的值是老王python的话,我用
    student = Student.objects.filter(name='老王python')
    它返回的student是一个对象的列表,可以看的出来student[0]和上面的get方式返回的student的结果是一样的。
    2如果你用django的get去取得关联表的数据的话,无论关联表有多少记录的都不会报错。
    django 除了model比较强大的话,表单和模板也很强大.
    另外我从别的资料里看到filter好像有缓存数据的功能,第一次查询数据库并生成缓存,下次再调用filter方法的话,直接取得缓存的数据,会get方法每次执行都是直接查询数据库的,不知道这个是不是正确。

     

     

    单表操作

    表记录的增

    models.Publisher.objects.create(name="沙河出版社")

    表记录的改

    方式一:
    b=Book.objects.get(author="oldboy")
    b.price=120
    b.save()
                
    方式二:
    #update是QuerySet
    Book.objects.filter(author="yuan").update(price=999)
    表记录的查(重点):
    book_list = Book.objects.filter(id=2)
    book_list=Book.objects.exclude(author="yuan").values("name","price")
                    
    book_list=Book.objects.all()
    book_list = Book.objects.all()[::2]
    book_list = Book.objects.all()[::-1]
                    
    #first,last,get取到的是一个实例对象,并非一个QuerySet的集合对象
    book_list = Book.objects.first()
    book_list = Book.objects.last()  
    book_list = Book.objects.get(id=2)#只能取出一条记录时才不报错
                    
    ret1=Book.objects.filter(author="oldboy").values("name")
    ret2=Book.objects.filter(author="yuan").values_list("name","price")
                    
    book_list= Book.objects.all().values("name").distinct()
    book_count= Book.objects.all().values("name").distinct().count()
    
    表记录的删

    models.Publisher.object.get(id=1).delete()

    Book.objects.filter(author="oldboy").delete()

  • 模糊查询  双下划线__

    book_list=Book.objects.filter(name__icontains="P").values_list("name","price")
    book_list=Book.objects.filter(id__gt=5).values_list("name","price")
    

     

  • 外键的增删改查

    增删查同上
       
        book_obj = models.Publisher.object.filter(id=1)
        book_obj.publisher是什么?
            和我这本书关联的出版社对象
        book_obj.publisher.id    是和我这本书关联的出版社id值
        book_obj.publisher.name    是和我这本书关联的出版社名称

    多表操作

    多表操作(一对多):
                   #添加记录
                   #publish_id=2
                   Book.objects.create(name="linux运维",price=77,pub_date="2017-12-12",publish_id=2)
                  

                   #publish=object
                   Book.objects.create(name="GO",price=23,pub_date="2017-05-12",publish=publish_obj)
                  
                   #查询记录(通过对象)
                  
                         正向查询:
                         book_obj=Book.objects.get(name="python")  
                         pub_obj=book_obj.publish----》书籍对象对应的出版社对象
                         pub_obj.name
                         反向查询:
                         pub_obj = Publish.objects.filter(name="人民出版社")[0]
                         pub_obj.book_set.all().values("name","price")
                        
                   #查询记录(filter values  双下划线__)
                        
                        #人民出版社出版过的书籍与价格
                        ret=Book.objects.filter(publish__name="人民出版社").values("name","price")
                       
                        #python这本书出版社的名字
                        ret2=Publish.objects.filter(book__name="python").values("name")
                       
                        #python这本书出版社的名字
                        ret3=Book.objects.filter(name="python").values("publish__name")
                       
                        #北京的出版社出版书的名字
                        ret4=Book.objects.filter(publish__city="北京").values("name")
                       
                        #2017年上半年出版过书的出版社的名字
                        ret5=Book.objects.filter(pub_date__lt="2017-07-01",pub_date__gt="2017-01-01").values("publish__name")
                       
                       
         多表操作(多对多):

                       1.查id为1的作者写过的书?

                          author_obj=models.Author.objects.get(id=1)

                          author_obj.books.all()

                       2.想给作者绑定多本书?

                           author_obj=models.Author.objects.get(id=1)

                          author_obj.books.set([1,2,3]) --->把id是1,2,3的书和我这个作者关联

     


                        
                        创建多对多的关系 author= models.ManyToManyField("Author")(推荐)
                       
                       
                        书籍对象它的所有关联作者  obj=book_obj.authors.all()
                                绑定多对多的关系  obj.add(*QuerySet)  
                                                  obj.remove(author_obj)
                                                 
                                                 
                        如果想向第三张表插入值的方式绑定关系:  手动创建第三张表

                                # class Book_Author(models.Model):
                                #     book=models.ForeignKey("Book")
                                #     author=models.ForeignKey("Author")                   
                                Book_Author.objects.create(book_id=2,author_id=3)
                               
                       
                        掌握:通过 filter values (双下换线)进行多对多的关联查询(形式和一对多)


  • 免责声明!

    本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



     
    粤ICP备18138465号  © 2018-2025 CODEPRJ.COM