Django - 模型層 - 下

1、多表 sql 

單表

多表
多對一 多對多 一對一

===============================================

一對多:
Book
id title price publish_id
1 php 100 1
2 python 200 1
3 go 300 2
Publish
id name email addr
1 人名出版社 @ 北京
2 沙河出版社 @ 沙河

一旦肯定是 一對多
怎麼創建一對多的關係?---》 關聯字段 ,建在‘多’的表中

查詢python這本書的出版社的郵箱
(子查詢)
select email from Publish where id = (
select publish_id from Book where title = 'python'
)

===============================================

多對多:(彼此一對多)
Book
id title price publish_id
1 php 100 1
2 python 200 1
3 go 300 2
Author
id name age addr
1 alex 34 beijing
2 egon 29 nanjing
Book2Author
id book_id author_id
1 2 1
2 2 2
3 3 2

alex 出版過的書籍名稱 (子查詢:以一個查詢的結果做爲下一個查詢的條件)
select title from Book where id in (
select book_id from Book2Author where author_id = (
select id from Author where name = 'alex'
)
)

===============================================

一對一:
Author
id name age authordetail_id(unique) (必定要加)
1 alex 34 1
2 egon 29 2
AuthorDetail (這個信息不常常查,爲了效率,擴展)
id addr gender tel gf_name
1 beijing male 110 小花
2 nanjing male 911 紅花

===============================================

總結:
一旦肯定是 一對多
怎麼創建一對多的關係?---》 關聯字段 ,建在‘多’的表中
一旦肯定是 多對多
怎麼創建多對多的關係?---》 建立第三張表(關聯表): id 和 兩個關聯字段
一旦肯定是 一對一
怎麼創建一對一的關係?---》 在兩張表中的任意一張表中創建關聯字段 + unique

Publish
Book
AuthorDetail
Author
Book2Author
=====================================================
create table publish(
id int primary key auto_increment,
name varchar(20)
);
create table book(
id int primary key auto_increment,
title varchar(20),
price decimal(8,2),
pub_date date,
publish_id int,
foreign key (publish_id) references publish(id)
);
create table authordetail(
id int primary key auto_increment,
tel varchar(20)
);
create table author(
id int primary key auto_increment,
name varchar(20),
age int,
authordetail_id int unique,
foreign key (authordetail_id) references authordetail(id)
);
create table book2author(
id int primary key auto_increment,
book_id int,
author_id int
);

=====================================================

2、建立模型

'''
Book
Publish
Author
AuthorDetail
Book2Author  會自定生成

Book    --   Publish        一對多
Author  --   AuthorDetail   一對一
Book    --   Author         多對多  Book2Author

'''
from django.db import models

# 做者詳情表
class AuthorDetail(models.Model):
    nid = models.AutoField(primary_key=True)
    birthday = models.DateField()
    telephone = models.BigIntegerField()
    addr = models.CharField(max_length=64)

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

    # 一對一 關係 這裏會生成一個字段 authordetail_id
    authordetail = models.OneToOneField(to='AuthorDetail',to_field='nid',on_delete=models.CASCADE)

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()

    # def __str__(self):  # 打印的時候 能夠打印出name
    #     return self.name

class Book(models.Model):
    nid = models.AutoField(primary_key=True)
    title = models.CharField(max_length=32)
    publishDate = models.DateField()
    price = models.DecimalField(max_digits=8,decimal_places=2)

    # 一對多 關係  # 這裏會生成一個 字段 publish_id
    publish = models.ForeignKey(to='Publish',to_field='nid',on_delete=models.CASCADE)
    '''
        publish_id int,
        foreign key (publish_id) references publish(id)
    '''

    # 多對多  # 這裏會生成第三張表 book_authors
    authors = models.ManyToManyField(to='Author')
    '''
        create table book_authors(
            id int primary key auto_increment,
            book_id int,
            author_id int
        );
    '''

    def __str__(self):
        return self.title

# 這裏生成第三張表的本質 # django 去寫不用咱們寫
# class Book2Author(models.Model):
#     nid = models.AutoField(primary_key=True)
#     book = models.ForeignKey(to='Book')  # 默認關聯主鍵
#     author = models.ForeignKey(to='Author')

'''
數據庫遷移
    python manage.py makemigrations
    python manage.py migrate
'''

