博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ORM一对一和多对多创建的3种方式
阅读量:4956 次
发布时间:2019-06-12

本文共 8052 字,大约阅读时间需要 26 分钟。

 

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="")

   from app01 import models     # 一对一的查询     # author_obj = models.Author.objects.get(id=1)     # obj = author_obj.detail     # print(obj.hobby, obj.addr)

3. ORM 多对多的三种方式

  多对多的方式:
    1. ORM自动帮我创建第三张表  

class Publisher(models.Model):     name = models.CharField(max_length=32)     city = models.CharField(max_length=32)     def __str__(self):         return self.name # 书 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)     # 创建外键,关联publish     publisher = models.ForeignKey(to="Publisher")     def __str__(self):         return self.title # 作者 class Author(models.Model):     name = models.CharField(max_length=32)     age = models.IntegerField()     phone = models.IntegerField()     books = models.ManyToManyField(to="Book", related_name="authors")     detail = models.OneToOneField(to="AuthorDetail")     def __str__(self):         return self.name # 作者详情 class AuthorDetail(models.Model):     # 爱好     hobby = models.CharField(max_length=32)     # 地址     addr = models.CharField(max_length=128)
if __name__ == '__main__':     os.environ.setdefault("DJANGO_SETTINGS_MODULE", "ormday70.settings")     import django     django.setup()     # 在app01 里面 查询 id是1的作者关联的书     from app01 import models     ret = models.Author.objects.get(id=1).books.all()     # 从作者关联的书里面移除id是1的书     models.Author.objects.get(id=1).books.remove(1)     print(ret)     print("app01".center(80, "-"))
 

    2. 自己创建第三张表, 利用外键分别关联作者和书

      关联查询比较麻烦,因为没办法使用ORM提供的便利方法

# 出版社 class Publisher(models.Model):     name = models.CharField(max_length=32)     city = models.CharField(max_length=32)     def __str__(self):         return self.name # 书 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)     # 创建外键,关联publish     publisher = models.ForeignKey(to="Publisher")     def __str__(self):         return self.title # 作者 class Author(models.Model):     name = models.CharField(max_length=32)     age = models.IntegerField()     phone = models.IntegerField()     detail = models.OneToOneField(to="AuthorDetail")     def __str__(self):         return self.name # 自己动手 创建作者和书关联的第三张表 # 此时 在ORM层面 作者和书就没有多对多的关系了 class Author2Book(models.Model):     id = models.AutoField(primary_key=True)     # 作者id     author = models.ForeignKey(to="Author")     # 书id     book = 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=128)
# 在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)
    3. 自己创建第三张表,使用ORM 的ManyToManyFiled()  

      使用此种方式创建多对多表的时候,没有 add() remove() 等方法

 

# 出版社 class Publisher(models.Model):     name = models.CharField(max_length=32)     city = models.CharField(max_length=32)     def __str__(self):         return self.name # 书 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)     # 创建外键,关联publish     publisher = models.ForeignKey(to="Publisher")     def __str__(self):         return self.title # 作者 class Author(models.Model):     name = models.CharField(max_length=32)     age = models.IntegerField()     phone = models.IntegerField()     # 通过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 = models.ForeignKey(to="Author")     # 书id     book = models.ForeignKey(to="Book")     # memo     memo = models.CharField(max_length=64, null=True)     class Meta:         # 建立唯一约束         unique_together = ("author", "book") # 作者详情 class AuthorDetail(models.Model):     # 爱好     hobby = models.CharField(max_length=32)     # 地址     addr = models.CharField(max_length=128)
 # 在app03 里面 查询 id是1的作者关联的书       from app03 import models       ret = models.Author.objects.get(id=1).books.all()       print(ret)       # 从作者关联的书里面移除id是1的书       # 没有django ORM 封装的那些快捷方式了,我们要自己亲自改第三张表       models.Author2Book.objects.get(author_id=1, book_id=1).delete()

 

 

我们应该用哪种?

看情况:
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数据的时候,它帮你做校验,如果校验不通过就拒绝这次请求

 

转载于:https://www.cnblogs.com/louzi/p/9329830.html

你可能感兴趣的文章
数据库特定SQL分页pdf
查看>>
About Face 3:交互设计精髓pdf
查看>>
jsday8
查看>>
DFS之城堡问题
查看>>
Implement Stack using Queues
查看>>
理解javascript中的回调函数(callback)【转】
查看>>
hdu 6113 度度熊的01世界
查看>>
poj 2441 Arrange the Bulls
查看>>
Selenium Webdriver——处理Table
查看>>
CakePHP 2.x CookBook 中文版 第七章 模型 之 关联:将模型连接在一起
查看>>
计算机技术:编程语言:Python
查看>>
BZOJ 1637: [Usaco2007 Mar]Balanced Lineup
查看>>
CSS
查看>>
BZOJ3990 排序
查看>>
商城签到功能的设计与实现
查看>>
py定义变量-循环-条件判断
查看>>
python 练习 16
查看>>
[Spring Data MongoDB]学习笔记--注册一个Mongo实例
查看>>
Python——电子邮件、Internet协议相关模块
查看>>
MySQL innodb_flush_method 【转载】
查看>>