Django - M to M relationship

Sinjae Lee·2021년 6월 23일
0

참조 django
https://docs.djangoproject.com/en/3.1/topics/db/examples/many_to_many/

문제

영화와 배우의 관계를 나타내는 데이터 모델을 작성하고 불러오는 로직을 짜봐라

요점

배우 A는 영화a, 영화b 에 출연 가능하며
영화a 에는 배우 A, 배우 B가 출연할 수 있다.

지금은 단순한 예제이지만 실제로 쓰이는
Many to Many 의 데이터 관계에는 테이블이 복잡하게 얽혀 있을 수 있다.

코드

Model

class Actor(models.Model):
    first_name = models.CharField(max_length=20)
    last_name = models.CharField(max_length=20)
    date_of_birth = models.DateField()
    movie = models.ManyToManyField("Movie", related_name="movies")
    
    class Meta:
        db_table = "actor"    
    
    
class Movie(models.Model):
    title = models.CharField(max_length=100)
    release_date = models.DateField()
    running_time = models.IntegerField()
    
    class Meta:
        db_table = "movie"

View
일단 view 로직을 짜기 전에 shell에서 찍어보자
actor 객체에서 movie

movie 객체에서 actor 객체는?
원래라면 obj_set. 을 통해 접근해야하지만 Actor model을 작성할때 ManyToManyField에 related name을 부여해줬으므로 해당 related name으로 접근가능하다. (해당 model에서 부여된 related name은... 할 말이 없다 movies라고 주다니 뇌절)

마지막은 기왕 부르는거 깔끔하게 부르고 싶어봐서 저렇게 해봤다

class ActorView(View):
    def get(self, request):
        results = []
        actors = Actor.objects.all()
        for actor in actors:
            movies = actor.movie.all()
            print("actor:", actor.first_name)
            results.append(
                {
                    "first_name": actor.first_name,
                    "last_name": actor.last_name,
                    "date_of_birth": actor.date_of_birth,
                    "movie": [movie.title for movie in movies],
                }
            )

        return JsonResponse({"resutls": results}, status=200)


class MovieView(View):
    def get(self, request):
        results = []
        movies = Movie.objects.all()

        for movie in movies:
            actors = movie.movies.all()
            results.append(
                {
                    "title": movie.title,
                    "release_date": movie.release_date,
                    "runnig_time": movie.running_time,
                    "actors": [actor.first_name for actor in actors],
                }
            )

        return JsonResponse({"resutls": results}, status=200)

shell 로 찍어본 로직 view page 로 옮기면 이렇게 작성할 수 있다.

request - response

httpi를 통해 request 날려보자
MovieView

ActorView

이렇게 ManyToManyField 를 사용하면 객체의 접근이 용이하다.
그리고 relataed name 과

만약 ForiengKey를 사용했으면 어떻게 했을까?

다음은 멍멍이와 주인의 상관관계에 대한 데이터 모델이다

class Owner(models.Model):
    name = models.CharField(max_length=20)
    email = models.CharField(max_length=300)
    age = models.IntegerField()

    class Meta:
        db_table = "owner"


class Dog(models.Model):
    owner = models.ForeignKey("Owner", on_delete=CASCADE)
    name = models.CharField(max_length=45)
    age = models.IntegerField()

    class Meta:
        db_table = "dog"

주인이 여러마리의 멍멍이를 키울 수 있으니 멍멍이가 owner의 foreignkey 를 가지고 있다.

view 로직이다.

class OwnerView(View):
    def post(self, request):
        data = json.loads(request.body)
        
        Owner.objects.create(
            name  = data["owner_name"], 
            email = data["owner_email"], 
            age   = data["owner_age"]
        )
    
        return JsonResponse({'MESSAGE':'SUCCESS'}, status=201)


    def get(self, request):
        owners = Owner.objects.all()
        results = []
        for owner in owners:
            dogs_list = []
            dogs = Dog.objects.filter(owner=owner)
            for dog in dogs:
                dogs_list.append({
                    "dog_name" : dog.name,
                    "dog_age" : dog.age, 
                })               
                
            results.append({
                "owner_name" : owner.name,
                "owner_email" : owner.email,
                "owner_age" : owner.age,
                "dog"       : dogs_list,
                })

        return JsonResponse({'resutls':results}, status=200)


class DogView(View):
    def post(self, request):
        data = json.loads(request.body)

        Dog.objects.create(
            name = data["dog_name"],
            age = data["dog_age"],
            owner = Owner.objects.create(
                name=data["owner_name"],
                email=data["owner_email"],
                age=data["owner_age"]
                )
        )

        return JsonResponse({'MESSAGE':'SUCCESS'}, status=201)

    def get(self, request):
        dogs = Dog.objects.all()
        results=[]
        for dog in dogs:
            results.append(
                {
                "dog_name"  : dog.name,
                "dog_age"   : dog.age,
                "owner_name": dog.owner.name,
            })

        return JsonResponse({'resutls':results}, status=200)
profile
Back-end developer

0개의 댓글