'''  
注:
# 這就是django2.0問題  
    authordetail = models.OneToOneField(to='AuthorDetail',to_field='nid')
    TypeError: __init__() missing 1 required positional argument: 'on_delete'
解決辦法:
     authordetail = models.OneToOneField(to='AuthorDetail',to_field='nid',on_delete=models.CASCADE)
     publish = models.ForeignKey(to='Publish',to_field='nid',on_delete=models.CASCADE)
     
     須要加上 on_delete = models.CASCADE
     
     django1 默認加上了 on_delete 

'''

 

生成表以下:php

 

 

 

 

 

注意事項:html

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

3、多表 - 添加

from django.shortcuts import render,HttpResponse

from app01.models import *

def add(request):

    # 單表
    pub = Publish.objects.create(name='人名出版社',city='陝西',email='1234@qq.com')

    # =============================綁定一對多的關係==================================
    # 方式一  book -- publish
    book_obj = Book.objects.create(title='西遊記',publishDate='2012-12-1',price=100,publish_id=1)
    print(book_obj.title)       #  西遊記
    print(book_obj.publish)     # Publish object (1)
    print(book_obj.publish_id)  # 1

    # 方式二
    pub_obj = Publish.objects.filter(nid = 2).first()  # 對象
    book_obj = Book.objects.create(title='放風箏得人',publishDate='2012-1-2',price=150,publish=pub_obj)
    print(book_obj.title)      # 放風箏得人
    print(book_obj.price)      # 150
    print(book_obj.publish_id) # 3
    print(book_obj.publish)    # Publish object (3)
    print(book_obj.publish.name)    # 人名出版社
    print(book_obj.publish.city)    # 陝西

    # 查詢西遊記這本書,出版社對應的郵箱
    book_obj = Book.objects.filter(title='西遊記').first()
    print(book_obj.publish.email)  # yuan@163.com

# =============================綁定多對多的關係================================== book_obj = Book.objects.create(title='西遊記',publishDate='2009-11-20',price=100,publish_id=3) egon = Author.objects.get(name='egon') alex = Author.objects.get(name='alex') # Book_author django 本身加的 你沒辦法操做 加數據 # django 找到第三張表 添加數據 綁定多對多關係的API book_obj.authors.add(egon,alex) book_obj.authors.add(1,2) book_obj.authors.add(*[1,2]) # # 等效於 傳位置參數時 加 * # 解除 多對多的 關係 book_obj = Book.objects.filter(nid=4).first() book_obj.authors.remove(2) book_obj.authors.remove(1,2) book_obj.authors.remove(*[1,2]) # 全解除 book_obj.authors.clear() # 查詢出全部做者對象集合 print(book_obj.authors.all()) # #queryset [obj1.obj2] # 與這本書關聯的全部做者對象 # 查詢主鍵爲4 的書籍的 全部做者的名字 print(book_obj.authors.all().values('name')) # # <QuerySet [{'name': 'alex'}, {'name': 'egon'}]>

http://www.cnblogs.com/yuanchenqi/articles/8963244.htmlpython

http://www.cnblogs.com/yuanchenqi/articles/8978167.htmlgit

add(obj1[, obj2, ...])sql

create(**kwargs)數據庫

remove(obj1[, obj2, ...])django

clear()app

set()方法ide

 

 

4、查詢 - 基於對象 - 跨表

def add(request):

    # =============================基於對象的跨表查詢===================
    '''   
        一對多
            按字段 :publish (正向查詢按字段)
            book  ----》 publish
                 《---   
                 按表名 book_set.all() (反向查詢按表名)
    '''
    '''   
        一對一
            按字段 :authordetail (正向查詢按字段)
            author  ----》 authordetail
                   《---   
                  按表名 author   (反向查詢按表名)
    '''
    '''   
        多對多
            按字段 :authors (正向查詢按字段)
            book  ----》 author
                 《---   
               按表名 book_set.all()  (反向查詢按表名)
    '''
    '''
    (0.000) select city from publish where nid =(
       select publish_id from book where nid = 1;
     ) 
     ---------------基於對象的sql 子查詢-----------------
     SELECT 
         "app01_book"."nid", 
         "app01_book"."title", 
         "app01_book"."publishDate", 
         "app01_book"."price",
         "app01_book"."publish_id" 
     FROM "app01_book"
       WHERE 
         "app01_book"."nid" = 1 
       ORDER BY 
         "app01_book"."nid" ASC LIMIT 1; args=(1,)

    SELECT 
       "app01_publish"."nid",
       "app01_publish"."name", 
       "app01_publish"."city",
       "app01_publish"."email" 
     FROM "app01_publish" 
     WHERE 
     "app01_publish"."nid" = 1; args=(1,)

     '''

    # 正向查詢 按字段
    #  查詢主鍵爲1的書籍的出版社所在的城市
    book_obj = Book.objects.filter(nid = 1).first()
    print(book_obj.publish.city)  # beijing


    # 反向查詢 按表名
    # 查詢人名出版社出版的全部書籍的名稱
    publish_obj = Publish.objects.filter(name='人名出版社').first()
    print(publish_obj.book_set.all())  # queryset [book1,book2]
    # <QuerySet [<Book: Book object (1)>, <Book: Book object (2)>,...]>
    # for obj in publish_obj.book_set.all():
    #     print(obj.title)


    # 正向查詢
    # 查詢alex的手機號
    alex = Author.objects.filter(name='alex').first()
    print(alex.authordetail.telephone)


    # 反向查詢
    # 查詢手機號爲119 的做者名字
    ad = AuthorDetail.objects.filter(telephone=119).first()
    print(ad.author.name)


    # 正向查詢
    # 查詢三國演義全部做者的名字
    book_obj = Book.objects.filter(title='三國演義').first()
    print(book_obj.authors.all().values('name'))
    # <QuerySet [<Author: Author object (1)>, <Author: Author object (2)>]>
    # <QuerySet [{'name': 'alex'}, {'name': 'egon'}]>


    # 反向查詢
    # alex 出版過的全部書籍的名稱
    alex = Author.objects.filter(name='alex').filter()
    print(alex.book_set.all())
    print(alex.book_set.all().values('title'))
    # <QuerySet [<Book: 金瓶書>, <Book: 三國演義>]>
    # <QuerySet [{'title': '金瓶書'}, {'title': '三國演義'}]>

    # for obj in alex.book_set.all():
    #     print(obj.title)
    # 金瓶書
    # 三國演義

注意:函數

你能夠經過在 ForeignKey() 和ManyToManyField的定義中設置 related_name 的值來覆寫 FOO_set 的名稱。例如,若是 Article model 中作一下更改:

  publish = ForeignKey(Book, related_name='bookList')

那麼接下來就會如咱們看到這般:

  # 查詢 人民出版社出版過的全部書籍

  publish = Publish.objects.get(name = "人民出版社" )
  book_list = publish.bookList. all ()   # 與人民出版社關聯的全部書籍對象集合

5、查詢 - 基於雙下劃線(join)- 跨表

Django 還提供了一種直觀而高效的方式在查詢(lookups)中表示關聯關係,它能自動確認 SQL JOIN 聯繫。要作跨關係查詢,就使用兩個下劃線來連接模型(model)間關聯字段的名稱,直到最終連接到你想要的 model 爲止。

關鍵點:正向查詢按字段,反向查詢按表名。

