djangoのクロステーブルクエリとレコードを追加するコードの例


テーブルを作成
書籍モデル:書籍には書名と出版日があり、一冊の本には複数の作者がいるかもしれません。一人の作者も複数の本を書くことができます。だから、著者と書籍の関係は多くの関連関係にあります。
本は出版社だけで出版されるべきです。出版社と本は一対の多関系です。
ペアの関係を作成します。OneToOne(バインディング関係のテーブル名)
ペアの多い関係を作成します。ForeignKey(「関係を結合するテーブル名」)
マルチペアの関係を作成する:ManyToMany(「関係を結びつける表名」)  自動的に3枚目の表を作成します。

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

  #         ,           
  #      publish_id,  django         _id
  publish = models.ForeignKey("Publish") #foreignkey(  )        
  # publish             
  authorlist = models.ManyToManyField("Author") #         
  def __str__(self): #__str__               ,          
    return self.title
class Publish(models.Model):
  #  id               id
  name =models.CharField(max_length=32)
  addr = models.CharField(max_length=32)

  def __str__(self):
    return self.name
class Author(models.Model):
  name = models.CharField(max_length=32)
  age = models.IntegerField()

class AuthorDeital(models.Model):
  tel = models.IntegerField()
  addr = models.CharField(max_length=32)
  author = models.OneToOneField("Author") #         

注意:一時的に追加したフィールドは、まず前のデータがあるかどうかを考慮しなければなりません。標準値を設定します。

wordNum = models.IntegerField(default=0)  
logingで翻訳された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',
    },
  }
}  
注意事項:
1、時計の名前はmypap_modelNameは、モデルの中のメタデータに基づいて自動的に生成され、別の名前に上書きすることもできます。
2、idフィールドは自動的に追加されます。
3、外キーフィールドに対して、Djangoはフィールド名に「_」を追加します。ID「データベースの列名を作成します。
4、この例のCREATE TABLE SQL文はPostgreSQL文法フォーマットを使用していますが、Djangoはsettingsで指定されたデータベースタイプに基づいて対応するSQL文を使用しています。
5、モデルを定義したら、Django_を教えてください。_を使うこれらのモデル。あなたがしたいのは、プロファイルのINSTALLを修正することです。APPSZでは、models.pyのアプリケーション名を追加します。
6、外キーフィールドForeignKeyにnull=Trueの設定があります。外キーは空の値NULLを受け入れることができます。空の値Noneを与えられます。
フィールドのオプション
各フィールドにはいくつかの特有のパラメータがあります。例えば、CharFieldはmax_を必要とします。lengthパラメータは、VRCHARRデータベースフィールドのサイズを指定します。すべてのフィールドに適用される共通のパラメータもあります。これらのパラメータは文書に詳しく定義されています。ここでは最もよく使われているものだけを簡単に紹介します。
1)null
Trueの場合、DjangoはNULLでデータベースに空の値を格納します。デフォルトの値はFalseです
(1)ブランク
Trueであれば、このフィールドは書き込めないことができます。デフォルトはFalseです。
注意してください。これはnullとは違います。nullは全くデータベースの範疇で、blankはデータ検証の範疇です。
フィールドのblank=Trueの場合、フォームの検証は、フィールドが空の値であることを許可します。フィールドのblank=Falseの場合、このフィールドは必須です。
(2)default
フィールドの標準値です。値またはオブジェクトを呼び出すことができます。呼び出し可能であれば、新しいオブジェクトが作成されるごとに呼び出します。
(3)prmary_key
Trueなら、このフィールドはモデルのキーです。もしあなたがフィールドを指定していないなら、primary_key=True、
Djangoは自動的にInteger Fieldフィールドをメインキーとして追加しますので、デフォルトのプライマリキーの挙動を上書きしたい場合以外は、
任意のフィールドを設定する必要はありません。key=True。
(4)unique
この値がTrueに設定されている場合、このデータフィールドの値は全シートで唯一でなければなりません。
(5)checes
2つのタプルからなる反復可能なオブジェクト(例えば、リストまたはタプル)は、フィールドに選択項目を提供するために使用される。もしchecesを設定したら、
標準のフォームは標準のテキスト枠ではなく選択枠になります。この選択ボックスのオプションはchecesの中のオプションです。
これはchecesリストに関する例です。

