TIL-djangoの起動(アプリケーションDB/機能実装-2)


ORM


前の記事では、ロングライブラリmodels.pyを使用して必要なモデルを作成し、移行によってデータベース・アーキテクチャに適用しました.次に、本明細書のORMを使用してデータベースにデータを格納し、必要に応じてインポート操作を行います.

ORMは


ORMは、オブジェクト-リレーショナル・マッピングの略で、マッピング・オブジェクトとリレーショナル・データベースのデータを指します.つまり、オブジェクト間の関係に基づいてSQLが自動的に生成され、データベース内のデータにSQLクエリが不要になります.
select * from actors;
のクエリ
from movies.actors import Actor
Actor.objects.all()
似たようなPython構文を使うことができます.
長期ORM用に提供されるQuery Set APIは標準ドキュメント(Query Set API)で検証され、ここでは実装する機能について簡単に説明します.
まずはORMと遊ぶためにターミナルをターミナルに入り、プロジェクトディレクトリに移動します.python manage.py shellコマンドを入力すると、1回目のPythonのように、少なくとも1回入ったPython基本IDLEの画面が表示されます.今は正式にORMと遊ぶことができます.
(前に作ったmodels.pyを横に置いて遊ぶと、モデルの属性や参照関係などを見ることができます).

まず、モデルを使用してデータベースにアクセスするために必要なものをインポートします.
# shell
from myApp.models import Movie, Actor
次に、次のように入力して、データの山を作成します.
# shell
from django.utils import timezone
# settings.py에서 정한 시간대에 맞게 사용하려면 장고의 타임존을 이용해야 한다.
a1 = Actor(first_name="Ted", last_name="Chang", date_of_birth=timezone.now().date())
# 더미데이터이기에 배우의 생일은 오늘의 날짜로 정해줬다.
# timezone.now()는 현재 날짜와 시간을 같이 리턴해준다.
# 현재 date_of_birth 부분은 날짜만 받는 DateField 이므로
# timezone.now().date()를 사용해 현재의 날짜만을 받아낸다.
a1.save()
# a1을 만들고 저장한 과정 == 
# Actor.objects.create(first_name="Ted", last_name="Chang", date_of_birth=timezone.now().date())
# objects.create를 사용하면 생성 후 저장까지 자동으로 진행한다.
m1 = Movie(title="극한직업", release_date=timezone.now().date(), running_time=250)
# Movie의 개봉일 또한 오늘의 날짜를 더미로 넣어주었다.
m1.save()
m1.actor.add(a1)
# m1을 만들고 저장한 뒤 배우를 추가한 과정 ==
# Movie.objects.create(title="극한직업", release_date=timezone.now().date(), running_time=250, actor = a1)
上記のすべてのデータを入力して、作成したmysqlデータベースに入ります.
select * from actors;
select * from movies;
に示すように、コマンドを入力すると、作成したテッドウィンドウと限界職業が各テーブルに含まれていることを確認できます.私たちのモデルはクラスの形式なので、クラスオブジェクトの作成と同じクエリー、objectsを作成できます.create()を使用してクエリーを作成することもできます(コメント/公式ドキュメントを参照).また,この例では,映画クエリーを生成し,俳優を映画に入れるが,逆に俳優を設定しながら映画に入れることができる.
a3 = Actor(first_name="bruce", last_name="lee", date_of_birth=timezone.now().date(), movie=m1)
a3.save()
# OR
a4 = Actor(first_name="hs", last_name="s", date_of_birth=timezone.now().date())
a4.movie_set.add(m1)
ここでひとつ疑問があるなら、映画で俳優を参照するとき(近いとき)はm1.movieのように近いかもしれませんが、俳優で映画を参照するとa4.movie_setのように_setが貼られています.これは、モデルの中で関係対象の違いが表示されているかどうかです.
映画モードを見るとManyToManyFieldの位置と俳優との関係を教えてくれますが、俳優モードにはその関係を表すフィールドはありません.
すなわち、「forward relation」(現在の映画モデルに相当)は、m1.actor~~に直接アクセスすることができる.「backward relationship」(現在の俳優モデルと同じ/関係は現在のモデルで定義されていないが、逆にこのモデルを参照するモデルを探す)に_setを加え、a2.movie_set~~とともに使用する.
FKの位置や正参照、逆参照の説明については良い説明があり、リンク(主にdjango Query Set Api公式ドキュメントのselect related、prefetch relatedに関する内容なので、読んでもいい/後の部分を読んでから探すのも良い方法です).
このように、データベースにデータを入れる機能を遊びましょう.
select * from actors;
select * from movies;
このコマンドで私がリアルタイムで追加したデータを見ることができます.
大量のスタックデータが作成された場合、データへのアクセスと取り出し(?)やってみよう
movies = Movie.objects.all()
# 모든 영화들 가져옴(QuerySet)
actors = Actor.obejcts.all()
# 모든 배우들 가져옴(QuerySet)
for movie in movies:
    print(movie.actor.values())
# 모든 영화들의 출연 배우들을 가져옴(QuerySet)
for actor in actors:
    print(actor.movie_set.values())
# 모든 배우들의 출연 영화를 가져옴(QuerySet)
上記のコードを入力すると、QuerySetタイプの配列に類似した出力結果が表示されます.クエリー・セット(QuerySet)は、渡されたモデルのオブジェクト・リストであり、データベースからのデータの読み取り、フィルタリング、ソートなどの操作に使用できます.
実際、QuerySetに関するすべての内容は上記のリンクで表示できますので、追加の説明は省略します.
私たちがこのアプリを作った目的は、俳優たちのカタログ(映画に出演する名前を含む)と映画のカタログ(俳優たちの名前を含む)を取得することなので、これらの仕事をするために、以下にこれらのコードを添付して、次の文章に移動します.公式ドキュメントや他のブログの助けで理解し、私が書いたコードよりも良いコードを書くことを望んでいます(もっと良い論理と方法があれば、教えてください.ありがとうございます...).
###### for actors GET ######
actors = Actor.objects.prefetch_related('movie_set').all()
results = [
    {
        'first_name': actor.first_name,
        'last_name': actor.last_name,
        'date_of_birth': actor.date_of_birth,
        'movies_list': list(actor.movie_set.values('title'))
    }
    for actor in actors
]

###### for movies GET ######
movies = Movie.objects.prefetch_related('actor').all()
results = [
    {
        'title': movie.title,
        'release_date': movie.release_date,
        'running_time': movie.running_time,
        'actors_list': list(movie.actor.values('first_name'))
    }
    for movie in movies
]