def add(request):

    # =============================基於雙下劃線 (queryset)(sql 是join 查詢) 的跨表查詢===================
    # 不分一對一,一對多  正向查詢按字段 反向查詢 按表名
    # 1. 查詢人名出版社出版過的全部書籍的名稱和價格(一對多)
    ret = Publish.objects.filter(name='人名出版社').values('book__title','book__price')
    print(ret)
    '''
     <QuerySet [{'book__title': '紅樓夢1','book__price': Decimal('100.00')}, 
     {'book__title': '紅樓夢2', 'book__price': Decimal('100.00')}, 
     {'book__title': '紅樓夢3', 'book__price': Decimal('100.00')}, 
     {'book__title': '紅樓夢4', 'book__price': Decimal('100.00')}, 
     {'book__title': '紅樓夢5', 'book__price': Decimal('100.00')}, 
     {'book__title': '西遊記', 'book__price': Decimal('100.00')}]>

     SELECT 
         "app01_book"."title", 
         "app01_book"."price" 
     FROM 
         "app01_publish" 
     LEFT OUTER JOIN "app01_book" ON 
         ("app01_publish"."nid" = "app01_book"."publish_id") 
     WHERE 
         "app01_publish"."name" = '人名出版社1' LIMIT 21; args=('人名出版社1',)


     '''

    ret = Book.objects.filter(publish__name='人名出版社').values('title','price')
    print(ret)
    '''
      <QuerySet [{'title': '三國演義', 'price': Decimal('200.00')}, 
      {'title': '三國演義2', 'price': Decimal('200.00')}, 
      {'title': '金瓶mei', 'price': Decimal('200.00')}]>

      SELECT 
          "app01_book"."title", 
          "app01_book"."price" 
      FROM 
          "app01_book" 
      INNER JOIN "app01_publish" ON 
          ("app01_book"."publish_id" = "app01_publish"."nid")
      WHERE 
          "app01_publish"."name" = '人名出版社2' LIMIT 21; args=('人名出版社2',)


      '''

    # 2.查詢alex 出版過的全部書籍的名字(多對多) join 的sql 語句 正向按字段 反向按表名
    ret = Author.objects.filter(name='alex').values('book__title')
    # <QuerySet [{'book__title': '金瓶mei'}, {'book__title': '三國演義'}]>

    ret = Book.objects.filter(authors__name='alex').values('title')
    # <QuerySet [{'title': '金瓶mei'}, {'title': '三國演義'}]>

    # 3.混合使用
    # 查詢人名出版社出版過的全部書籍的名字以及做者的名字
    ret = Book.objects.filter(publish__name='人名出版社').values('title','authors__name')
    # <QuerySet [{'title': '三國演義', 'authors__name': 'alex'},{'title': '金瓶shu', 'authors__name': None}]>
    '''
         (0.000)SELECT 
             "app01_book"."title", 
             "app01_author"."name" 
         FROM 
             "app01_book" 
         INNER JOIN "app01_publish" ON 
             ("app01_book"."publish_id" = "app01_publish"."nid") 
         LEFT OUTER JOIN "app01_book_authors" ON 
             ("app01_book"."nid" = "app01_book_authors"."book_id") 
         LEFT OUTER JOIN "app01_author" ON 
             ("app01_book_authors"."author_id" = "app01_author"."nid") 
         WHERE 
             "app01_publish"."name" = '人名出版社2' LIMIT 21; args=('人名出版社2',)

     '''
    # 混合使用 手機號以151 開頭的做者出版過的全部書籍名稱以及出版社名稱
    ret = Book.objects.filter(authors__authordetail__telephone__startswith = '151').values('title','publish__name')
    print(ret)
    # <QuerySet [{'title': '金瓶mei', 'publish__name': '人名出版社2'}, {'title': '三國演義', 'publish__name': '人名出版社2'}]>
    '''
        (0.000) SELECT 
            "app01_book"."title", 
            "app01_publish"."name" 
        FROM "app01_book" 
        INNER JOIN "app01_book_authors" ON 
            ("app01_book"."nid" = "app01_book_authors"."book_id") 
        INNER JOIN "app01_author" ON 
            ("app01_book_authors"."author_id" = "app01_author"."nid") 
        INNER JOIN "app01_authordetail" ON 
            ("app01_author"."authordetail_id" = "app01_authordetail"."nid") 
        INNER JOIN "app01_publish" ON 
            ("app01_book"."publish_id" = "app01_publish"."nid") 
        WHERE 
            "app01_authordetail"."telephone" LIKE '151%' ESCAPE '\' LIMIT 21; args=('151%',)

    '''

 

注意:

反向查詢時,若是定義了related_name ,則用related_name替換表名,例如:

  publish = ForeignKey(Blog, related_name='bookList')

6、聚合查詢 - 分組查詢

