각 유저는 스쿼드를 생성하고, 이를 관리할 수 있어야한다.
스쿼드는 크게 포메이션 별로 나누어지고, 각각의 포지션마다 선수들을 세울 수 있어야 할것이다.
따라서 스쿼드는 다음과 같은 데이터를 갖고 있어야한다.
MongoDB 에서는 배열 데이터를 지원하기 때문에 선수단, players 를 쉽게 구현할 수 있을 것이다.
일단 squad 앱을 생성하고 시작한다.
django-admin startapp squad
포메이션, 포지션의 종류는 정해져있기 때문에 Enum 타입으로 생성한다.
#squad/models.py
from djongo import models
class Position(models.Choices):
GK = "GK"
LB = "LB"
LWB = "LWB"
LM = "LM"
LW = "LW"
CB = "CB"
RB = "RB"
RWB = "RWB"
RM = "RM"
RW = "RW"
CDM = "CDM"
CM = "CM"
CAM = "CAM"
CF = "CF"
ST = "ST"
class Formation(models.TextChoices):
F442 = "4-4-2"
F433 = "4-3-3"
F41212 = "4-1-2-1-2"
F352 = "3-5-2"
...
스쿼드는 최종적으로 Player 와 포지션이 매핑 되어있는 배열을 가져야 하기 때문에, 각각의 값을 가지고있는 class 를 정의한다.
#squad/models.py
class player_in_sqaud(models.Model):
#enum 으로 선언한 Position 값을 갖도록한다.
position = models.CharField(choices=Position.choices, default=Position.ST, max_length=5,null=False)
playerId = models.PositiveIntegerField(null=False,default=0)
class Meta: # 실질적으로 DB 에 값이 들어갈 필요가 없기 때문에 추상으로 선언한다.
abstract = True
MongoDB 에 저장될때 배열의 값이 Document 형식으로 저장되기 때문에, 이를 변형시켜 줄 From 을 정의 한다.
#squad/models.py
class Player_Position_Form(forms.ModelForm):
class Meta:
model = player_in_sqaud
fields = (
'position', 'playerId'
)
최종적으로 Squad 의 Model 을 정의한다.
#squad/models.py
class Squad(models.Model):
name = models.CharField(max_length=20,default='My Squad')
own_user = models.ForeignKey(User, on_delete=models.CASCADE) # 스쿼드 소유자
formation = models.CharField(choices=Formation.choices, default=Formation.F442,max_length=20) # enum 으로 선언한 포메이션
players = models.ArrayField(
model_container=player_in_sqaud, #값을 가질 객체
model_form_class=Player_Position_Form, #객체의 From
default=list()
)
objects = models.DjongoManager()
⚠️ 이제 Migration 을 하고 저장, 호출하는 로직을 실행하면 된다…
고 생각했는데, 저장은 정상작동하는데 호출, Squad.objects.* 이 정상작동하지 않는다.
Abstract models cannot be instantiated for models for retrieving data
에러가 발생한다.**
검색해보니, Django 와 djongo 버전이 맞지 않아서 발생하는 문제다.
Django 4.0.6 버전을 사용하고 있었는데, 3.1.12 로 변경한다.
pip uninstall django
pip install django==3.1.12
외부 라이브러리를 많이 사용하다 보니 생각보다 버전에 따른 호환 문제가 자주 발생하는 것 같다.
Djongo 의 ArrayFiled 를 사용하는 방법은
Using Djongo Array Model Field - Djongo (djongomapper.com) 를 참고하였다.