天天看點

Django- ORM操作

一 、查詢

1、一對多

執行個體一(正向,用字段):

# 查詢紅樓夢的出版社名稱
#方式1:
ret=Book.objects.filter(title="紅樓夢").values("publish__name")           
print(ret)                                                          
# <QuerySet [{'publish__name': '北京出版社'}]>
# 方式2:
res=Publish.objects.filter(book__title="紅樓夢").values("name")          
print(res)                                                          
#<QuerySet [{'name': '北京出版社'}]>
           

執行個體二(反向,用表名):

# 查詢沙河出版社出版過的書籍名稱
#方式1:
ret=Publish.objects.filter(name="沙河出版社").values("book__title")
print(ret)                                                         
#<QuerySet [{'book__title': '金品梅2'}, {'book__title': '金品梅3'}]>
#方式2:
res=Book.objects.filter(publish__name="沙河出版社").values("title")
print(res)                                                         
#<QuerySet [{'title': '金品梅2'}, {'title': '金品梅3'}]>
           

2、多對多

# 查詢紅樓夢所有作者的名字
ret=Book.objects.filter(title="紅樓夢").values("authors__name")
print(ret)                                                       
#<QuerySet [{'authors__name': 'alex'}, {'authors__name': 'egon'}]>
           
#查詢alex出版過的所有書籍
ret=Author.objects.filter(name="alex").values("book__title")
print(ret)                                                       
#<QuerySet [{'book__title': '金品梅2'}, {'book__title': '紅樓夢'}]>
           

3、一對一

# 查詢位址在沙河并且email是123的作者的名字
ret=AuthorDetail.objects.filter(adrr="沙河",email=123).values("author__name")
print(ret)                                                        
#<QuerySet [{'author__name': 'alex'}]>
           
# 查詢alex作者的adrr位址
ret = Author.objects.filter(name="alex").values("authordetail__adrr")
print(ret)                                                      
#<QuerySet [{'authordetail__adrr': '沙河'}]>
           

執行個體三(綜合執行個體):

#email以456開頭的作者出版過的所有書籍名稱以及出版社名稱  ret=Book.objects.filter(authors__authordetail__email__startswith="456").values("title","publish__name")
print(ret)
           

  總結,在上一章的對象查詢中,我們可以總結為所有的查詢是基于一個models對象,而本節中雙下劃線查詢均是基于queryset對象進行的!反向查詢使用的表名同樣必須為小寫。

二、聚合函數(aggregate)

  

aggregate()

QuerySet

的一個終止子句,意思是說,它傳回一個包含一些鍵值對的字典。鍵的名稱是聚合值的辨別符,值是計算出來的聚合值。鍵的名稱是按照字段和聚合函數的名稱自動生成出來的。如果你想要為聚合值指定一個名稱,可以向聚合子句提供它。如下例:

#查詢所有書籍的平均價格
# 執行個體1:
ret=Book.objects.all().aggregate(Avg("price"))
print(ret)                                                         
#{'price__avg': 172.66666666666666}
# 執行個體2:
res = Book.objects.all().aggregate(avgPrice=Avg("price"))
print(res)                                                         
#{'avgPrice': 172.66666666666666}
           

  如果你希望生成不止一個聚合,你可以向

aggregate()

子句中添加另一個參數。是以,如果你也想知道所有圖書價格的最大值和最小值,可以這樣查詢:

# 查詢所有書籍的平均價格、價格最大值、價格最小值
ret = Book.objects.all().aggregate(Avg("price"),Min("price"),Max("price"))
print(ret)                         
#{'price__avg': 172.66666666666666, 'price__min': Decimal('123.00'), 'price__max': Decimal('230.00')}
           

  以上執行個體中需要按照如下方式引入相應的子產品方法:

``from

django.db.models ``import

Avg, ``Max``, ``Min

三、分組函數(annotate)

  annotate()為調用的

QuerySet