YEAR_IN_SCHOOL_CHOICES = (
  ('FR', 'Freshman'),
  ('SO', 'Sophomore'),
  ('JR', 'Junior'),
  ('SR', 'Senior'),
  ('GR', 'Graduate'),
)
各タプルの最初の要素は、データベースに格納された値です。第二の要素は、管理インターフェースまたはModel Choice Fieldに表示として使用されるものである。
与えられたmodelクラスの例では、あるchecesフィールドの表示値を取得するために、get_を呼び出します。FOO_display方法(ここのFOOはchecesフィールドの名前です)。たとえば:

from django.db import models

class Person(models.Model):
  SHIRT_SIZES = (
    ('S', 'Small'),
    ('M', 'Medium'),
    ('L', 'Large'),
  )
  name = models.CharField(max_length=60)
  shirt_size = models.CharField(max_length=1, choices=SHIRT_SIZES)


>>> p = Person(name="Fred Flintstone", shirt_size="L")
>>> p.save()
>>> p.shirt_size
'L'
>>> p.get_shirt_size_display()
'Large

データモデルを作ったら、djangoは自動的にデータベースの抽象的なAPIを生成します。テーブルレコードの添削に関する操作を実行させます。
レコードを追加
ペアに複数のレコードを追加:

 #       
  #    :         publish_id      ,              
  #   :      (  book      publish    )   publish 
  #   :    
  models.Book.objects.create(title="     ",publishDdata="2015-5-8",price="111",publish_id=1)
  #    :  
  pub_obj = models.Publish.objects.filter(name="     ")[0]
  print(pub_obj)
  models.Book.objects.create(title = "  ",publishDdata="2000-6-6",price="222",publish=pub_obj)

  #    :save
  pubObj= models.Publish.objects.get(name="     ") #        get,           
  bookObj = models.Book(title = "     ",publishDdata="2015-9-9",price="50",publish=pubObj)
  bookObj.save()

マルチペアのレコードを追加:
本と作者は多対多の関係です。一つの本は複数の作者がいて、一つの作者は複数の本を出版することができます。
ステップ:まず本のオブジェクトを見つけます。
必要な作成者のオブジェクトを見つけます。
本の対象に作者のオブジェクトを結びつける(add方法を使う)ということは、複数対の関係を結びつけることです。

#            
  #    :
  #       :
  pub_obj=models.Publish.objects.filter(name="     ").first()
  book_obj = models.Book.objects.create(title="   ",publishDdata="2015-4-10",price="222",publish=pub_obj)
  # #       django    id
  haiyan_obj = models.Author.objects.filter(name="haiyan")[0]
  egon_obj = models.Author.objects.filter(name="egon")[0]
  xiaoxiao_obj = models.Author.objects.filter(name="xiaoxiao")[0]
  #         、
  book_obj.authorlist.add(haiyan_obj, egon_obj, xiaoxiao_obj)

  #    =========,       
  pub_obj = models.Publish.objects.filter(name="     ").first()
  book_obj = models.Book.objects.create(title="   ", publishDdata="2015-4-10", price="222", publish=pub_obj)
  authers = models.Author.objects.all()
  # #       
  book_obj.authorlist.add(*authers)

バインディングを解除:remove
xiは、ある特定の対象を関連対象のセットから削除する。    ======   bookobj.authors.remove(*)

#         (remove) book_obj=models.Book.objects.filter(title="   ").last() #      authers=models.Author.objects.filter(id__lt=3) #            book_obj.authorlist.remove(*authers) #        ,   *
バインディング解除:clear」  #関連するオブジェクトのセットをクリアします。

  #       (clear)
  book_obj= models.Book.objects.filter(title="   ")
  for book_obj_item in book_obj:#            
    book_obj_item.authorlist.clear()
まとめ:removeとclearの違い
remove:はい、クリアしたいデータを絞り出して削除します。
clear:調べなくてもいいです。直接にデータを全部空にしました。
それぞれのアプリケーションシーンがあります。
三、対象に基づくクエリー記録(sql文に相当するwhere子クエリ)
一対の照会記録:authorとauthordetileは一対の関係です。
順方向クエリー(フィールドauthorで)
逆方向クエリ(表の名前でauthordeintal):一対一の関係ですので、_を使いません。セットしました。

 #       
  #     :    13245      
  deital_obj = models.AuthorDeital.objects.filter(tel="13245").first()
  print(deital_obj.author.name)
  #     :  egon    
  egon_obj = models.Author.objects.filter(name="egon").first()
  print(egon_obj.authordeital.tel)
