#4 CRUD(4) - Assignment
課題として出てきた『飼い主と犬』『俳優と映画』について
仮想環境、プロジェクト、git repo生成、DB設定などの初期設定が完了し、飼い主と犬は
views.pyは以下のことを学びました.1)導入時に構築するモジュール/外部パッケージモジュール/カスタムモジュール規約 を遵守する.2)メソッド定義時に、目的/入出力コメントを使用して を作成する.3)応答すると、owner idまたはcustomer idなどの要求元IDが生成される 4)一対の多関係においてPOSTメソッドを作成する場合、外部キー参照はid(pk)、 である.5)一対の多関係においてGETメソッドを作成する際の逆参照の3つのメソッド
(
dog.owner.テーブルネスト(nameなど) 6)GETメソッドを実行すると、結果値がネストされたディックシェリー構造の場合、ネストされたリスト計算によって作成されます.
4~6日まで詳しく知ります.まず4番のコードを比較してみましょう.
次に、5番局参照と6番リスト計算が重なるのを見てみましょう.
またmycodeでは、1つのテーブルで複数のテーブルを逆参照する場合、
wrap-upコードでは、ネストされたリストコンパイルを再度使用して、コードを再度簡潔に置き換えることができます.
このような適切なリスト計算の使用は計算性能を向上させるだけでなく、コードもより簡潔であり、適切な可読性があれば、できるだけ使用することが望ましい.
まず、case 1のように
次に、case 2のように
*
1つ目は現場ログインです.DjangoはSQLクエリ文で使用されるWHEREセクションも使用します.例:
2つ目は
views.pyの作成時に
ここで、dogテーブルのpk idは、
[
張高のモデル照会セットで、ダブルアンダースコア()はどういう意味ですか?
ソース・サイト
最後に、私が書いたコードと一致するcase 3を見てみましょう.
上記の2つのケースとは異なり、
クラス名には、リファレンスバックグラウンドが使用されていません.コード規則を適用します. djangoがサポートする多対多関係法 を用いる.
当初、
しかし、これはまったく間違った考えだ.djangoで内部に中間テーブルを作成するかどうかは、
同様に、wrap-upからのcase 2も、中間テーブルではなくMovieテーブルを使用しますが、コードには大きな違いはありません.
しかし,
符号化フレームワークにおいて予め定められた便利な方法の場合は,積極的に用いるべきである.
「飼い主と犬」セクションでは、コードを簡潔に変更するように、オーバーラップリストcompressionを使用して適用します.
最後に、中間テーブルを使用する場合、ActorViewと同じ構造のMovieViewを
モデルには
仮想環境、プロジェクト、git repo生成、DB設定などの初期設定が完了し、飼い主と犬は
feature/owner
行、俳優と映画はfeature/movie
行に設定されている.飼い主と子犬
owner/models.py
### My code
from django.db import models
class Owner(models.Model):
name = models.CharField(max_length=45)
email = models.CharField(max_length=300)
age = models.IntegerField()
class Meta:
db_table = 'owners'
class Dog(models.Model):
owner = models.ForeignKey('Owner',on_delete=models.CASCADE)
name = models.CharField(max_length=45)
age = models.IntegerField()
class Meta:
db_table = 'dogs'
### Wrap-up code
/...
email = models.CharField(max_length=300,unique=True)
# email은 중복되면 안되므로 unique=True 작성
age = models.PositiveIntegerField()
# 나이는 음수가 되면 안되므로 PositiveIntegerField 사용
/...
それ以外に,課題単位でappを作成し,wrap−upではapp,飼い主,子犬のモデルをビュー単位で区分した.py urls.py views.一人一人がpyを作成し、必要に応じてインポートして使用する違いは明らかです.owner/views.py
views.pyは以下のことを学びました.
(
related_name
、get
またはfilter
の方法および_set
の方法を使用する.dog.owner.テーブルネスト(nameなど)
4~6日まで詳しく知ります.まず4番のコードを比較してみましょう.
owner = Owner.objects.get(name=data["owner"]) # My code
owner_id = data['owner_id'] # Wrap-up code
oneto multi関係では、multiに相当するテーブルがownerテーブルに関する情報をowner idとして持っているため、getクエリーownerテーブルを使用する必要がなく、post機能の作成時に問題がないと判断できます.次に、5番局参照と6番リスト計算が重なるのを見てみましょう.
# OwnerView My code
def get(self, request):
owners = Owner.objects.all()
result = []
for owner in owners:
dogs_list = [
{'dog_name':dog.name} for dog in Dog.objects.filter(owner_id=owner.id)]
]
result.append(
{
'name' : owner.name,
'email' : owner.email,
'age' : owner.age,
'dogs' : dogs_list
}
)
return JsonResponse({"dogs" : result}, status=200)
# OwnerView Wrap-up code
/...
for owner in owners:
results.append({
"id" : owner.id,
"name" : owner.name,
"age" : owner.age,
"dogs" : [{"id" : dog.id, "name" :dog.name} for dog in owner.dog_set.all()]
}
)
飼い主が所有する子犬のリストdog listを作成し、私のコードでは簡単なダブルfor文を使用しましたが、wrap-upではリストコンパイルを使用しました.またmycodeでは、1つのテーブルで複数のテーブルを逆参照する場合、
get
またはfilter
メソッドを用い、wrap-upでは_set
メソッドを用いた.wrap-upコードでは、ネストされたリストコンパイルを再度使用して、コードを再度簡潔に置き換えることができます.
result = [{"id": owner.id, "name":owner.name,"age":owner.age,"dogs": [{"id" : dog.id, "name" : dog.name} for dog in owner.dog_set.all()]} for owner in owners]
return JsonResponse({"MESSAGE" : result}, status=200)
コードは簡潔になりましたが、長すぎて読みにくいので、途中で行を変えました.result = [{"id": owner.id, "name":owner.name,"age":owner.age,"dogs":
[{"id" : dog.id, "name" : dog.name} for dog in owner.dog_set.all()]} for owner in owners]
return JsonResponse({"MESSAGE" : result}, status=200)
だいぶよくなった.このような適切なリスト計算の使用は計算性能を向上させるだけでなく、コードもより簡潔であり、適切な可読性があれば、できるだけ使用することが望ましい.
# DogView My Code
def get(self,request):
dogs = Dog.objects.all()
result = []
# My code == case 3(many.one table)
for dog in dogs:
result.append({
'dog_name' : dog.name,
'dog_age' : dog.age,
'owner' : {
"id" : dog.owner.name,
"name" : dog.owner.id
}
})
# DogView Wrap-up code case1(related_name)
for dog in dogs:
owner = Owner.objects.get(dogs__id = dog.id)
result.append({
"id" : dog.id,
"name" : dog.name,
"age" : dog.age,
"owner" : {
"id" : owner.id,
"name" : owner.name
}
})
# DogView Wrap-up code case2(NOT USE related_name)
for dog in dogs:
owner = Owner.objects.get(dog__name = dog.id)
result.append({
"id" : dog.id,
"name" : dog.name,
"age" : dog.age,
"owner" : {
"id" : owner.id,
"name" : owner.name
}
})
次にwrap-upで学んだ逆参照の3つの方法を順に見てみましょう.まず、case 1のように
related_name
を使用する場合は、まずモデルにrelated_name
を設定する必要があります.# models.py
class Dog(models.Model):
owner = models.ForeignKey('Owner',on_delete=models.CASCADE,related_name="dogs")
related_name
として指定されたdogs
を使用する場合、ownerテーブルのデータではなくdogテーブルのデータを読み出す場合、owner.dogs.all()で閲覧できます.次に、case 2のように
related_name
を使用する必要はなく、dog_set
のようにテーブル名setを使用して逆参照することもできる.この時がご主人様dog_set.all()で読み取ることができます.related_name
を使用しなくても逆参照できますが、使用していない場合は競合します.表名が複雑または長い場合は、related_name
を使用して短い置換を行うことができますので、できるだけ使用することをお勧めします.*
dogs__id
では、関数のモデルクエリセット__
は何を意味しますか?1つ目は現場ログインです.DjangoはSQLクエリ文で使用されるWHEREセクションも使用します.例:
Owner.objects.filter(name__contains="김")
上記のコードは、Owner
モデルのname
フィールドに「のり」を含むデータをフィルタリングするコードです.contains
に加えて、gt
、startwith
などの多くの現場位置決め方法が存在する.2つ目は
외래키 모델의 속성 참조
です.dog__id
はこれに相当すると考えられる.views.pyの作成時に
owner = Owner.objects.get(dog__id = dog.id)
とともに作成し、ownerテーブルでdogテーブルを参照します.ここで、dogテーブルのpk idは、
__
によってownerによって参照されることができる.[
__
(二重下線)参照サイト]張高のモデル照会セットで、ダブルアンダースコア()はどういう意味ですか?
ソース・サイト
最後に、私が書いたコードと一致するcase 3を見てみましょう.
上記の2つのケースとは異なり、
owner = Owner.objects.get(dogs__id = dog.id)
のコードは記述されていない.dog.owner.name
のようにテーブルの名前をネストしています.多くのdogモデルにはowner idという外部キーがあるため、getメソッドを使用することなくアクセスできます.俳優と映画
git checkout -b
命令によりfeature/movie
ブランチを生成して移動し、追加のタスクを行った.最初の設定からGET,POST方式の作成は最初の課題と似ているが,俳優と映画は一対多の関係ではなく,多対多の関係である.movie/models.py
# models.py My code
from django.db import models
class Actor(models.Model):
first_name = models.CharField(max_length=45)
last_name = models.CharField(max_length=300)
date_of_birth = models.DateField()
class Meta:
db_table = 'actors'
class Movie(models.Model):
title = models.CharField(max_length=45)
release_date = models.DateField()
running_time = models.IntegerField()
class Meta:
db_table = 'movies'
class Actor_Movie(models.Model):
actor = models.ForeignKey("Actor",on_delete=models.CASCADE)
movie = models.ForeignKey("Movie",on_delete=models.CASCADE)
class Meta:
db_table = 'actors_movies'
# models.py Wrap-up code
/..
class ActorMovie(models.Model):
/..
class Actor(models.Model):
/..
movies = models.ManyToManyField('movies.Movie', through = ActorMovie)
/..
ManyToManyField()
は当初、
ManyToManyField()
を使用すると、参照とコードの作成がより便利になりますが、中間テーブルはdjango内部で生成されるので、ManyToManyField()
を使用しないで、中間テーブルのみを作成する必要があります.しかし、これはまったく間違った考えだ.djangoで内部に中間テーブルを作成するかどうかは、
ManyToManyField()
のthrough
オプションがあるかどうかによって決まります.すなわち、through
オプションを使用しない場合、djangoは内部に中間テーブルを作成し、ユーザーが作成した中間テーブルを指定することができます.movie/views.py
import json
from django.views import View
from django.http import JsonResponse
from .models import Actor, Movie, Actor_Movie
class ActorView(View):
def get(self, request):
actors = Actor.objects.all()
result = []
for actor in actors:
# views.py My code (case 1, 중간테이블 사용)
actors_movies = Actor_Movie.objects.filter(actor_id = actor.id)
movie_list = []
for actor_movie in actors_movies:
movie_list.append(
{
'title' : actor_movie.movie.title
}
)
result.append(
{
'Name' : actor_movie.actor.first_name + actor_movie.actor.last_name,
'Birth' : actor_movie.actor.date_of_birth,
'Filmography' : movie_list
}
)
return JsonResponse({"Actors" : result}, status=200)
/..
# views.py Wrap-up code (case2, Movie 테이블 이용)
/..
movies = Movie.objects.filter(actor_movie__actor_id = actor.id)
movie_list = []
for movie in movies:
movie_list.append({
"id" : movie.id,
"title" : movie.title
})
results.append({
"first_name" : actor.first_name,
"last_name" : actor.last_name,
"movies" : movie_list
/..
# views. py Wrap_up code (case3, recommend)
/..
results.append({
"first_name" : actor.first_name,
"last_name" : actor.last_name,
"movies" : [{"title" : movie.title} for movie in actor.movies.all()]
})
/..
djangoサポートを使用していないManyToManyField()
、中間表のみ使用している私は、最初のGETメソッドを実現するために工夫を凝らしました.中間表だけを使って俳優のデータと俳優が出演した映画のデータをディックの繰り返し文に格納するのはコードが長いだけでなく、インデントも複雑だ.同様に、wrap-upからのcase 2も、中間テーブルではなくMovieテーブルを使用しますが、コードには大きな違いはありません.
しかし,
ManyToManyField()
を用いたcase 3では,参照関係が容易になり,コード記述が容易になり,また中間テーブルを用いたためテーブル名が長くなり,コードが長くなる現象が消失することが見られる.through
でカスタムを中間テーブルとして指定すると、中間テーブル管理の問題もなくなります.符号化フレームワークにおいて予め定められた便利な方法の場合は,積極的に用いるべきである.
「飼い主と犬」セクションでは、コードを簡潔に変更するように、オーバーラップリストcompressionを使用して適用します.
最後に、中間テーブルを使用する場合、ActorViewと同じ構造のMovieViewを
ManyToManyField()
を使用したリストコンパイル形式に変換する.モデルには
related_name
は使用されていないのでactor set.all()から逆参照が行われていることがわかります.Reference
この問題について(#4 CRUD(4) - Assignment), 我々は、より多くの情報をここで見つけました https://velog.io/@aerialslash/Django-C.R.U.D-Assignmentテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol