9.14.16 Django ORM进阶用法

2018-9-14 14:26:45

ORM 练习题   : http://www.cnblogs.com/liwenzhou/articles/8337352.html

2018-9-14 21:17:49 明天继续看 day70

2018-9-16 15:58:11

终于把day70看完了 都是讲的ORM查询什么的!

贴上源代码

ORM1

# /usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2018/9/14 15:28 
# @Author : TrueNewBee
import os
from app001 import models
"""
2018-9-14 19:29:12
这里只涉及用法,不涉及具体数据内容
因为数据库里面内容我没有添加

"""


if __name__ == '__main__':
    # 加载Django项目的配置信息
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite67.settings")
    import django
    django.setup()

    # 一对一的查询
    # 和外键查询类似
    author_obj = models.Author.objects.get(id=1)
    obj = author_obj.detail
    print(obj.hobby, obj.addr)

    # 在app01 里面查询 id是1的作者关联的书
    from app01 import models
    ret = models.Author.objects.get(id=1).books.all()
    print(ret)
    print("app01".center(80, "-"))

    # 在app02 里面查询 id是1的作者关联的书
    # from app02 import models
    ret = models.Author2Book.objects.filter(author_id=1).values_list("book_id")
    # id是1的作者关联的书的id
    print(ret)
    ret = [i[0] for i in ret]
    # 查书这张表
    ret = models.Book.objects.filter(id_in=ret)
    print(ret)

    # 在app03 里面查询id 是1的作者关联的书
    # from app03 import models
    ret = models.Author.objects.get(id=1).book.all()
    print(ret)
    # 从作者关联的书里面移除id是1的书
    # 没有django ORM封装的那些快捷方式,我们要自己亲自修改第三张表
    models.Author2Book.objects.get(author_id=1, book_id=1).delete()

ORM2

# /usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2018/9/16 14:51 
# @Author : TrueNewBee
import os
"""
2018-9-16 14:51:59
这里只涉及用法,不涉及具体数据内容
因为数据库里面内容我没有添加
"""
from app01 import models

if __name__ == '__main__':
    # 加载Django项目的配置信息
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite67.settings")
    import django
    django.setup()

    # 查找左右书名包含沙河的书
    ret = models.Book.objects.filter(title__contains="沙河")
    print(ret)
    # 查找所有出版日期是2018的书
    ret = models.Book.objects.filter(publishe_data_year=2018)
    print(ret)
    # 查找价格大于10元的书
    ret = models.Book.objects.filter(price_gt=10)
    print(ret)
    # 找到沙河的出版社
    ret = models.Publisher.objects.filter(city="沙河")
    print(ret)

    # distinct  去重
    # 查找所有出关联的出版社
    ret = models.Book.objects.all().values_list("publisher__name")
    print(ret)
    print(ret.distinct())   # Queryset  去重

    # 将所有的书按照价格倒叙排序
    ret = models.Book.objects.all().order_by("price").reverse()
    print(ret)
    # 支持符号表示倒序
    ret = models.Book.objects.all().order_by("-price")
    print(ret)

    # 查询书名是沙河异闻录的书的出版社的city
    ret = models.Book.objects.filter(title="沙河异闻录").values("publisher__city")
    print(ret)

    # 查询书名是沙河异闻录的书的作者的爱好(夸两张表)
    ret = models.Book.objects.filter(title="沙河异闻录").values("authors__detail__hobby")
    print(ret)

Models 模块代码

from django.db import models


#
class Book(models.Model):
    title = models.CharField(max_length=32)
    publish_date = models.DateField(auto_now_add=True)
    price = models.DecimalField(max_digits=5, decimal_places=2)
    memo = models.TextField(null=True)
    # 创建外键,关联publish
    publisher = models.ForeignKey(to="Publisher")
    # 创建多对多关联author
    authors = models.ManyToManyField(to="Author")

    def __str__(self):
        return self.title


# 出版社
class Publisher(models.Model):
    name = models.CharField(max_length=32)
    city = models.CharField(max_length=32)

    def __str__(self):
        return self.name


# 作者
class Author(models.Model):
    name = models.CharField(max_length=32)
    age = models.IntegerField()
    phone = models.CharField(max_length=11)
    # 通过 through, through_fields来指定使用我创建的第三章表来构建多对多的关系
    books = models.ManyToManyField(to="Book", through="Author2Book", through_fields=("author", "book",))
    # 第一个字段: 多对多设置在哪一张表里,第三张表通过什么字段找到这张表,就把这个字段写在前面
    detail = models.OneToOneField(to="AuthorDetail")

    def __str__(self):
        return self.name


# 自己手动 创建作者和书关联的第三张表
# 此时 在ORM里面 作者和书就没有多对多的关系了
class Author2Book(models.Model):
    id = models.AutoField(primary_key=True)
    # 作者id
    author_id = models.ForeignKey(to="Author")
    # 书id
    book_id = models.ForeignKey(to="book")

    class Meta:
        # 建立唯一约束
        unique_together = ("author", "book")


# 作者详情
class AuthorDetail(models.Model):
    # 爱好
    hobby = models.CharField(max_length=32)
    # 地址
    addr = models.CharField(max_length=64)

笔记

day70 2018-05-14