中每一個對象都生成一個獨立的統計值(統計方法用聚合函數)。

  執行個體1:查詢每一個出版社出版過的書籍個數

ret=Publish.objects.all().annotate(num=Count("book__title"))     #可以了解為每一個出版社對象增加一個num字段,該字段值是通過聚合函數聯表求得
for pub_obj  in ret:
    print(pub_obj.name,pub_obj.num)
           

 annotate的傳回值是querySet,如果不想周遊對象,可以用上values_list,如下:

ret = Publish.objects.all().annotate(num=Count("book__title")).values_list("name","num")
print(ret)                                                       
#<QuerySet [('人民出版社', 0), ('沙河出版社', 2), ('北京出版社', 1)]>
           

  執行個體2:查詢每一本書的作者個數

ret=Book.objects.all().annotate(counts=Count("authors__nid")).values("title","counts")
print(ret)        
#<QuerySet [{'title': '金品梅2', 'counts': 2}, {'title': '金品梅3', 'counts': 2}, {'title': '紅樓夢', 'counts': 2}]>
           

二、方法

python生成requirements.txt項目依賴環境

進入python 項目目錄下,執行指令

pip freeze > requirements.txt
           

生成的requirements.txt 裡面就記錄了目前所有已經安裝的依賴包以及版本号

然後将生成的requirements.txt 拷貝到需要安裝同樣依賴環境的伺服器上

最後執行指令

pip install -r requirements.txt
           

就可以将所有依賴一次安裝完成

django中所有的指令

下載下傳django

pip install django==1.11.25 -i 源

建立django項目

django-admin startproject 項目名

啟動項目

切換到項目目錄下

python manage.py runserver # 127.0.0.1:8000

python manage.py runserver 80 # 127.0.0.1:80

python manage.py runserver 0.0.0.0::80 # 0.0.0.0::80

建立app

python manage.py startapp app名稱

資料庫遷移的指令

python manage.py makemigrations # 檢測已經注冊app下的models變更記錄

python manage.py migrate # 将變更記錄同步到資料庫中
           

request

request.POST    #  POST送出的資料 {}    urlencode編碼
request.GET     #   url上攜帶的參數  ?id=1  {id:1}
request.method  #  請求方法  GET POST
request.path_info  # 路徑資訊  不包含IP和端口 也不包含查詢參數
request.FILES   # 上傳的檔案 enctype='form-data'
request.session  # {}  session 
request.COOKIES  # cookie  
request.META   # 請求頭的資訊  HTTP_  小寫——》  大寫  - ——》 _
request.body  # 請求體  原始資料

request.get_full_path()  #  完整的路徑資訊 不包含IP和端口 包含查詢參數
request.is_ajax()  # 是否是ajax請求
request.get_signed_cookie(key,salt,defalut='')
           

response

HttpResponse('字元串')   #  字元串
JsonResponse({})   JsonResponse([],safe=False) 
render(request,'模闆檔案的路徑',{})   # 傳回頁面 已經替換好了
redirect('位址或者URLname')   # 重定向  響應頭Location:位址 301 302 
TemplateResponse(request,'模闆檔案的路徑',{})  # 後續在調用render方式進行渲染

           

ORM

正向查詢

有關聯關系的哪一方成為正向--也就是多的哪一方 -- 屬性查詢
           

反向查詢

沒有關聯關系的哪一方成為反向--也就是一的哪一方 -- 表名小寫
           

正向和反向查詢

正向 ----> 關聯字段在目前表中,從目前表向外查叫正向

反向 —> 關聯字段不在目前表中,當目前表向外查叫反向

正向通過字段,反向通過表名查

一對一 OneToOneField

# 一個文章詳情表一對一關聯文章表,相當于Foreignkey 加unique
class Article(models.Model):
	nid = models.AutoField(primary_key=True)
	desc = models.CharField(max_length=255)
	
class ArticleDetail(models.Model):
    """
    文章詳情表
    """
    nid = models.AutoField(primary_key=True)
    content = models.TextField()
    article = models.OneToOneField(to="Article", to_field="nid",on_delete=models.DO_NOTHING)
           

