2016-08-17 5 views
0

콘텐츠 유형을 저장하기 위해 "content_type"필드를 사용하고 개체 ID를 저장하기 위해 "object_id"를 사용하는 일반 외래 키를 사용하는 모델이 있습니다. 이 모델은 CRUD API로 조작해야하며 DRF를 사용하고 있습니다. 모델에 대한 serializer가 있지만 약간의 문제가 발생합니다. 난 그냥이DRF에서 GenericForeignKey를 직렬화하는 방법은 무엇입니까?

 
class MySerializer(ModelSerializer): 
    class Meta: 
     fields = ('name', 'state', 'content_type', 'object_id') 

같은 필드 목록에 콘텐츠 _를 추가하면 시리얼 라이저는 ContentType이 모델 인스턴스의 ID로 JSON 표현을 설정합니다. API 사용자는이 ID를 모르고 있기 때문에 ContentType 모델을 아직 또 다른 API로 노출하고 싶지 않습니다. API 사용자는 링크하려는 개체 유형을 알고 있으므로 콘텐츠 형식 이름을 보낼 수 있습니다. 그래서, 나는 이런 serializer를 정의했다.

 
class MySerializer(ModelSerializer): 
    content_type = serializers.CharField(source="content_type.name") 
    class Meta: 
     fields = ('name', 'state', 'content_type', 'object_id') 

모델의 직렬화는 잘 동작한다. User 인스턴스를 연결하기 위해 일반적인 관계를 사용하면 {'name': 'test', 'state': 'NY', 'content_type': 'user', 'object_id': 123}과 같은 것을 얻을 수 있습니다. 하지만 JSON 구조체로 PUT 또는 POST 요청을 제출하면 DRF는 이것을 {'name': 'test', 'state': 'NY', 'content_type': {'name': {'name': 'user'}}, 'object_id': 123}과 같은 것으로 변환합니다. 나는 다음과 같이 쓸 수있다

 
    def create(self, validated_data): 
     ct_model = validated_data['content_type']['name']['name'] 
     validated_data['content_type'] = ContentType.objects.get(model=ct_model) 
     return MyModel.objects.create(**validated_data) 

그러나 그것은 임의적이고 연약한 것처럼 보인다. 이 상황을 처리하는 올바른 방법은 무엇입니까?

# 1 업데이트

: 순간, 나는이 코드

 
def to_internal_value(self, data): 
    content_type = data.get('content_type', None) 
    validated_data = super().to_internal_value(data) 
    try: 
     validated_data['content_type'] = ContentType.objects.get(model=content_type) 
    except ContentType.DoesNotExist: 
     raise serializers.ValidationError("invalid content type %s" % content_type) 
    return validated_data 

그것은 추한 해킹의 일종처럼 보인다와 to_internal_value()를 재정 의하여 문제를 해결 한은을 표시해야합니다 관련 개체.

+0

문서에서 해결책을 찾으셨습니까? http://www.django-rest-framework.org/api-guide/relations/#generic-relationships? – mateuszb

+0

솔루션은 사용자 정의 관련 필드 클래스를 정의하는 것으로 보입니다. 나는 그것을 들여다 볼 것이다. 그러나 그것은 복잡한 것처럼 보인다. –

+0

질문에 대한 답변이 있으시면 답변이 아닌 업데이트로 게시하십시오. –

답변

0

이러한 관계를 직렬화하려면 to_representationto_internal_value 메서드를 사용하여 사용자 정의 필드 클래스를 제공해야 할 것입니다. 그것은 그렇게 복잡하지는 않습니다.

직렬화 형식으로 URI 표기 /api/resource/object_id을 사용해보십시오.

콘텐츠 유형을 리소스 uris 및 back로 변환하는 것이 약간의 어려움이있을 수 있지만 가능한 몇 가지 방법이 있어야합니다.

+0

URI를 콘텐츠 유형으로 사용하는 경우, API를 통해 콘텐츠 유형을 노출해야합니다 (장고는 시스템의 모든 모델에 대해 콘텐츠 유형을 생성하므로 권한 및 필터링 문제의 처리를 처리해야합니다). 2. API 사용자는 단일 데이터를 얻기 위해 여러 요청을합니다. –

+0

귀하의 1. 사실이라고 생각하지 않습니다 및 어떻게 어쨌든 사용 권한 및 필터링을 피할 수 있지만 두 경우 귀하의 API를 중첩 된 대신 천천히 대신 여전히 앞서 serializer 메서드를 사용자 지정해야합니다. –

+0

중첩 리소스에 uris를 사용하는 경우 uri를 사용하여 리소스를 가져올 수 있어야합니다. 이 경우 콘텐츠 유형에 uris를 사용하도록 제안 했으므로 콘텐츠 유형에 액세스하기위한 API가 있어야합니다. 그리고 장고는 절대적으로 모든 콘텐츠 유형을 생성하고 API 사용자에게 응용 프로그램의 내부 구조를 공개하고 싶지 않기 때문에 일부 명백하지 않은 방법으로 액세스를 제한해야합니다. 두 번째 부분에서는 내 API를 중첩하지 않습니다. 그러나 내가 그랬다 할지라도, 당신이 그 성과를 판단 할 수있는 위치에 있는지 확신 할 수 없습니다. –

관련 문제