1. 内容回顾
    1. ORM
        1. ORM常用字段和属性
            1. AutoField(primary_key=True)
            2. CharField(max_length=32)
            3. IntgerField()
            
            4. DateField()
            5. DateTimeField()
                1. auto_now_add    --> 创建的时候自动填充当前时间
                2. auto_now        --> 每次修改的时候自动把当前时间更新
                
        2. 关系字段
            1. ForeignKey(to="类名",related_name=“xx”)   --> 1对多  ,外键通常设置在多的那一边、
            2. ManyToMany(to="类名",related_name="xx")    --> 多对多,通常设置在正向查询多的那一边
            

        3. ORM一般操作
            1. 必知必会13条
                1. 返回QuerySet对象的
                    1. all()
                    2. filter()
                    3. values()
                    4. values_list()
                    5. exclude()
                    6. order_by()
                    7. reverse()
                    8. distinct()
                2. 返回具体对象的
                    1. get()
                    2. first()
                    3. last()
                3. 返回布尔值的
                    1. exists()
                4. 返回具体数值的
                    1. count()
            2. 单表查询的双下划线
                1. models.Book.objects.filter(id__gt=1)
                2. models.Book.objects.filter(id__in=[1,2,3])
                3. models.Book.objects.filter(id__range=[1,5])
                4. models.Book.objects.filter(title__contains="沙河")
                5. models.Book.objects.filter(title__icontains="沙河")
                6. models.Book.objects.filter(title__startswith="沙河")
                7. models.Book.objects.filter(title__endswith="沙河")
                8. models.Book.objects.filter(publish_date__year=2017)
                9. models.Book.objects.filter(publish_date__month=2)
            3. 外键的跨表查询
                1. 正向查找
                    1. 基于对象
                        book_obj = models.Book.object.get(id=1)
                        book_obj.publisher.name
                    
                    2. 基于双下划线的
                        models.Book.object.filter(id=1).values("publisher__name")
                    
                2. 反向查找(由出版社查书)
                    1. 基于对象
                        publisher_obj = models.Publisher.objects.get(id=1)
                        默认反向查找的时候是表名加_set
                            publisher_obj.book_set.all()
                        如果在外键中设置了related_name="books"
                            publisher_obj.books.all()
                    
                    2. 基于双下划线
                        models.Publisher.objects.filter(id=1).values("book__title")
                        如果配置了related_query_name="books"
                        models.Publisher.objects.filter(id=1).values("books__title")
                    
            4. 分组和聚合
                1. 聚合
                    from django.db.models import Avg, Sum, Max, Min, Count
                    models.Book.objects.all().aggregate(Avg("price"))
                2. 分组
                    book_list = models.Book.objects.all().annotate(author_num=Count("author"))
            
            5. F和Q
                1. 当需要字段和字段作比较的时候用F查询
                2. 当查询条件是 或 的时候 用Q查询,因为默认的filter参数都是且的关系
                
            6. 事务
                1. 保证数据的原子性操作!!!
            
            7. 执行原生的SQL语句(了解即可)

2. ORM 一对一
    1. 什么时候用一对一?
        当 一张表的某一些字段查询的比较频繁,另外一些字段查询的不是特别频繁
        把不怎么常用的字段 单独拿出来做成一张表 然后用过一对一关联起来
        
    2. 优势
            既保证数据都完整的保存下来,又能保证大部分的检索更快
            
    3. ORM中的用法
        OneToOneField(to="")

3. ORM 多对多的三种方式
    多对多的方式:
        1. ORM自动帮我创建第三张表
        
        
        2. 自己创建第三张表, 利用外键分别关联作者和书
            关联查询比较麻烦,因为没办法使用ORM提供的便利方法
            
        3. 自己创建第三张表,使用ORM 的ManyToManyFiled()
             使用此种方式创建多对多表的时候,没有 add() remove() 等方法
             
        
        
    我们应该用哪种?
        看情况:
            1. 如果你第三张表没有额外的字段,就用第一种
            2. 如果你第三张表有额外的字段,就用第三种或第一种
        
        
        相亲网站:
            Boy
                girls = ManyToManyField(to=“Girl")
            
            Girl
            
            约会记录:多对多
                id  boy_id girl_id  date

4. ORM查询的练习题
    1. 跨表查询
    2. 跨多张表查询
    
5. csrf简单用法

    什么是CSRF ?
        跨站请求伪造,
        
        
    问题:
        1. 钓鱼网站的页面和正经网站的页面对浏览器来说有什么区别? (页面是怎么来的?)
            钓鱼网站的页面是由 钓鱼网站的服务端给你返回的
            
            正经网站的网页是由 正经网站的服务端给你返回的
            
            
        2. Django中内置了一个专门处理csrf问题的中间件
            django.middleware.csrf.CsrfViewMiddleware
            
            这个中间件做的事情:
                1. 在render返回页面的时候,在页面中塞了一个隐藏的input标签
                
                用法:
                    我们在页面上 form表单 里面 写上 {% csrf_token %}
                    
                <input type="hidden" name="csrfmiddlewaretoken" value="8gthvLKulM7pqulNl2q3u46v1oEbKG7BSwg6qsHBv4zf0zj0UcbQmpbAdijqyhfE">
                
                2. 当你提交POST数据的时候,它帮你做校验,如果校验不通过就拒绝这次请求

                
作业:
    1. 多对多的三种情况 自己整理下笔记
    2. ORM查询练习 
        1. 正向查
        2. 反向查
        3. 跨表查
    3. 预习

预习:
http://www.cnblogs.com/liwenzhou/p/8343243.html
原文地址:https://www.cnblogs.com/zhen1996/p/9648124.html