def add(request):

    # =============================聚合查詢與分組查詢==============================
    # 1.計算全部圖書的平均價格
    # select avg(price) from book  (avg count sum min )
    from django.db.models import Avg,Max,Count

    ret = Book.objects.all().aggregate(c = Avg('price'))
    # {'price__avg': 160.0}  {'c': 160.0}

    ret = Book.objects.all().aggregate(Max('price'))
    # {'price__max': Decimal('200.00')}

    # 分組 統計每一本書 做者的個數   (group by)
    ret = Book.objects.all().annotate(c = Count('authors__name'))
    print(ret)  # 查詢出的結果 看不出 須要 循環 查看count
    for obj in ret:
        print(obj.title,obj.c)
    '''
       紅樓夢 0
       三國演義 2
       三國 0
    '''
    '''
     (0.000) SELECT 
         "app01_book"."nid", 
         "app01_book"."title", 
         "app01_book"."publishDate", 
         "app01_book"."price", 
         "app01_book"."publish_id", 
     COUNT("app01_author"."name") AS "c" 
     FROM "app01_book" 
     LEFT OUTER JOIN "app01_book_authors" ON 
         ("app01_book"."nid" = "app01_book_authors"."book_id") 
     LEFT OUTER JOIN "app01_author" ON 
         ("app01_book_authors"."author_id" = "app01_author"."nid") 
     GROUP BY 
         "app01_book"."nid", "app01_book"."title", "app01_book"."publishDate", "app01_book"."price", "app01_book"."publish_id"; args=()

     '''

    # 統計每個做者出版過的書籍最高價格
    ret = Author.objects.all().annotate(max_price = Max('book__price'))
    print(ret) # <QuerySet [<Author: Author object (1)>, <Author: Author object (2)>]>
    for obj in ret:
        print(obj.name,obj.max_price)
        # alex  300.00
        # egon 200.00

    # 每個出版社 出版過的書籍的平均價格
    ret = Publish.objects.all().annotate(avg_price = Avg('book__price')).values('name','avg_price')
    print(ret)
    '''
     <QuerySet [{'name': '人名出版社1', 'avg_price': 100.0}, 
      {'name': '人名出版社2', 'avg_price': 216.66666666666666},
      {'name': '人名出版社3', 'avg_price': 200.0}, 
      {'name': '人名出版社4', 'avg_price': None}, 
      {'name': '人名出版社5', 'avg_price': None}, 
      {'name': '人名出版社6', 'avg_price': None}]>

     '''
    for obj in ret:
        print(obj.name,obj.avg_price)
    '''
    人名出版社1 100.0
    人名出版社2 216.66666666666666
    人名出版社3 200.0
    人名出版社4 None
    '''

聚合

aggregate(*args, **kwargs)

    # 計算全部圖書的平均價格

     >>>  from  django.db.models  import  Avg
     >>> Book.objects. all ().aggregate(Avg( 'price' ))
     { 'price__avg' 34.35 }

aggregate()QuerySet 的一個終止子句,意思是說,它返回一個包含一些鍵值對的字典。鍵的名稱是聚合值的標識符,值是計算出來的聚合值。鍵的名稱是按照字段和聚合函數的名稱自動生成出來的。若是你想要爲聚合值指定一個名稱,能夠向聚合子句提供它。

  >>> Book.objects.aggregate(average_price=Avg('price'))

  { 'average_price' 34.35 }
 

若是你但願生成不止一個聚合,你能夠向aggregate()子句中添加另外一個參數。因此,若是你也想知道全部圖書價格的最大值和最小值,能夠這樣查詢:

  >>> from django.db.models import Avg, MaxMin

  >>> Book.objects.aggregate(Avg( 'price' ),  Max ( 'price' ),  Min ( 'price' ))
  { 'price__avg' 34.35 'price__max' : Decimal( '81.20' ),  'price__min' : Decimal( '12.99' )}

分組

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

統計每一本書的做者個數

  bookList=Book.objects.annotate(authorsNum=Count('authors'))

  for  book_obj  in  bookList:
     print (book_obj.title,book_obj.authorsNum)

統計每個出版社的最便宜的書

  publishList=Publish.objects.annotate(MinPrice=Min("book__price"))

  for  publish_obj  in  publishList:
     print (publish_obj.name,publish_obj.MinPrice)
annotate的返回值是querySet,若是不想遍歷對象,能夠用上valuelist:
queryResult= Publish.objects
            .annotate(MinPrice=Min("book__price"))
            .values_list("name","MinPrice")
print(queryResult)

統計每一本以py開頭的書籍的做者個數:
queryResult=Book.objects
           .filter(title__startswith="Py")
           .annotate(num_authors=Count('authors'))
統計不止一個做者的圖書:
queryResult=Book.objects
          .annotate(num_authors=Count('authors'))
          .filter(num_authors__gt=1)
根據一本圖書做者數量的多少對查詢集 QuerySet進行排序:
Book.objects.annotate(num_authors=Count('authors')).order_by('num_authors')
查詢各個做者出的書的總價格:
# 按author表的全部字段 group by
    queryResult=Author.objects
              .annotate(SumPrice=Sum("book__price"))
              .values_list("name","SumPrice") print(queryResult) # 按authors__name group by queryResult2=Book.objects.values("authors__name")
              .annotate(SumPrice=Sum("price"))
              .values_list("authors__name","SumPrice") print(queryResult2)

