본문 바로가기

IT/Django

[Django-seed] test data 자동 생성 정리

테스트를 해야하는데 언제까지 일일이 손으로 클릭해서 넣거나 스페이스를 눌러가며 입력하기 귀찮았다. 

그래서 데이터를 자동으로 생성해서 편하게 테스트 하기 위해 방법을 검색하다보니 django-seed라는 library를 발견했다. 

 

목표

django-seed를 이용해 company와 1:n 관계를 가진 employee를 생성해, employee와 one-to-one relationship을 가지고 있는 모델의 데이터도 생성한다. 

 

설치

pip install django-seed

설정

INSTALLED_APPS = (
	...,
    'django_seed'
)

 

실행

python manage.py create_employee --number 30 --settings=config.settings.deploy
python manage.py create_polls --number 30 --settings=config.settings.deploy

django manager로 실행할 명령어가 create_employee고 30개를 만들겠다는 의미다. 

또, create_polls로 생성된 employee와 연관된 데이터도 30개 만든다. 

 

number 같은 argument와 settings설정을 줘도 제대로 작동하는 것을 보여준다. 

 


과정

django manager엔 create_employee라는 명령어가 없다. 

만들어줘야 한다. 

 

1. app 내에 model과 동일한 경로에 management/commands 폴더를 생성한다. 

경로 

  • polls
    • management
      • commands
        • create_employee.py (명령어의 이름이 되는 파일)
        • __init__.py
      • __init__.py

2. create_employee.py 

Employee를 생성하는 예제다. 

from django.core.management.base import BaseCommand
from django_seed import Seed
from polls.models import Company
from polls.models Employee
import datetime

class Command(BaseCommand):
	help = 'this command create employee'

	def add_arguments(self, parser):
		parser.add_argument('--number', default=1, type=int)

	def handle(self, *args, **options):
		number = options.get('number')
		com = Company.objects.get(company_id = '...')
        
		seeder = Seed.seeder()
		seeder.add_entity(Employee, number, {
			'company_id': com,
			'created_dt': datatime.datetime.now()
		})

		seeder.excute()

add_arguments 함수를 overriding하면서 초기값, 타입 설정 

default =1 은 1회가 기본이고, 입력이 int라고 알려준다.  

--number 30 할때 30이 여기들어간다. 

 

handle 함수를 overring하면서 원하는 명령어 기능 수행을 한다. 

 

seeder = Seed.seeder()

seeder.add_entity(Employee, number, {'company_id': com,...})

seeder.excute()

 

Employee 모델에 number만큼 데이터를 생성한다. 

값을 정하고 싶거나 커스텀하고 싶을 때, 필드명과 넣고 싶은 값을 넣는다. 

company와 employee는 1:n 관계이므로 모두 동일한 com을 입력으로 해도 괜찮다. 

 

3. create_polls.py 

employee와 1:1관계를 가지고 있는 데이터를 생성한다. 

from django_seed import Seed
from django.core.management.base import BaseCommand
from polls.models import Comany
from polls.models import Employee
from polls.models import Part1, Part2, Part3, Part4, Part5 
import datetime

class Command(BaseCommand):
	def add_arguments(self, parser):
    	parser.add_argument('--number', default=1, type=int)
        
    def handle(self, *args, **options):
    	com = Company.objects.get(company_id = ~)
        number = options.get('number')
        employees = Employee.objects.filter(company_id=com).order_by('-created_dt')[:number]
        employee_list = list(employees)
        
        today = datetime.datetime.today()
        
        seeder = Seed.seeder()
        
        employee_list1 = list(employees)
        seeder.add_entity(Part1, number, {
        	'employee_id': lambda x : employee_list1.pop(0),
        	'created_dt': today,
        	'part1_1': lambda x : random.randrange(1,6),
            'part1_2': lambda x : random.randrange(1,6),
            ...
        })
        employee_list2 = list(employees)
        seeder.add_entity(Part2, number, {
        	'employee_id': lambda x : employee_list2.pop(0),
            'created_dt': today,
            'part2_2': lambda x : random.randrange(1,6),
            ...
            
        })
        
        ...
        
        employee_list5 = list(employees)
        seeder.add_entity(Part5, number, {
        	'gender': lambda x : random.choice(['미혼', '기혼']),
            ...
            
        })
        seeder.execute()

employees = Employee.objects.filter(company_id=com).order_by('-created_dt')[:number]

com에 속한 Employee를 filter로 거르고 created_dt를 내림차순으로 number만큼 정렬한다. 

최근 생성된 30개가 불려온다. 

 

Employee하나에 Part1, ..., Part5가 한개씩 붙어야 하는데, 단순히 생성하면 unique 문제가 계속 발생했다. 

단순하게 'employee_id' : random.choice(...)로 하면 운 좋으면 통과지만 대부분 중복문제가 생긴다.

그래서 employee를 리스트로 만들어서 pop(0)를 사용해 이미 만들어진 employee는 리스트에서 제거해 중복 문제를 해결했다. 

 

seeder.add_entity(Part1, number, {'employee_id': lambda x : employee_list1.pop(0)})

seeder.add_entity(Part1, number, {'employee_id': employee_list1.pop(0)})

은 차이가 있다. 

 

위에는 30개의 Part1가 각각 다른 employee에 연결되어 생성된다. Part1 - A / Part1 - B ... 이런식으로  

아래는 30개의 Part1가 같은 employee에 연결되어 30개 생성된다. Part1 - A * 30 이렇게 

 

따라서 lambda x 의 역할이 중요하다. 

 

'part1_1' : lambda x : random.randrange(1,6) 도 마찬가지다. 

lambda x 를 안하고 random.randrage(1,6) 만하면 30개 Part1의 part1_1필드는 모두 동일하다. 

lambda x 를 해줘야 30개의 part1_1필드가 랜덤하게 다르게 생성된다. 

 

 

'IT > Django' 카테고리의 다른 글

[crontab] django-crontab  (0) 2021.02.20
[python] makedirs, mkdir 차이  (0) 2021.01.14
[ CORS ] Cross Origin 리소스 공유 에러 해결  (0) 2021.01.04
django nginx ssl 적용  (0) 2020.09.23
convert model to sql query  (0) 2020.09.16