zoukankan      html  css  js  c++  java
  • Django之模型层,单,多表操作(三)

    一:多表操作之增、删、改

      1.1:增:

      一对多:

      方式1:

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

        book_obj=Book.objects.create(title="海尔兄弟",publishDate="2012-12-12",price=100,publish=publish_obj)

      方式2:

        book_obj=Book.objects.create(title="海尔兄弟",publishDate="2012-12-12",price=100,publish_id=1)

      多对多:

        # 当前生成的书籍对象
        book_obj=Book.objects.create(title="追风筝的人",price=200,publishDate="2012-11-12",publish_id=1)
        # 为书籍绑定的做作者对象
        yuan=Author.objects.filter(name="yuan").first() # 在Author表中主键为2的纪录
        egon=Author.objects.filter(name="alex").first() # 在Author表中主键为1的纪录
        # 绑定多对多关系,即向关系表book_authors中添加纪录
        book_obj.authors.add(yuan,egon)    #  将某些特定的 model 对象添加到被关联对象集合中。

      1.2:删

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

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

     1.3:改 

        set会先清空在设置:

      new_list = [obj1, obj2, obj3]

      e.related_set = new_list

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

     1.4:补充:

      clear() :从关联对象集中移除一切对象。

          b = Blog.objects.get(id=1)

        b.entry_set.clear()

          注意这样不会删除对象 —— 只会删除他们之间的关联。
    就像
    remove() 方法一样,clear()只能在 null=True的ForeignKey上被调用。
    add(obj1[, obj2, ...])
    View Code

    二:多表操作之查询

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

     2.1:基于对象查询

       一对多正向查询:按字段,publish

    # 查询主键为1的书籍的出版社所在的城市
    book_obj=Book.objects.filter(pk=1).first()
    # book_obj.publish 是主键为1的书籍对象关联的出版社对象
    print(book_obj.publish.city)
       一对多反向查询:按表名_set(book_set) 
    publish=Publish.objects.get(name="苹果出版社")
    #publish.book_set.all() : 与苹果出版社关联的所有书籍对象集合
    book_list=publish.book_set.all()    
    for book_obj in book_list:
           print(book_obj.title)
      多对多正向查询:正向查询按字段
    # python所有作者的名字以及手机号
    book_obj=Book.objects.filter(title="python").first()
    authors=book_obj.authors.all()
    for author_obj in authors:
         print(author_obj.name,author_obj.authorDetail.telephone)

     多对多反向查询:反向查询按表名_set

        # 查询egon出过的所有书籍的名字
    
        author_obj=Author.objects.get(name="yjp")
        book_list=author_obj.book_set.all()        #与yjp作者相关的所有书籍
        for book_obj in book_list:
            print(book_obj.title)

    2.2:基于双下划线查询

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

    多对多正向查询:正向查询按字段

        # 正向查询 按字段:authors:
        queryResult=Book.objects.filter(authors__name="yjp").values_list("title")

    多对多反向查询:反向查询按字段

     # 反向查询 按表名:book
     queryResult=Author.objects.filter(name="yuan").values("book__title","book__price")

    values和values_list区别:

       values():返回QuerySet对象

       values_list():返回list

    注意:
    反向查询时,如果定义了related_name ,则用related_name替换表名,例如:

    publish = ForeignKey(Blog, related_name='bookList')
    #反向查询 不再按表名:book,而是related_name:bookList
    queryResult=Publish.objects
              .filter(name="人民出版社")
              .values_list("bookList__title","bookList__price")

    三:聚合查询和分组查询

      3.1:聚合查询      

    from django.db.models import Sum,Avg,Max,Min # 导入分组函数
    
    # 计算所有图书的平均价格,返回{'price__avg': 34.35}
     Book.objects.all().aggregate(Avg('price'))
    #计算所有图书的价格,和,最大值,最小值
    #返回字典
     Book.objects.aggregate(Sum('price'), Max('price'), Min('price'))

      3.2:分组查询

    from django.db.models import Count  #导入分组函数
    # 标签列表  通过mldels进行跨表查询,并通过'article_tags'进行分组
    # 返回值中 c 就是分组后的值
    tag_list=UserInfo.objects.filter(username=username).values(c=Count('article__tags')).values_list('c','article__tags__title')

     四:F查询,Q查询,extra

         4.1:F查询:可以引用当前表内的字段

      在上面所有的例子中,我们构造的过滤器都只是将字段值与某个常量做比较。如果我们要对两个字段的值做比较,那该怎么做呢?Django 提供 F() 来做这样的比较。F() 的实例可以在查询中引用字段,来比较同一个 model 实例中两个不同字段的值。

    # 查询评论数大于收藏数的书籍
    from django.db.models import F
    Book.objects.filter(commnetNum__lt=F('keepNum'))

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

    # 查询评论数大于收藏数2倍的书籍
     Book.objects.filter(commnetNum__lt=F('keepNum')*2)

      4.2:Q查询:可对查询条件进行 & | ~ 与 或 操作

        filter() 等方法中的关键字参数查询都是一起进行“AND” 的。 如果你需要执行更复杂的查询(例如OR 语句),你可以使用Q 对象

        查询函数可以混合使用Q 对象和关键字参数。所有提供给查询函数的参数(关键字参数或Q 对象)都将"AND”在一起。但是,如果出现Q 对象,它必须位于所有关键字参数的前面。

    #
    bookList=Book.objects.filter(Q(authors__name="yuan")|Q(authors__name="egon"))
    #与和非
    bookList=Book.objects.filter(Q(authors__name="yuan") & ~Q(publishDate__year=2017)).values_list("title")
    #混合使用
    bookList=Book.objects.filter(Q(publishDate__year=2016) | Q(publishDate__year=2017),
                                  title__icontains="python"
                                 )

       4.3:extra: django提供的sql语句不能进行复杂的操作,extra可以对现有的操作函数进行扩展

        extra源码:

    def extra(self, select=None, where=None, params=None, tables=None,
                  order_by=None, select_params=None):
            """
            Adds extra SQL fragments to the query.
            """
            assert self.query.can_filter(), 
                    "Cannot change a query once a slice has been taken"
            clone = self._clone()
            clone.query.add_extra(select, select_params, where, params, tables, order_by)
            return clone

      extra用法

    ## select提供简单数据
    # SELECT age, (age > 18) as is_adult FROM myapp_person;
    Person.objects.all().extra(select={'is_adult': "age > 18"})  # 加在select后面
    
    ## where提供查询条件
    # SELECT * FROM myapp_person WHERE first||last ILIKE 'jeffrey%';
    Person.objects.all().extra(where=["first||last ILIKE 'jeffrey%'"])  # 加一个where条件
    
    ## table连接其它表
    # SELECT * FROM myapp_book, myapp_person WHERE last = author_last
    Book.objects.all().extra(table=['myapp_person'], where=['last = author_last']) # 加from后面
    
    ## params添参数
    # !! 错误的方式 !!
    first_name = 'Joe'  # 如果first_name中有SQL特定字符就会出现漏洞
    Person.objects.all().extra(where=["first = '%s'" % first_name])
    # 正确方式
    Person.objects.all().extra(where=["first = '%s'"], params=[first_name])
    View Code

     

    
    
    

         

      

    
    
     
  • 相关阅读:
    条形码校验码生成
    js 模仿块级作用域(私有作用域)、私有变量
    js 闭包
    js 继承
    javascript 创建对象
    jQuery.noConflict() 函数
    C#对话框-打开和保存对话框(转)
    String.format()的用法
    转:WPF中ListBox的创建和多种绑定用法
    在wpf或winform关闭子窗口或对子窗口进行某个操作后刷新父窗口
  • 原文地址:https://www.cnblogs.com/yingjp/p/10094465.html
Copyright © 2011-2022 走看看