1. 程式人生 > >django模型層2 多表操作

django模型層2 多表操作

digits 名稱 alt req 最大 app 聚合 員工 postgre

1.多表操作:

  1.創建模型:

實例:我們來假定下面這些概念,字段和關系

作者模型:一個作者有姓名和年齡。

作者詳細模型:把作者的詳情放到詳情表,包含生日,手機號,家庭住址等信息。作者詳情模型和作者模型之間是一對一的關系(one-to-one)

出版商模型:出版商有名稱,所在城市以及email。

書籍模型: 書籍有書名和出版日期,一本書可能會有多個作者,一個作者也可以寫多本書,所以作者和書籍的關系就是多對多的關聯關系(many-to-many);一本書只應該由一個出版商出版,所以出版商和書籍是一對多關聯關系(one-to-many)。

模型建立如下:

from django.db import
models # Create your models here. class Author(models.Model): nid = models.AutoField(primary_key=True) name=models.CharField( max_length=32) age=models.IntegerField() # 與AuthorDetail建立一對一的關系 authorDetail=models.OneToOneField(to="AuthorDetail",on_delete=models.CASCADE)
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) # 與Publish建立一對多的關系,外鍵字段建立在多的一方 publish=models.ForeignKey(to="Publish",to_field="nid",on_delete=models.CASCADE) # 與Author表建立多對多的關系,ManyToManyField可以建在兩個模型中的任意一個,自動創建第三張表 authors=models.ManyToManyField(to=Author,)

技術分享圖片

技術分享圖片

技術分享圖片

技術分享圖片

技術分享圖片

註意事項:

  • 表的名稱myapp_modelName,是根據 模型中的元數據自動生成的,也可以覆寫為別的名稱  
  • id 字段是自動添加的
  • 對於外鍵字段,Django 會在字段名上添加"_id" 來創建數據庫中的列名
  • 這個例子中的CREATE TABLE SQL 語句使用PostgreSQL 語法格式,要註意的是Django 會根據settings 中指定的數據庫類型來使用相應的SQL 語句。
  • 定義好模型之後,你需要告訴Django _使用_這些模型。你要做的就是修改配置文件中的INSTALL_APPSZ中設置,在其中添加models.py所在應用的名稱。
  • 外鍵字段 ForeignKey 有一個 null=True 的設置(它允許外鍵接受空值 NULL),你可以賦給它空值 None 。

  2.添加數據庫

操作前先簡單的錄入一些數據:

publish表:

技術分享圖片

author表:

技術分享圖片

authordetail表:

技術分享圖片

一對多

1 2 3 4 5 6 方式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 對象添加到被關聯對象集合中。   =======    book_obj.authors.add(*[])

多對多關系其它常用API:

將某個特定的對象從關聯的對象集合中去除:

  book_obj.authours.remove()

清空被關聯的對象集合:

  book_obj.authors.clrar()

先清空,在設置:

  book_obj.authors.set()

詳情請點我!!!

所有的查詢:

def select(request):
################基於對象的跨表查詢##############
# 1.1對多
# 1.查詢linex這本書出版社的名字和郵箱


# book = Book.objects.filter(title="linex").first()
# # pub_obj = Publish.objects.first(nid=book.publish_id).first()
# # print(pub_obj.name)
# print(book.publish.name)
# print(book.publish.email)
# 2
# 查詢人民教育出版社出版的所有的書籍的名稱
# pub_obj=Publish.objects.get(name="人民教育出版社")
# print(pub_obj.book_set.all().values("title"))

####### 多對多 ##########
# 查詢linex這本書籍的作者的年齡
# book=Book.objects.filter(title="linex").first()
# ret=book.authors.all().values("age")
# print(ret)
# #查詢alex出版過的所有的書籍名稱
# alex=Author.objects.filter(name="alex").first()
# print(alex.book_set.all())
# alex=Author.objects.filter(name="alex").first()
# print(alex.book_set.all())

####### 一對一 ##########
# 查詢alex的手機號
# alex=Author.objects.filter(name="alex").first()
# print(alex.ad.tel )
# alex=Author.objects.filter(name="alex").first()
# print(alex.ad.tel)
# # 查詢手機號為110的作者的名字
# ad=AuthorDetail.objects.filter(tel=110).first()
# print(ad.author.name)