正向:

1、基于對象:obj.(外鍵).屬性

ArticleDetail_obj = models.ArticleDetail.objects.filter(pk=pk).first()
ArticleDetail_obj.article.desc
           

2、基于字段跨表查詢:外鍵__屬性

models.ArticleDetail.objects.filter(pk=2).values("article__desc")
           

反向:從詳情查文章

1、基于對象:obj.(表名小寫).屬性

article_obj = models.Article.objects.filter(pk=pk).first()
article_obj.articledetail.content
           

2、基于字段跨表查詢:表名小寫__屬性

models.Article.objects.filter(id=1).values('articledetail__content')
           

一對多 ForeignKey

book – > publish :一個出版社有多個書

class Publish(models.Model):
    nid = models.AutoField(primary_key=True)
    name=models.CharField( max_length=32)

class Book(models.Model):
    nid = models.AutoField(primary_key=True)
    title = models.CharField( max_length=32)
    # 與Publish建立一對多的關系
	publish=models.ForeignKey(to="Publish",to_field="nid",on_delete=models.CASCADE)

           

1、基于字段:obj.(外鍵).屬性

book_obj = models.Book.objects.filter(title='紅樓夢').first()
book_obj.publish.name
           

反向:obj.(表名小寫_set).all()

1、set查詢

publish_obj=models.Publish.objects.filter(name="教育").first()
books = publish_obj.book_set.all()
for book in books:
	print(book.title)
           

多對多 ManyToManyField

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 Author(models.Model):
    nid = models.AutoField(primary_key=True)
    name=models.CharField( max_length=32)
    age=models.IntegerField()
    
class Book(models.Model):
    nid = models.AutoField(primary_key=True)
    title = models.CharField(max_length=32)

    # 與Author表建立多對多的關系,ManyToManyField可以建在兩個模型中的任意一個,自動建立第三張表
    authors=models.ManyToManyField(to='Author',)

           

1、基于字段:obj.(外鍵).all()

book_obj = models.Book.objects.filter(title="python教程").first()
authors = book_obj.authors.all()
for author in authors:
	print(author.name,author.age)
           
author_obj = models.Author.objects.filter(name="moke").first()
books = author_obj.book_set.all()
for book in books:
	print(book.title)
           

2、related_name查詢

author_obj.related_name.all()
           

常用字段

AutoField       自增  primary_key = True主鍵

IntegerField    整形 -21億  - 21億

BooleanField     布爾值類型

NullBooleanField  可以為空的布爾值

CharField      字元串

TextField      文本類型

DateTimeField   日期+加時間

DateField     日期格式
    
TimeField     時間格式

FloatField    浮點型

DecimalField(max_difits=6,decimal_piaces=3)   十進制小數
           

字段參數

null = True    資料庫中該字段可以為空

black = True    使用者輸入可以為空

default         預設值

db_index=True 索引

unique    唯一限制

verbose_name   顯示的名稱

choices   可選擇的參數
           

必知必會十三條

傳回對象清單  QuerySet
all()      所有的對象
filter()    擷取滿足條件的所有對象
exclude()   擷取不滿足條件的所有對象
order_by()   排序   - 
reverse()   反轉
values()    [ {}  ]
values_list()    [ ()  ]
distinct()   去重  不能按照字段去重

傳回對象
get()    擷取有且唯一的對象
first()
last()

傳回數字
count

傳回布爾值
exists() 
           

單表的雙下劃線

字段__條件
__gt   大于
__gte   大于等于
__lt  小于
__lte   小于等于
__in= []    成員判斷
__range = [3,6]  範圍  3-6

__contains =''    包含   like
__icontains =''   忽略大小寫

__startswith =''   以什麼開頭
__istartswith =''   以什麼開頭


__endswith =''   以什麼結尾
__endswith =''   以什麼結尾


__year ='2019'  

__isnull = True   字段值為null