ペアの複数クエリ記録
順方向クエリ(フィールド:publishで):
リバースクエリ(表の名前によると:book_セット):

 #     :                 
  book_obj = models.Book.objects.filter(title="     ")[0] #    
  print("======", book_obj.publish) #             
  print(book_obj.publish.addr)
 #     :                     
  pub_obj = models.Publish.objects.filter(name="     ")[0]
  book_dic = pub_obj.book_set.all().values("price", "title")[0]
  print(book_dic)
  print(book_dic["price"])
  #                 

  publish=models.Publish.objects.get(name="     ")  #get          ,  get          

  book_list=publish.book_set.all() #                  

   for book_obj in book_list:

   print(book_obj.title)

ここでforサイクルを使っても、valuesを使っても、vauleslistを使ってもいいです。
マルチペアのクエリ記録
順方向クエリ(フィールドauthorlistで)
逆方向クエリ(表の名前でbook_)セット

 #       
  #     :                       
  book_obj = models.Book.objects.filter(title="   ")[0]
  print(book_obj.authorlist.all().values("name", "age")) #                
  #     :     haiyan             
  haiyan_obj = models.Author.objects.filter(name="haiyan")[0]
  print("bookinfo====", haiyan_obj.book_set.all().first().title) #                
  return HttpResponse("ok")
ForeignKey()とManyToManyFieldの定義でrelatedを設定することができます。nameの値はFOO_を上書きします。セットの名前。例えば、Artcle modelで変更したら、publish=ForeignKey(Blog、related_)name='book List')では、次は私達が見ているようになります。

#                 
  publish=Publish.objects.get(name="     ") 
  book_list=publish.bookList.all() #                  
二重下線に基づくクロステーブルクエリ
Djangoはまた、SQL JOIN連絡を自動的に確認することができる、直感的かつ効率的な方法を提供しています。クロス関係クエリをするには、モデル間の関連フィールドの名前を2つのアンダーラインでリンクします。最終的にはあなたが欲しいモデルにリンクするまで。sql文でjoinで接続するのに相当します。settingsで設定できます。sql文を確認できます。
ペアで複数のクエリ:
練習1、人民出版社が出版した本の値段と名前を調べます。

#            1================   
  #      
  ret = models.Publish.objects.filter(name="     ").values("book__price","book__title")
  print(ret)
  #      
  ret2 = models.Book.objects.filter(publish__name="     ").values("price","title")
  print(ret2)
練習2、linuxという本の出版社の住所を調べます。filerは先にフィルタして、valuesは要求のフィールドを表示します。

       
  ret = models.Book.objects.filter(title="linux").values("publish__addr")
  print(ret)
       
  ret2 = models.Publish.objects.filter(book__title="linux").values("addr")
  print(ret2)
マルチペア
練習1、egonから出た本の名前を全部調べます。

#     
  ret = models.Author.objects.filter(name="egon").values("book__title")
  print(ret)
#   :            
  ret2 = models.Book.objects.filter(authorlist__name="egon").values("title")
  print(ret2)
練習2、携帯番号を調べて151で始まる著者が出版した本の名前と出版社の名前を調べます。

  #    :
  author_obj = models.AuthorDeital.objects.filter(tel__startswith="151").first()
  print(author_obj.author.book_set.all().values("title","publish__name"))
  #    :
  ret = models.Book.objects.filter(authorlist__author_deital__tel__startswith="151").values("title","publish__name")
  print(ret)
集約クエリとグループクエリ(重要です!!!)
アグレッガテは、一つのグループにのみ集約されます。

from django.db.models import Avg,Sum,Count,Max,Min
# 1、            print(models.Book.objects.all().aggregate(Avg("price")))
aggregate()はQuerySetの終止子句(つまり、戻ってくるのはもう一つのQuerySetの集合の時ではない)という意味で、キーパッドのペアを含む辞書を返すという意味です。キーの名前は集約値の識別子であり、値は計算された集約値である。キーの名前は、フィールドと集計関数の名前によって自動的に生成されます。統合値に名前を指定すると、その子文が集約されます。

from django.db.models import Avg,Sum,Count,Max,Min
# 1、           
print(models.Book.objects.all().aggregate(avgprice = Avg("price")))
一つ以上のクラスターを生成したい場合は、他のパラメータをaggregate()のサブルーチンに追加します。だから、もしあなたがすべての図書の価格の最大値と最小値を知りたいなら、このように調べられます。

print(models.Book.objects.all().aggregate(Avg("price"),Max("price"),Min("price")))
#      : {'price__avg': 174.33333333333334, 'price__max': Decimal('366.00'), 'price__min': Decimal('12.00')}

