[TIL.34]DjangoモデルAPI(データインポート-正参照、逆参照)


Queryset?


クエリー・セットとは、渡されたモデルのオブジェクトのリストです.データベースからデータの読み込み、フィルタリング、ソートなどができます.リストと構造は同じですが、Pythonの基本資料構造ではなく、読み書きのために資料型変換が必要です.クエリー・セットは、データベース内の複数のレコード(行)を表します.
from .models import Book
Book.objects.all()	# Book 모델(테이블)의 모든 데이터를 갖고와라!
<QuerySet [<Book: 책 제목1>, <Book: 책 제목2>]>
ここでobjectsはModel Managerです.データベースとDjangoモデル間のクエリー操作のインタフェース.この場合、objectsを使用して複数のデータを取得する関数を使用すると、返されるオブジェクトはQuerySetです.
マネージャの各モデル(クラス)には少なくとも1つあります.
Person.objectsとは、objectsというmanagerがPersonデータベースをQuerySetにすることを意味します.彼らにそのQuerySetでデータを検索させることができます.

CRUD


クエリー・セットを返さない方法


  • create()

  • .get()
    1行のみインポートする場合に使用します.
    Question.objects.get(pk=1)
    pkが1の値
    1つの値のみ取得
    <オブジェクトを返す>

  • .update()
    指定したフィールドの更新クエリーを実行し、一致するローの数を返します.
  • In  : Category.objects.filter(name='탄산').update(name='콜드브루')
    Out : 2 #총 업데이트된 row 개수
  • .delete()
    データ消去に使用します.
    を選択して設定できます.
    まず削除するRowオブジェクトを読み込み、使用します.
  • fb = Feedback.objects.get(pk=2)
    fb.delete()
  • .save()
    個々のオブジェクトに対して更新を実行するための挿入、更新を実行する方法.
  • In  : category = Category.objects.get(id=2)
    Out : <Category: Category object (2)>
    
    In  : category.name
    Out : '브루드커피'
    
    In  : category.name = 'new name'
    In  : category.save()
    
    In  : category.name
    Out : 'new name'
  • exist()
    filterを使用して条件を満たすデータを検索し、Trueが返されない場合、falsereturn
  • In  : Category.objects.filter(name='브루드커피').exists()
    Out : True

    クエリー・セットを返す方法


  • all()
    すべてのテーブルデータを取得する方法
    <クエリーセットに戻る>

  • filter, exclude()
    -> .filter()
    特定の条件を満たすRowのインポートに使用
    2つ以上の値を取得することもできます
    何の条件も持たないすべてと同じ
    <クエリーセットに戻る>

  • values()
    iterableとして使用すると、モデルインスタンスではなくdictionaryを含むクエリーセットが返されます.

  • values_list()
    tupleを返します.
  • add()
    多対多関係の場合に使用します.
  • d1 = Drink.objects.get(id=1)
    a1 = Allergy.objects.get(id=1)
    
    #drink와 allergy는 다대다 관계이고, 중간 테이블(DrinkAllergy 테이블)을 거치지 않고 drink를 통해 allergy에 정보를 담을 수 있다. 
    d1.allergies.add(a1)
  • オブジェクトの作成
    q = Question(question_text="What's new?", pub_date=timezone.now())
  • Shell使用時
  • テストするならコードを見てビューに入れる...?
    データがあるかどうか見てみましょう.
    シェルでデータが入っているかどうかを一つ一つ検索してからビューに入れます!
    電源を切ると内容が消えます(変数とか)
    objectにしか使えないattributeがあるので、よく知っておきましょう.

    Many to Many関係を設定するより良い理由は?


    中間テーブルAllergyDrinkを作成し、AllergyとDrinkをFKに接続しますが、実際にデータの読み取りとインポートに問題はありません.しかし、なぜ関係を多対多に設定しなければならないのだろうか.
    1)データを入れるときに中間表を通す必要がないので、簡単になりました.
    2)データをインポートする場合は、最小のデータベースでインポートするのが望ましいが、MTM接続の場合は、中間テーブルを必要とせずにデータをインポートするプロセスが簡単になる.
    詳細の表示
    マルチペアマルチリレーションシップを追加する利点は、中間テーブルを必要とせず、いつでも簡単にデータを追加およびインポートできることです.

    データのインポート(「」を参照)

    class Drink(models.Model):
        korean_name = models.CharField(max_length=45)
        english_name = models.CharField(max_length=45)
        description = models.TextField()
        category = models.ForeignKey('Category', on_delete=models.CASCADE)
        allergies = models.ManyToManyField(Allergy, through = "AllergyDrink")
        
    class Category(models.Model):
        name = models.CharField(max_length=45)
        menu = models.ForeignKey('Menu', on_delete=models.CASCADE)
        
    class Allergy(models.Model):
        name = models.CharField(max_length=45)
    
    class AllergyDrink(models.Model):
        allergy = models.ForeignKey('Allergy',on_delete=models.CASCADE)
        drink = models.ForeignKey('Drink',on_delete=models.CASCADE)

    正参照の場合。


    1)Drinkにより、driveが参照するcategoryを容易に知ることができる.(Drink -> Category)
    In [42]: d1 = Drink.objects.get(id=1)
    In [43]: d1.category.name
    Out[43]: '콜드 브루 커피'
    # 또는 이렇게 
    In [47]: Drink.objects.get(id=1).category.name
    Out[47]: '콜드 브루 커피'
    
    2)dinkによるアレルゲン導入(++多対多関係)
    # 1개의 알러지만 가지고 있는 경우
    In [2]: d1 = Drink.objects.get(id=1)
    
    In [4]: d1.allergies.get()
    Out[4]: <Allergy: Allergy object (2)>
    
    In [5]: d1.allergies.values()
    Out[5]: <QuerySet [{'id': 2, 'name': '우유'}]>
    
    In [6]: d1.allergies.get().name
    Out[6]: '우유'
    
    # 2개 이상의 알러지를 가지고 있는 row
    In [7]: d10 = Drink.objects.get(id=10)
    
    In [8]: d10.allergies.values()
    Out[8]: <QuerySet [{'id': 1, 'name': '대두'}, {'id': 2, 'name': '우유'}]>
    
    In [9]: a = d10.allergies.values()
    
    In [10]: for i in a:
        ...:     print(i)
        ...: 
    {'id': 1, 'name': '대두'}
    {'id': 2, 'name': '우유'}
    
    In [11]: for i in a:
        ...:     print(i['name'])
        ...: 
        ...: 
    대두
    우유
    
    # 또 다른 방법 
    In [42]: Drink.objects.get(id=1).allergies
    Out[42]: <django.db.models.fields.related_descriptors.create_forward_many_to_many_manager.<locals>.ManyRelatedManager at 0x7f8b6ec95190>
    
    In [43]: Drink.objects.get(id=1).allergies.get()
    Out[43]: <Allergy: Allergy object (2)>
    
    In [44]: Drink.objects.get(id=1).allergies.get().name
    Out[44]: '우유'
    

    逆参照の場合


    related nameが設定されていない場合は、setが貼り付けられ、逆参照データであることを示します.
    ✔¥逆参照系
    Fkのクラスが指定されていません.つまり、pkが存在するテーブル!
    1)Category逆参照Drinkのインポート
    In [11]: Category.objects.get(id=1).drink_set
    Out[11]: <django.db.models.fields.related_descriptors.create_reverse_many_to_one_manager.<locals>.RelatedManager at 0x7fe9e0c6dc90>
    
    In [12]: Category.objects.get(id=1).drink_set.all()
    Out[12]: <QuerySet [<Drink: Drink object (1)>, <Drink: Drink object (2)>, <Drink: Drink object (7)>, <Drink: Drink object (8)>, <Drink: Drink object (11)>, <Drink: Drink object (12)>]>
    In [13]: c = Category.objects.get(id=1).drink_set.all()
    In [16]: for ca in c:
        ...:     print(ca.korean_name)
        ...: 
        ...: 
        ...: 
    나이트로 바닐라 크림
    미드나잇 베르가못 콜드 브루
    벨젯 다크 모카 나이트로
    프렌치 애플 타르트 나이트로
    프렌치 애플 타르트 나이트로
    카푸치노
    2)アレルギーによる飲み物の入手方法(Driink->Allergy:もとはこう引用した関係)(++multi to multi関係)
    In [26]: Allergy.objects.get(id=2).drink_set.values()
    Out[26]: <QuerySet [{'id': 1, 'korean_name': '나이트로 바닐라 크림', 'english_name': 'Nitro Vanilla Cream', 'description': '부드러운 목넘김의 나이트로 커피와 바닐라 크림의 매력을 한id': 2, 'korean_name': '미드나잇 베르가못 콜드 브루', 'english_name': '', 'description': '', 'category_id': 1}, {'id': 3, 'korean_name': '딸기 딜라이트 요거트 블렌디드', 'english_n'', 'category_id': 2}, {'id': 5, 'korean_name': '쿠키 블루베리 잼 머핀', 'english_name': '', 'description': '', 'category_id': 3}, {'id': 7, 'korean_name': '벨젯 다크 모카 나이트로'', 'description': '', 'category_id': 1}, {'id': 10, 'korean_name': '돌체 라떼', 'english_name': '', 'description': '', 'category_id': 3}]>
    
    In [27]: b = Allergy.objects.get(id=2).drink_set.values()
    
    In [28]: for bs in b:
        ...:     print(bs)
        ...: 
    {'id': 1, 'korean_name': '나이트로 바닐라 크림', 'english_name': 'Nitro Vanilla Cream', 'description': '부드러운 목넘김의 나이트로 커피와 바닐라 크림의 매력을 한번에 느껴보세요!', 'category_id': 1}
    {'id': 2, 'korean_name': '미드나잇 베르가못 콜드 브루', 'english_name': '', 'description': '', 'category_id': 1}
    {'id': 3, 'korean_name': '딸기 딜라이트 요거트 블렌디드', 'english_name': '', 'description': '', 'category_id': 2}
    {'id': 5, 'korean_name': '쿠키 블루베리 잼 머핀', 'english_name': '', 'description': '', 'category_id': 3}
    {'id': 7, 'korean_name': '벨젯 다크 모카 나이트로', 'english_name': '', 'description': '', 'category_id': 1}
    {'id': 10, 'korean_name': '돌체 라떼', 'english_name': '', 'description': '', 'category_id': 3}
    
    In [29]: for bs in b:
        ...:     print(bs['korean_name'])
        ...: 
        ...: 
    나이트로 바닐라 크림
    미드나잇 베르가못 콜드 브루
    딸기 딜라이트 요거트 블렌디드
    쿠키 블루베리 잼 머핀
    벨젯 다크 모카 나이트로
    돌체 라떼
    

    all, get, values

  • all、get、値の違い
    valuesはディクソン形式で戻ります.
    objectを返してfield値をすぐに読み込む必要があります.
  • 値は1つしかありません。



    getはobjectを返すので、すぐに使用できます.(でもstringタイプ…)

    複数の値があります。


    このとき考慮できるのはall,valuesである.
    1)allを使用する場合
  • allを使用してquery setを返します.この場合もフィールド値を直接読み込むことはできません.
  • for文を使用してquerysetをオブジェクトに変換します.したがって、for文を使用してobject形式に変換し、すぐにフィールド値を読み込むことができます.
  • 2)値を使用する場合:
  • の価値はディックシャーナの形で価値をもたらす.
    の値は、最初にディック年鑑を含むquerysetを返し、for文を使用してディック年鑑に変換できます.だから.(dot)インポートは使用できません.['key name'でのみインポートできます.
  • ++その他の方法!!
    値()を使用しなくてもよいし、値(「フィールド値」)を使用してもよい.
    は、このようにしてリストをインポートすることもできる
    💡 objectの形態の場合のみ.(dot)を使用してフィールド値を直接取得できます!
    django公式ドキュメント-Query set API