본문 바로가기

코딩/장고

장고에서 공통코드를 처리하는 법

스프링에서 mybatis로 쿼리를 짜서 할때는 공통테이블을 따로 만들고 조인을 해서 코드를 처리하였는데

orm에서는 이 부분을 처리하기가 애매했다.

그래서 검색을 해보니 

www.inflearn.com/questions/16873

 

코드테이블 조인방법이 궁금합니다. - 인프런

질문 - 코드테이블 조인방법이 궁금합니다. 안녕하세요. 강의 잘 듣고있습니다. 질문은, 회사에서 Query를 작성하다보면 코드테이블을 여러번 join 하는 경우가 허다한데요. a join code 처럼 a 테이블

www.inflearn.com

이런 글이 있었고 마침 장고에서도 enum을 지원하고 있어 적용해봤다.

 

# model.py

class Student(models.Model):
    class YearInSchool(models.TextChoices):
        FRESHMAN = 'FR', _('Freshman')
        SOPHOMORE = 'SO', _('Sophomore')
        JUNIOR = 'JR', _('Junior')
        SENIOR = 'SR', _('Senior')
        GRADUATE = 'GR', _('Graduate')

    name = models.CharField(max_length=200, null=True)
    address = models.CharField(max_length=200, null=False, default="seoul")
    year_in_school = models.CharField(
        max_length=2,
        choices=YearInSchool.choices,
        default=YearInSchool.FRESHMAN,
    )

 

 

# views.py (1)

class StudentView(generics.ListCreateAPIView): 
    serializer_class = StudentSerializer

    def get_queryset(self):
        return

    def get(self, request):
        students = Student.objects.all()
        
        serializer = StudentSerializer(students, many=True).data
        return Response(serializer)


(2)
class StudentView(generics.ListCreateAPIView):
    serializer_class = StudentSerializer

    def get_queryset(self):
        return

    def get(self, request):
        students = Student.objects.all()
        students = students.values('year_in_school')

        serializer = StudentSerializer(students, many=True).data
        return Response(serializer)
        
        
        

 

대충 이렇게 적용해주면 

[
    {
        "id": 1,
        "name": "김철수",
        "address": "서울시 중구",
        "year_in_school": "FR"
    },
    {
        "id": 2,
        "name": "안영희",
        "address": "서울시 강동구",
        "year_in_school": "SO"
    }
]

이렇게 나오고

 

# serializers.py (1) 쿼리셋에 모델이 있을 때

class StudentSerializer(serializers.ModelSerializer):
    year_in_school = serializers.CharField(source='get_year_in_school_display')

    class Meta:
        model = Student
        fields = '__all__'
        

# serializers.py (2) 쿼리셋에 모델이 없을 때
def get_enum_field_display(klass, field, value):
    f = klass._meta.get_field(field)
    return dict(f.flatchoices).get(value, value)   
    
class StudentSerializer(serializers.ModelSerializer):
    year_in_school = serializers.CharField(source='get_year_in_school_display')

    class Meta:
        model = Student
        fields = '__all__'

    def get_year_in_school(self, obj):
        return get_enum_field_display(TblistData, 'year_in_school', obj['year_in_school'])


     

serializers.py에서 get_foo_display 이런식으로 추가를 해주면 된다 -- (1)

만약에 쿼리셋이 바뀌면 

Got KeyError when attempting to get a value for field `field_name` on serializer `serializer_name`. 

이런 에러가 날 수 있는데 이때는 모델에서 enum을 따로 조회해서 처리해야 한다 -- (2)

 

# json
[
    {
        "id": 1,
        "year_in_school": "Freshman",
        "name": "김철수",
        "address": "서울시 중구"
    },
    {
        "id": 2,
        "year_in_school": "Sophomore",
        "name": "안영희",
        "address": "서울시 강동구"
    }
]

# db

1	"FR"	"서울시 중구"	"김철수"
2	"SO"	"서울시 강동구"	"안영희"

 

만약 enum을 조회하고 싶다면

 

# views.py

def get_enum_Field_display(klass, field):
    f = klass._meta.get_field(field)
    return dict(f.flatchoices)

class StudentEnumList(generics.ListAPIView):
    def get(self, request):
        result = get_enum_Field_display(Student, "year_in_school")
        return Response(result)
        
# json

{
    "FR": "Freshman",
    "SO": "Sophomore",
    "JR": "Junior",
    "SR": "Senior",
    "GR": "Graduate"
}

이런식으로 사용하면 된다.