TIL #14 CRUD(M2M)

21937 ワード

実装したいテーブルの形式は同じであるが,例として異なるデータ変数やタイプなどを選択した.

M 2 MからForeignKeyへ


「モデル」フィールドでForeignKeyを使用する場合は、2つのテーブルを接続するために中間テーブルモデルを追加する必要があります.
models.py
まず、2つのテーブルを接続するには、classで中間テーブルモデルを宣言する必要があります.
class Actor(models.Model):
    name = models.CharField()
    age  = models.IntegerField()
    
class Movie(models.Model):
    title = models.CharField()
    score = models.IntegerField()

class MovieActor(models.Model):      # 중간 테이블
    actor = models.ForeignKey('Actor', on_delete=models.CASCADE)
    movie = models.ForeignKey('Movie', on_delete=models.CASCADE)
  • MovieActorという中間テーブルを作成し、ActorとMovieをFKに接続します.
  • shell CREATE
    In [1]: a1 = Actor.objects.create(name='Bob', age=12)
    In [2]: m1 = Movie.objects.create(title='Armageddon',score='5')
    In [3]: MovieActor.objects.create(actor=a1, movie=m1)
  • は、このように各クラスをa 1、m 2に含め、その変数をMovieActorに宣言する.
  • shell READ
    In [1]: a1 = Actor.objects.get(id=1)
    
    #중간테이블 이름 together라고 가정.
    #_set은 역참조를 의미
    In [2]: a1.together_set.all()
    Out[3]: <QuerySet [<MovieActor: MovieActor object (1), <MovieActor: MovieActor object (2)>]
    
    In [4]: a1.together_set.get(id=1).movie
    Out[5]: <Movie: Movie object (1)>
    
    In [6]: a1.together_set.get(id=1).movie.name
    Out[7]: 'Armageddon'
  • 俳優のアイデンティティ>>together中間テーブルのmovie ForegnKeyによって>>movieクラスアクセス>>nameを見つけ、
  • を返します.
  • の中間テーブルを通る必要があるトラブルがあります.
  • M 2 MからManyToManyFieldへ


    このフィールドを使用すると、2つのテーブルを接続する中間テーブルが宣言されないようにします.
    models.py
    class Actor(models.Model):
        name = models.CharField()
        age  = models.IntegerField()
    
    class Movie(models.Model):
        title  = models.CharField()
        score  = models.IntegerField()
        actors = models.ManyToManyField(Actor, related_name='movies')
  • Movieは、Actorを参照する関数をactorとして宣言します.
  • related nameはオプションですが、入れやすいです.GETの場合、マクロベースがMovieを逆参照するときにその部分を空にした場合、set.all()と呼ぶべきです.下の景色pyで例を見てみましょう.
  • shell CREATE
    In [1]: a1 = Actor.objects.create(name='Bob', age=12)
    In [2]: m1 = Movie.objects.create(title='Armageddon',score='5')
    In [3]: m1.actors.add(a1) #Movie 아마게돈에 Actor 밥을 넣어주었다.
    In [4]: m1.save()         ###### 잊지말고 하자.. 안그럼 저장이 안됨.
  • 逆a 1.movies.add(m 1)でもいいです.
    名前が関連付けられていない場合、a 1.movie_set.add(m1)
  • SHELL READ
    In [1]: m1 = Movie.objects.get(id=1)
    In [2]: m1.actors.get()   #하나의 actor를 참조했을 경우 가능. 만약 둘 이상이면 get()안에 특정 actor의 id값을 넣어줘야 한다.
    Out[3]: <Actor: Actor object (1)>
    -------또는-------
    In [2]: m1.actors.all()   #이렇게하면 m1에 해당하는 actor들을 불러온다.
    Out[3]: <QuerySet [<Actor: Actor object (1)>, <Actor: Actor object (2)>]>
    
    In [4]: m1.actors.get().name   #값이 하나일 경우.
    Out[5]: 'Bob'
    -------또는--------
    In [4]: m1.actors.get(id=1).name  #2개 이상일시 지정함.  or m1.actors.get(name='Bob')
    Out[5]: 'Bob'                                       or <Actor: Actor object (1)>
    views.py (GET)
    ActorはMovieのtitleを参照しようとしています.
    class ActorView(View):
        def get(self, request):
        	actors = Actor.objects.all()
            
           	result = []
            for actor in actors:
                movies = actor.movies.all()   #이 부분.
                movies_list = []
                for movie in movies:
                	movies_info = {
                    	'title' : movie.title
                        }
                    movies_list.append(movies_info)
             actor_info = {
                'name'   : actor.name
                'age'    : actor.age
                'movies' : movies_list
                }
             result.append(actor_info)
         return JsonResponse({'result'}, result}, status=200)
  • 関連するnameが上に指定されていない場合、この部分はmovies = actor.actor_set.all()であるべきである.actor変数が逆参照されることを示します(クラスですが、前は小文字).
  • とは対照的に、MovieはActorを参照するときに変数をActorとして定義しているので、actors = movie.actors.all()と呼ぶことができる.
  • 注意事項:ManyToManyFiledは、参照するクラス関数の下にあるクラスにある必要があります.
    つまり、ManyToManyFieldをClass ActorViewに入れる場合は、まずClass MovieViewを宣言する必要があります.
  • n/a.結論


  • ForeignKeyFieldを使用する場合は、中間テーブルを作成する必要があります.

  • python shellのCRUDデータは、テーブルに到達するには中間テーブルを通過する必要があります.

  • ManyToManyKeyを使用して正逆参照を行うと、中間テーブルが自動的に作成されます.

  • CRUD中間テーブルはできませんが、参照テーブルの値を呼び出すと、中間テーブルを介さずにshellから比較的簡単にデータを追加および削除できます.