グループクエリ:annotate():QuerySetの各オブジェクトに独立した集約値を生成します。グループ化された後の結果の集約です。
1、各本の作者の個数を統計する

  #    :
  print(models.Book.objects.all().annotate(authorNum = Count("authorlist__name")).values("authorNum"))
  #    :
  booklist =models.Book.objects.all().annotate(authorNum=Count("authorlist__name"))
  for book_obj in booklist:
    print(book_obj.title,book_obj.authorNum)
2、出版社ごとに一番安い本を統計します。

  # 2、              
  #    :
  print(models.Book.objects.values("publish__name").annotate(nMinPrice=Min('price')))   :values     group by   ,,       
  #    :
  print(models.Publish.objects.all().annotate(minprice=Min("book__price")).values("name","minprice"))
  #    
  publishlist = models.Publish.objects.annotate(minprice = Min("book__price"))
  for publish_obj in publishlist:
    print(publish_obj.name,publish_obj.minprice)
3、pyで始まる本の作者の個数を統計する:

print(models.Book.objects.filter(title__startswith="py").annotate(authNum = Count("authorlist__name")).values("authNum"))

4統計は一人の作者の図書を超えません。

print(models.Book.objects.annotate(num_authors=Count('authorlist__name')).filter(num_authors__gt=1).values("title","num_authors"))
5本の著者の数に基づいてQuerySetをソートします。

print(models.Book.objects.all().annotate(authorsNum=Count("authorlist__name")).order_by("authorsNum"))
6各作者が出した本の総価格を調べます。

 #    
  print(models.Author.objects.all().annotate(priceSum = Sum("book__price")).values("name","priceSum"))
 #    
  print(models.Book.objects.values("authorlist__name").annotate(priceSum=Sum("price")).values("authorlist__name","priceSum"))

FクエリとQクエリ
Fクエリ:
上記のすべての例では、私達が作成したフィルタは、フィールド値をある定数と比較するだけです。二つのフィールドの値を比較するなら、どうすればいいですか?
DjangoはF()を提供してこのような比較をします。F()の例は、同じmodelの例の中の2つの異なるフィールドの値を比較するために、クエリーでフィールドを参照することができる。
1、レビューの数が読書数より大きい本を見る

 from django.db.models import F,Q
 print(models.Book.objects.filter(commentNum__gt=F("readNum")))
2、修正操作はF関数を使ってもいいです。例えば、idを1より大きい本の価格を100元値上げします。

print(models.Book.objects.filter(nid__gt=1).update(price=F("price")+100))
3、DjangoはF()オブジェクト間およびF()オブジェクトと定数間の加減乗除とダイ取の動作をサポートします。

#           2    
  models.Book.objects.filter(commnetNum__lt=F('keepNum')*2)
Qクエリ:
filter()などのキーワードパラメータの照会は一緒に「AND」を行います。より複雑なクエリ(OR文など)を実行する必要がある場合は、Qオブジェクトを使用しても良いです。
1、検索IDが1より大きく、コメント数が100より大きい本

 print(models.Book.objects.filter(nid__gt=1,commentNum__gt=100))
 print(models.Book.objects.filter(nid__gt=1).filter(commentNum__gt=100))
 print(models.Book.objects.filter(Q(nid__gt=1)&Q(commentNum__gt=100)))
2、クエリのコメント数が100以上か200未満の本を読みます。

print(models.Book.objects.filter(Q(commentNum__gt=100)|Q(readNum__lt=200)))
Qオブジェクトは、オペレータと組み合わせることができます。オペレータが2つのQオブジェクトで使用すると、新しいQオブジェクトが生成される。
3、照会年は2017年と同じ、または200以上の本

print(models.Book.objects.filter(Q(publishDdata__year=2017)|Q(price__gt=200)))
4、照会年は2017年ではないか、または200以上の価格の本

print(models.Book.objects.filter(~Q(publishDdata__year=2017)&Q(price__gt=200)))
注意:
クエリー関数は、Qオブジェクトとキーワードパラメータを混合して使用できます。クエリー関数に提供されるすべてのパラメータ(キーワードパラメータまたはQオブジェクト)は、ANDを一緒にします。しかし、Qオブジェクトが現れると、すべてのキーワードパラメータの前に位置しなければなりません。たとえば:

  bookList=models.Book.objects.filter(Q(publishDate__year=2016) | Q(publishDate__year=2017),
                 title__icontains="python"
                 )
以上が本文の全部です。皆さんの勉強に役に立つように、私たちを応援してください。