#########基於雙下劃線的跨表查詢(基於join實現的)#########
# 1
# 查詢linex這本書出版社的名字
# ret=Book.objects.filter(title="linex").values("publish__name")
# print(ret)
# pub_obj=Publish.objects.filter(book__title=‘linex‘).values("name")
# print(pub_obj)
# ret=Book.objects.filter(title="linex").values("publish__name")
# print(ret)
# ret=Publish.objects.filter(book__title="linex").values("name")
# print(ret)
# 2
# 查詢人民教育出版社出版的所有的書籍的名稱
# ret=Book.objects.filter(publish__name="人民教育出版社").values("title")
# print(ret)
# ret=Publish.objects.filter(name="人民教育出版社").values("book__title")
# print(ret)
# 3 查詢python這本書籍的作者的年齡
# ret=Book.objects.filter(title="linex").values("authors__age")
# print(ret)
# ret=Author.objects.filter(book__title="linex").values("age")
# print(ret)
# ret=Book.objects.filter(title="linex").values("authors__age")
# print(ret)
# ret=Author.objects.filter(book__title="linex").values("age")
# print(ret)
#
# 4 查詢alex出版過的所有的書籍名稱
# ret=Book.objects.filter(authors__name="alex").values("title")
# print(ret)
# ret=Author.objects.filter(name="alex").values("book__title")
# print(ret)
# 5 查詢alex的手機號
# ret=Author.objects.filter(name="alex").values("ad__tel")
# print(ret)
# ret=AuthorDetail.objects.filter(author__name="alex").values("tel")
# print(ret)
# 6 查詢手機號為110的作者的名字
# ret=Author.objects.filter(ad__tel=110).values("name")
# print(ret)
# ret=AuthorDetail.objects.filter(tel=110).values("author__name")
# print(ret)
# 查詢人民教育出版社出版過的所有書籍的名字以及作者的姓名
# ret=Publish.objects.filter(name="人民教育出版社").values("book__title","book__authors__name")
# print(ret)
# ret=Publish.objects.filter(name="人民教育出版社").values("book__title","book__authors__name")
# print(ret)
# ret=Book.objects.filter(publish__name="人民教育出版社").values("title","authors__name")
# print(ret)
# ret=Book.objects.filter(publish__name="人民教育出版社").values("title","authors__name")
# print(ret)
# 手機號以110開頭的作者出版過的所有書籍名稱以及出版社名稱
# ret=AuthorDetail.objects.filter(tel__startswith=110).values("author__book__title","author__book__publish__name")
# print(ret)
# ret=AuthorDetail.objects.filter(tel=110).values("author__book__title","author__book__publish__name")
# print(ret)
# ret=Book.objects.filter(authors__ad__tel=110).values("title","publish__name")
# print(ret)
# ret=Author.objects.filter(ad__tel=110).values("book__title","book__publish__name")
# print(ret)
################ 聚合 分組 ################
from django.db.models import Avg,Max,Min,Count
# 查詢所有書籍的平均價格
# ret=Book.objects.all().aggregate(Avg("price"))
# print(ret)
# # 查詢所有書籍的個數
# ret=Book.objects.all().aggregate(c=Count(1))
# print(ret)
# 查詢書籍表每一個出版社id以及對應的書籍個數
# ret=Book.objects.annotate(c=Count(1)).values("publish_id","c")
# print(ret)
# 查詢每一個部門的名稱以及對應員工的平均薪水
# ret=Emp.objects.annotate(c=Avg("salary")).values("dep","c")
# print(ret)
# ret=Emp.objects.values("dep").annotate(c=Avg("salary"))
# print(ret)
# 查詢每一個省份的名稱以及對應的員工最大年齡
# ret= Emp.objects.values("pro").annotate(c=Max("age"))
# print(ret)
# 跨表分組查詢
# 查詢每一個出版社的名稱以及對應的書籍平均價格
# ret=Publish.objects.annotate(c=Avg("book__price")).values("c","name")
# print(ret)
# 查詢每一個作者的名字以及出版的書籍的最高價格
# ret=Author.objects.annotate(M=Max("book__price")).values(‘M‘,"name")
# print(ret)
# 查詢每一個書籍的名稱以及對應的作者的個數
# ret=Book.objects.annotate(a=Count("authors")).values("title","a")
# print(ret)
# 4
# 查詢作者數不止一個的書籍名稱以及作者個數
# ret=Book.objects.annotate(c=Count("authors__name")).filter(c__gt=1).values("title","c")
# print(ret)
# ret=Book.objects.annotate(c=Count("authors__name")).filter(c__gt=1).values("title","c")
# print(ret)
# 5 根據一本圖書作者數量的多少對查詢集 QuerySet進行排序
# ret=Book.objects.annotate(c=Count("authors__name")).order_by("c")
# print(ret)
# 6 統計每一本以py開頭的書籍的名稱以及作者個數
# ret=Book.objects.filter(title__startswith="li").annotate(c=Count("authors__name"))
# print(ret)
# ret=Book.objects.filter(title__startswith="li").annotate(c=Count("authors__name")).values("title","c")
# print(ret)
################ F 與 Q ################
from django.db.models import F, Q
# # 查詢評論數大於100的所有的書籍名稱
# ret=Book.objects.filter(comment_count__gt=2000).values("title")
# print(ret)
# # 查詢評論數大於2倍點贊數的所有的書籍名稱
# ret=Book.objects.filter(comment_count__gt=F("poll_count")*2)
# print(ret)
# 給每一本書籍的價格提升100
ret=Book.objects.all().update(price=100+F("price"))
print(ret)





return HttpResponse("ok")

  

django模型層2 多表操作