• 博客园项目前夕之ORM操作回顾


    创建表(建立模型)

    创建表首先我们应该知道自己想要创建什么表,就比如老师,或者作者这一类的,字段就应该是他的姓名、年龄、之类的。

    我们就用作者和书籍这一类来举例。

    作者模型:作者姓名和年龄

    作者详细模型:这个里面就是作者具体的详细信息。生日、手机号、家庭住址等信息

    作者模型和作者是一对一的关系

    出版社:出版社名称、地址

    书籍:有书籍的名称,一本书也有可能有多个作者一个作者也可能写很多本书,所以他们两个之间是

    多对多的关系(manytomany);一本书应该只有一个出版社,但是出版社可以出版很多本书,所以他和出版社应该是一对多的关系。

    具体模型如下:

    """
    作者表
    """

    class Author(models.Model): nid = models.AutoField(primary_key=True) name=models.CharField( max_length=32) age=models.IntegerField() # 与AuthorDetail建立一对一的关系
    authorDetail=models.OneToNoeFiled(to="AsuthorDetail") """
    作者详细信息表
    """ class AuthorDetail(models.Model): nid = models.AutoField(primary_key=True) birthday=models.DateField() telephone=models.BigIntegerField() addr=models.CharField( max_length=64) """
    出版社表
    """ class Publish(models.Model): nid = models.AutoField(primary_key=True) name=models.CharField( max_length=32) city=models.CharField( max_length=32) email=models.EmailField() """

    """ 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) keepNum=models.IntegerField()<br> commentNum=models.IntegerField() # 与Publish建立一对多的关系,外键字段建立在多的一方 publish=models.ForeignKey(to="Publish",to_field="nid") # 与Author表建立多对多的关系,ManyToManyField可以建在两个模型中的任意一个,自动创建第三张表 authors=models.ManyToManyField(to='Author') 
      

    添加表记录

    普通字段

    两种方式:

    1.

    publish_obj=Publish(name="新华出版社",city="北京")

    publish_obj.save()   #将数据保存到数据库

    2.

    publish_obj=Publish.objects.create(name="新华出版社",city="北京")

    外键字段

    两种方式

    1.

    publish_obj=Publish.objects.get(nid=1)

    Book.objects.create(title="金瓶眉",publishDate="2012-12-12",price=665,pageNum=334,publish=publish_obj)

    2.

    Book.objects.create(title="平凡的世界",publishDate="2012-12-12",price=75,pageNum=334,publish_id=1)

    多对多字段

    book_obj=Book.objects.create(title="追风筝的人",publishDate="2012-12-12",price=69,pageNum=4521,publish_id=2)

    author_lan=Author.objects.create(name="lan",age=21,authorDeatil=1)

    author_cao=Author.objects.create(name="cao",age=26,authorDetil=2)

    book_obj.authors.add(author_lan,author_cao)    #  将某个特定的 model 对象添加到被关联对象集合中。   =======    book_obj.authors.add(*[])

    book_obj.authors.create()    #创建并保存一个新对象,然后将这个对象加到被关联对象的集合中,然后返回这个新对象。

    解除关系

    book_obj.authors.remove()   将某个特定的对象从被关联对象集合中除去也就是#book_obj.authors.remove(*[])

    book_obj.authors.clear()       清空被关联的对象集合

    set方法()

    先清空,再设置,编辑书籍时就可以用到

    注意:

        对于所有的类型的关联字段,add()、create()、remove()和clear,set()都会马上更新数据库,也就是说,在关联的任何一端,都不需要再调用save()方法

    直接赋值:

    通过赋值一个新的可迭代的对象,关联对象集可以被整体替换掉。

    >>> new_list = [obj1, obj2, obj3]

    >>> e.related_set = new_list

    如果外键关系满足null=True,关联管理器会在添加new_list中的内容之前,首先调用clear()方法来解除关联集中一切已存在对象的关联。否则, new_list中的对象会在已存在的关联的基础上被添加

    查询表记录

    我们在这里再次将API相关查询写一下

    <1> all():                 查询所有结果
     
    <2> filter(**kwargs):      它包含了与所给筛选条件相匹配的对象
     
    <3> get(**kwargs):         返回与所给筛选条件相匹配的对象,返回结果有且只有一个,
                               如果符合筛选条件的对象超过一个或者没有都会抛出错误。
     
    <5> exclude(**kwargs):     它包含了与所给筛选条件不匹配的对象
     
    <4> values(*field):        返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一系列
                               model的实例化对象,而是一个可迭代的字典序列
     
    <9> values_list(*field):   它与values()非常相似,它返回的是一个元组序列,values返回的是一个字典序列
     
    <6> order_by(*field):      对查询结果排序
     
    <7> reverse():             对查询结果反向排序
     
    <8> distinct():            从返回结果中剔除重复纪录
     
    <10> count():              返回数据库中匹配查询(QuerySet)的对象数量。
     
    <11> first():              返回第一条记录
     
    <12> last():               返回最后一条记录
     
    <13> exists():             如果QuerySet包含数据,就返回True,
    否则返回False
      

    双下划线之单表查询

    models.User.objects.filter(id_lt=),id_gt=1)   获取id大于1且小于10的值

    models.User.objects.filter(id_in=[11,55,88])   获取id等于11,55,88的值

    models.User.objects.exclude(id_id=[11,55,88])  不等于这个的

    models.Tb1.objects.filter(name__contains="ven")
    models.Tb1.objects.filter(name__icontains="ven") # icontains大小写不敏感
     
    models.Tb1.objects.filter(id__range=[1, 2])      # 范围bettwen and
     
    startswith,istartswith, endswith, iendswith 

    基于对象的跨表查询

    一对多查询(publish与Book)

    正向按字段

    查询nid=1的书籍的出版社所在的城市

    book_obj=Book.objects.get(nid=1)

    print(book_obj.publish.city)

    # book_obj.publish 是nid=1的书籍对象关联的出版社对象

    反向查询按表名

    查询人民出版社出版过的所有书籍

    publish=Publish.objects.filter(name="人民出版社")

    book_list=publish.book_set.all()     #与人民出版社关联的所有书籍对象集合

    for book_obj in book_list:

         print(book_obj.title)

    一对一查询(Author与AuthorDetail)

    正向查询(按字段:authorDetail)

    #查询lan作者的手机号

    author_obj=Author.objects.get(namae="lan")

    print(author_obj.authorDetail.telphone)

    反向查询(按表名:author)

    #查询所有住在北京的作者的姓名

    authorDetail_list=AuthorDetail.objects.filter(addr="beijing")

    for obj in authorDetail_list:

       print(obj.author.name)

    多对多查询(Author与Book)

    正向查询(按字段:authors)

    #平凡的世界所有的作者的名字以及手机号

    book_obj=Book.objects.filter(title="平凡的世界").first()

    author_list=book_obj.authors.all()

    for obj in author_list:

    print(obj.name.obj.authorDetail.telphone)

    反向查询(按表名:book_set)

    查询lan出过的所有书籍的名字

    author_obj=author.objects.filter(name="lan").first()

    book_obj=author_obj.book_set.all()

    for obj in book_obj:

      print(book_obj.title)

    基于双下划线的跨表查询

    这是一种高效只管的查询表中关系的方式,可以自动确认sql join联系

    正向查询按字段,反向查询按表名

    用几道练习题来再次熟悉一下

    1.查询人民出版社出版过的所有书籍的名字与价格(一对多)

    正向查询按字段

    Book.objects.filter(publish__name="人民出版社").values_list("title","price")

    反向查询按表名

    obj=Publish.objects.filter(name="人民出版社").values_list("book__title","book__price")

    2.查询lan出过的所有的书籍的名字(多对多)

    正向查询按字段 authors

    obj=Book.objects.filter(authors__name="lan").values_list("title")

    反向查询按表名

    Author.objects.filter(name="lan").values_list("book__title")

    3.查询人民出版社出版过的所有书籍的名字以及作者的名字

    反向查询

    obj=Publish.objects.filter(name="人民出版社").values_list("book__title","book__authors__name")

    正向查询

    Book.objects.filter(publish__name="人民出版社").values("title","authors__name")

    4.查询手机号以151开头的作者出版过的所有书籍名称以及出版社名称

    Book.objects.filter(authors__authorDetail__telephone__startwith=="151").values_list("title","publish__name")

    ps反向查询时,如果定义了related_name,则用related_name替换表名

    ,例如: publish = ForeignKey(Blog, related_name='bookList'):

    查询人民出版社出版过的所有书籍的名字与价格

    反向查询不再是按表名,而是related_name:bookList

    obj=Publish.objects.filter(name="人民出版社").values_list("bookList__title","bookList__price")

    聚合查询与分组查询

    聚合:aggregate(*args,**kwargs)

    计算所有图书的平均价格

    from django,db.models import Avg

    Book,objects,all().aggregate(Avg("price"))

    {'price__avg': 34.35}

    aggregate是queryset的一个终止子句,它返回的是一个包含一些键值对的字典,键的名称是聚合值的标示符,值是计算出来的聚合值,键的名称是按照字段和聚合函数的名称自动生成出来的,如果你想要为聚合值指定一个名称,可以向聚合子句提供它。

    Bookobjects.aggregate(average_price=Avg("price"))

    {'average_price': 34.35}

    如果你希望生成不止一个聚合,你可以向aggregate()子句中添加另一个参数。所以,如果你也想知道所有图书价格的最大值和最小值,可以这样查询:

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

    Book.objects.faggregate(Avg("price"),Max("price"),Min(price))

    {'price__avg': 34.35, 'price__max': Decimal('81.20'), 'price__min': Decimal('12.99')}

    分组:annotate()

    为调用的queryset中的每一个对象都生成一个独立的统计值(统计方法用聚合函数)

    1.练习:统计每一本书的作者个数

    bookList=Book.objects.annotate(authorsNum=Count("authors"))

    for book_obj in bookList:

        print(book_obj.title.authorsNum)

    2.如果想对所查询对象的关联对象进行聚合

    练习:统计没一个出版社最便宜的书

    publishList=Publish.objects.annotate(MinPrice=Min("book__price"))

     for publish_obj in publishList:

      print(publish_obj.name,publish_obj.MinPrice)

    annotate的返回值是queryset,如果不想遍历对象,可以用valueslist:

    query=Publish.pbjects.annotate(MinPrice=Min("book__price")).values_list("name","Minprice")

    3.统计每一本以py开头的书籍的作者个数

    queryResult=Book.objects .filter(title__startswith="Py").annotate(num_authors=Count('authors'))

     

    4.统计不止一个作者的图书

    Book.objects.annotate(num_authors=Count('authors')).filter(num_authors__gt=1)

    5.根据一本书作者的数量的多少飞查询集queryset进行排序

    Book.objects.annotate(num_authors=Count("authors")).order_by('num_authors')

    6.按照各个作者出的书的总价格

    # 按author表的所有字段 group by

    obj=Author.objects.annotate(SumPrice=Sum("book__price")).values_list("name","SumPrice")

    # 按authors__name group by

    Book.objects.values("author__name").annotate(SumPrice=Sum("price")).values_list("authors__name","SumPrice")

    F查询和Q查询

    F是用来做比较的

    F查询

    1.查询评论数大于收藏数的书籍

    from django.db.models import F

    Book.objects.filter(commentNum_lt=F("keepNum"))

    Django支持F()对象之间以及F()对象和常数之间的加减乘除和取模的操作

    2.查询评论数大于收藏数2倍的书籍

    Book,objects.filter(commentNum__lt=F("keepNum")*2)

    修改操作也可以用F函数,比如将一本书的价格提高30元

    Book.objects.all().update(price=F("price")+30)

    Q查询

    q查询类似于or

    from django.db.models import Q

    q对象可以使用&和|符组合起来,当一个操作符在两个Q对象上使用时,它会产生一个新的Q对象

    BookList=Book.objects.filter(Q(authors__name="yuan")|Q(authors__name="egon"))

  • 相关阅读:
    浅谈数组
    前端冷知识
    number框
    jQuery封装轮播图插件
    瀑布流的简单制作
    Java script-数组与字符串方法
    Java script-1
    Web前端基础学习-2
    Web前端基础学习-3
    Web前端基础学习-1
  • 原文地址:https://www.cnblogs.com/1996-11-01-614lb/p/8409707.html
Copyright © 2020-2023  润新知