7、F查詢 - Q查詢

。。。 

http://www.cnblogs.com/yuanchenqi/articles/8963244.html

F查詢

在上面全部的例子中,咱們構造的過濾器都只是將字段值與某個常量作比較。若是咱們要對兩個字段的值作比較,那該怎麼作呢?

Django 提供 F() 來作這樣的比較。F() 的實例能夠在查詢中引用字段,來比較同一個 model 實例中兩個不一樣字段的值。

示例1:

查詢評論數大於收藏數的書籍

from django.db.models import F
models.Book.objects.filter(commnet_num__gt=F('keep_num'))

Django 支持 F() 對象之間以及 F() 對象和常數之間的加減乘除和取模的操做。

models.Book.objects.filter(commnet_num__lt=F('keep_num')*2)

修改操做也可使用F函數,好比將每一本書的價格提升30元

models.Book.objects.all().update(price=F("price")+30)

引伸:

若是要修改char字段咋辦?

如:把全部書名後面加上(初版)

>>> from django.db.models.functions import Concat
>>> from django.db.models import Value
>>> models.Book.objects.all().update(title=Concat(F("title"), Value("("), Value("初版"), Value(")")))

Q查詢

filter() 等方法中的關鍵字參數查詢都是一塊兒進行「AND」 的。 若是你須要執行更復雜的查詢(例如OR語句),你可使用Q對象

示例1:

查詢做者名是小仙女或小魔女的

models.Book.objects.filter(Q(authors__name="小仙女")|Q(authors__name="小魔女"))

你能夠組合& 和|  操做符以及使用括號進行分組來編寫任意複雜的Q 對象。同時,Q 對象可使用~ 操做符取反,這容許組合正常的查詢和取反(NOT) 查詢。

示例:查詢做者名字是小仙女而且不是2018年出版的書的書名。

>>> models.Book.objects.filter(Q(author__name="小仙女") & ~Q(publish_date__year=2018)).values_list("title")
<QuerySet [('番茄物語',)]>

查詢函數能夠混合使用Q 對象和關鍵字參數。全部提供給查詢函數的參數(關鍵字參數或Q 對象)都將"AND」在一塊兒。可是,若是出現Q 對象,它必須位於全部關鍵字參數的前面。

例如:查詢出版年份是2017或2018,書名中帶物語的全部書。

>>> models.Book.objects.filter(Q(publish_date__year=2018) | Q(publish_date__year=2017), title__icontains="物語")
<QuerySet [<Book: 番茄物語>, <Book: 香蕉物語>, <Book: 橘子物語>]>

 

8、關聯管理器

。。。 http://www.cnblogs.com/yuanchenqi/articles/8978167.html 

 ===================================================================

 http://www.cnblogs.com/liwenzhou/p/8660826.html
http://www.cnblogs.com /yuanchenqi/articles/8978167.html
https://docs.djangoproject.com/en/1.11/ref/models/querysets/

9、補充知識

