09.-3 seed_rooms

조재훈·2022년 7월 22일

Clone_Airbnb

목록 보기
20/31
post-thumbnail

1) faker

직전에 했던 seed_users를 본받아 진행한다.
rooms - management - commands - seed_rooms.py

from django.core.management.base import BaseCommand
from django_seed import Seed
from rooms import models as models_room
from users import models as models_user

class Command(BaseCommand):

    help = "This command creates many rooms"
    
    def add_arguments(self, parser):
        parser.add_argument(
            "--number",
            default=2,
            type=int,
            help="How many rooms do you want to create?",
        )
    
    def handle(self, *args, **options):
        number = options.get("number")
        seeder = Seed.seeder()
        seeder.add_entity(
            models_room.Room,
            number,
        )
        seeder.execute()
        self.stdout.write(self.style.SUCCESS(f"{number} users created!"))

일단 이 상태에서 실행해보면 아래와 같은 에러가 뜬다.

django_seed.exceptions.SeederException: Field rooms.Room.host cannot be null

ForeignKey는 seeder로 어찌 하기가 힘든 모양이다. 우리가 도와주자.

rooms - management - commands - seed_rooms.py - handle

import random

...


    def handle(self, *args, **options):
        number = options.get("number")
        seeder = Seed.seeder()
        all_users = models_user.User.objects.all()
        seeder.add_entity(
            models_room.Room,
            number,
            {
                'host': lambda x: random.choice(all_users)
            },

실행해보자.

똑같은 문제가 나온다. rooms의 models.py를 보면 RoomType 클래스에 ForeignKey와 ManyToManyField가 몇개 더 정의되어있다. 일단 ForeignKey인 room_type부터 해결해주자.

rooms - management - commands - seed_rooms.py Command - handle

        room_types = models_room.RoomType.objects.all()
        seeder.add_entity(
            models_room.Room,
            number,
            {
                'host': lambda x: random.choice(all_users),
                'room_type': lambda x: random.choice(room_types),
            },
        )
        ...

다행히 실행된다.

'ㅅ' ....

아 이게 문제였구나. 생성된 review가 없다.

그럼 저 부분을 고쳐주도록 하자.
rooms - models.py

    def total_rating(self):
        all_reviews = self.reviews.all()
        all_ratings = 0
        if len(all_reviews) > 0:
            for review in all_reviews:
                all_ratings += review.rating_average()
            return all_ratings / len(all_reviews)
        return 0

잘 생성되었다.

그런데 보면 ManyToManyFields 는 전부 텅텅 비어있다. 이 부분도 설정을 해야겠다. 이름도 너무 길고.
그리고 가격이 음수인것도 그런데 침대가 2600개가 넘다니. 공장인줄? 숫자 범위도 조절하자.
우선 주소같은 텍스트는 faker 기능을 이용할 수 있다.

https://github.com/joke2k/faker/
rooms - management - commands - seed_rooms.py - Command - handle

            {
                "name": lambda x: seeder.faker.address(),
                "price": lambda x: random.randint(1000, 1000000),
                "guests": lambda x: random.randint(1, 20),
                "beds": lambda x: random.randint(1, 10),
                "bedrooms": lambda x: random.randint(1, 5),
                "baths": lambda x: random.randint(1, 5),
            }

이제 확인해보면 잘 되는걸 볼 수 있다.

근데 보면 rooms에서는 name과 address 속성이 따로 있는데 둘이 주소가 다르게 나온다?

2) Photos

일단 인강 사이트에서 사진들이 저장된 목록을 다운받았다. 이 사진들을 upload안의 rooms_photo에 넣는다.

seeder.execute()는 입력된 리스트들의 PrimaryKey를 반환한다.

그 키들을 받아와보자.
rooms - management - commands - seed_rooms.py - Command

        created_photos = seeder.execute()
        print(created_photos.values())


이걸 리스트로 바꿔서 받으면

        created_photos = seeder.execute()
        print(listcreated_photos.values()))


이중 리스트니까 안에 있는 숫자만 받아오자. 이거는 장고의 flatten 이란 기능을 쓸 것이다. 이제 갓 생성된 room들의 pk가 줄줄이 나오게 된다.

from django.contrib.admin.utils import flatten

...

class Command(BaseCommand):

	...
    
    created_photos = seeder.execute()
    created_clean = flatten(list(created_photos.values()))
    print(created_clean)
    ...

사진의 id가 출력되었다.

그럼 마저 짜보자.
사진은 최소 3장에서 10~17장 사이가 되도록 하고
models.py에 정의되어있던 Photo 클래스의 변수들에 대해서도 각각 어떻게 설정할 것인지 정해준다. caption은 그냥 아무 문장이나 갖다 쓰도록, room은 위에서 pk를 통해 얻은 room 인스턴스, file은 사진파일 경로.

        created_photos = seeder.execute()
        created_clean = flatten(list(created_photos.values()))
        for pk in created_clean:
            room = models_room.Room.objects.get(pk=pk)
            for i in range(3, random.randint(10, 17)):
                models_room.Photo.objects.create(
                    caption=seeder.faker.sentence(),
                    room=room,
                    file=f"/room_photos/{random.randint(1,32)}.webp",
                )
            self.stdout.write(self.style.SUCCESS(f"{number} rooms created!"))


이제 좀 상식적인 값들이 들어갔다. 사진도 링크 눌러보면 잘 열린다.

3) ManyToManyField

amenities, facilities, rules
rooms - management - commands - seed_rooms.py - Command - handle

        for pk in created_clean:
            room = models_room.Room.objects.get(pk=pk)
            for a in amenities:
                magic_number = random.randint(0, 15)
                if magic_number % 2 == 0:
                    room.amenities.add(a)

새로 생성된 Room을 들어가보면 Amenities가 적당히 잘 차있다.

facilities와 house_rules 도 추가해주자.

        for pk in created_clean:
            room = models_room.Room.objects.get(pk=pk)
            for f in facilities:
                magic_number = random.randint(0, 15)
                if magic_number % 2 == 0:
                    room.facilities.add(f)
            for r in rules:
                magic_number = random.randint(0, 15)
                if magic_number % 2 == 0:
                    room.house_rules.add(r)

잘된다!

profile
맨땅에 헤딩. 인생은 실전.

0개의 댓글