1. 內容回顧
    1. 經常使用字段和字段參數
        1. 經常使用字段
            1. AutoField
                primary_key=True  # 設置爲主鍵
            2. CharField
                max_length=32     # 設置最大長度
            3. IntegerField
            4. BigInterField
            5. TextField
            6. DateField
                auto_now_add      # 建立這條數據時自動添加當前時間
                auto_now          # 每次更新的時候都自動更新時間

            7. DateTimeField
                同上
            ...

            經常使用參數:
                default=""        # 設置默認值
                null=True         # 能夠爲空
                unique=True       # 該字段在數據庫中不能重複

        2. 關係字段
            1. 外鍵  ForeignKey
                1. 外鍵一般放在多(一對多的多)的那一邊

                2. 參數
                    1. to=「表名」
                    2. related_name="xx"  用來替換反向查詢時的 表名_set
                    3. on_delete=models.CASCADE

            2. 一對一  OneToOneField
                1. 何時用  做者和做者詳情

            3. 多對多  ManyToManyField
                1. 三種方式
                    1.  不用ManyToMany
                    2.  自帶的ManyToMany, 自動幫我建立第三張表
                    3.  自定義第三張表


                        # 相親網站
                        # 男孩
                        class Boy(models.Model):
                            name = models.CharField(max_length=32)
                            girls = models.ManyToManyField(to='Girl', through="Info", through_fields=("boy1", "girl1"))  # 能知足多對多的關係,可是少點東西


                        # 女孩
                        class Girl(models.Model):
                            name = models.CharField(max_length=32)
                            # through_fields=('field1', 'field2'),
                            # 你把多對多建在那個表,field1就是這個表的名字
                            # field2是你目標表的表名
                            # boys = models.ManyToManyField(to=Boy, through="Info", through_fields=("girl1", "boy1"))  # 能知足多對多的關係,可是少點東西


                        # 約會記錄
                        # 男孩1      女孩1
                        # 男孩2      女孩1
                        # 男孩1      女孩2


                        # 本身建立第三張表, 記錄約會的記錄
                        class Info(models.Model):
                            girl1 = models.ForeignKey(to=Girl)
                            boy1 = models.ForeignKey(to=Boy)

                            # 其餘補充字段
                            date = models.DateTimeField(auto_now_add=True)


        3. 元信息
            # 定義元信息
            class Meta:
                ordering = ("price", )  # 默認按照價格排序
                db_table = "book"  # 指定在數據庫中建立表的表名
                unique_together = ("title", "price")  # 多字段聯合惟一

    2. ORM操做
        1. 單表13個    --> 永遠不要懷疑本身!要自信!!!  混亂即階梯!

            返回QuerySet的有:
                1. all()
                3. filter()
                4. exclude()

                7. values_list()  --> 元祖
                8. values()       --> 字典
                9. order_by()
                10. reverse()
                13. distinct()
            返回對象:
                2. get()
                5. first()
                6. last()
            返回數字:
                11. count()
            返回布爾值:
                12. exist()

            雙下劃線:
                id__lt=10
                ...

            跨表的雙下劃線:
                models.Book.objects.filter(author__name=「小仙女")
                models.Book.objects.filter(author__detail__age=18)
                ...

        2. 關係表的操做
            1. 外鍵
                1. 正向查找         --> 具體的對象
                    直接找
                2. 反向查找         --> 對象的列表
                    .表名(小寫)_set.all()
            2. 多對多
                1. 正向查找
                    直接找          --> 對象的列表

                2. 反向查找
                    表名_set.all()  --> 對象的列表

                多對多才有的:
                    .create()    --> author_obj.books.create(title="番茄物語")
                    .add(1,2,3)
                    .clear()     -->清空
                    .remove(1)
                    .set([1,2,3]/QuerySet對象)
        3.聚合和分組
            1. aggregate()
            2. annotate()     ---> GROUP BY
        4. F和Q
            1. 同一張表的不一樣列做比較
            2. 多個條件作查詢

        5. 事務
                try:
                    from django.db import transaction
                    with transaction.atomic():
                        new_publisher = models.Publisher.objects.create(name="新華出版社CCC")
                        # 再去建立新書
                        # new_book = models.Book.objects.create(title="新華字典", price=3.5, publisher_id=new_publisher.id)
                        new_book = models.Book.objects.create(titl="新華字典CCC", price=3.5, publisher=new_publisher)
                except Exception as e:
                    print(str(e))

        6. 如何在Python腳本加載Django環境
            import os
            os.environ.setdefault("DJANGO_SETTINGS_MODULE", "項目名.settings")
            import django
            django.setup()

            # 引用Django內部的變量
補充知識

事務

import os

if __name__ == '__main__':
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "BMS.settings")
    import django
    django.setup()

    import datetime
    from app01 import models

    try:
        from django.db import transaction
        with transaction.atomic():
            new_publisher = models.Publisher.objects.create(name="火星出版社")
            models.Book.objects.create(title="橘子物語", publish_date=datetime.date.today(), publisher_id=10)  # 指定一個不存在的出版社id
    except Exception as e:
        print(str(e))

 

Django終端打印SQL語句

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'console':{
            'level':'DEBUG',
            'class':'logging.StreamHandler',
        },
    },
    'loggers': {
        'django.db.backends': {
            'handlers': ['console'],
            'propagate': True,
            'level':'DEBUG',
        },
    }
}

 

在Python腳本中調用Django環境

import os

if __name__ == '__main__':
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "BMS.settings")
    import django
    django.setup()

    from app01 import models

    books = models.Book.objects.all()
    print(books)

orm參數

https://www.cnblogs.com/liwenzhou/p/8688919.html 

相關文章
相關標籤/搜索