Django REST 프레임 워크의 중첩 된 리소스에 필터를 적용해야합니까?
내 앱에는 다음 모델이 있습니다.
class Zone(models.Model):
name = models.SlugField()
class ZonePermission(models.Model):
zone = models.ForeignKey('Zone')
user = models.ForeignKey(User)
is_administrator = models.BooleanField()
is_active = models.BooleanField()
Django REST 프레임 워크를 사용하여 영역 세부 정보와 해당 영역에 대한 중첩 된 리소스를 반환하는 리소스를 만듭니다. 출력은 다음과 같아야합니다.
{
"name": "test",
"current_user_zone_permission": {
"is_administrator": true,
"is_active": true
}
}
다음과 같이 serializer를 만들었습니다.
class ZonePermissionSerializer(serializers.ModelSerializer):
class Meta:
model = ZonePermission
fields = ('is_administrator', 'is_active')
class ZoneSerializer(serializers.HyperlinkedModelSerializer):
current_user_zone_permission = ZonePermissionSerializer(source='zonepermission_set')
class Meta:
model = Zone
fields = ('name', 'current_user_zone_permission')
문제는 특정 영역을 포함 할 때 중첩 된 리소스가 해당 영역에 대한 권한이있는 모든 사용자에 대한 ZonePermission 레코드를 반환 하는 것입니다. request.user
중첩 된 리소스 에 필터를 적용하는 방법이 있습니까?
BTW 나는이를 HyperlinkedIdentityField
위해 (http 요청을 최소화하기 위해) 사용하고 싶지 않습니다 .
해결책
이것은 아래 답변을 기반으로 구현 한 솔루션입니다. serializer 클래스에 다음 코드를 추가했습니다.
current_user_zone_permission = serializers.SerializerMethodField('get_user_zone_permission')
def get_user_zone_permission(self, obj):
user = self.context['request'].user
zone_permission = ZonePermission.objects.get(zone=obj, user=user)
serializer = ZonePermissionSerializer(zone_permission)
return serializer.data
솔루션에 대단히 감사합니다!
나는 같은 시나리오에 직면했다. 내가 사용하고있는 SerializerMethodField
해당 메소드 쿼리 를 사용 하고 원하는 값을 반환하는 것입니다. 을 request.user
통해 해당 방법 으로 에 액세스 할 수 있습니다 self.context['request'].user
.
그래도 약간의 해킹처럼 보입니다. 나는 DRF를 처음 접했기 때문에 더 많은 경험을 가진 사람이 참여할 수 있습니다.
대신 필터를 받으세요. 복수의 번호가 반환되면 예외가 발생합니다.
current_user_zone_permission = serializers.SerializerMethodField('get_user_zone_permission')
def get_user_zone_permission(self, obj):
user = self.context['request'].user
zone_permission = ZonePermission.objects.filter(zone=obj, user=user)
serializer = ZonePermissionSerializer(zone_permission,many=True)
return serializer.data
이제 여기에서 어디 방법을 사용하여 ListSerializer를 하위 클래스로 만들 수 있습니다. https://stackoverflow.com/a/28354281/3246023
ListSerializer를 하위 클래스로 생성하여 표현할 수 있습니다.
기본적으로 to_representation 메소드는 중첩 된 쿼리 세트에서 data.all ()을 호출합니다. 따라서 메소드가 호출되기 전에 데이터 = data.filter (** your_filters)를 호출합니다. 그런 다음 하위 클래스 화 된 ListSerializer를 중첩 된 serializer의 메타에 list_serializer_class로 추가해야합니다.
- ListSerializer 하위 클래스, _representation 프로그램 쓰기 및 수퍼 호출
- 중첩 된 Serializer의 메타 list_serializer_class로 서브 클래 싱 된 ListSerializer를 추가합니다.
여러 위치에서 QuerySet / 필터를 사용하는 경우 모델 에서 getter 함수를 다음 Serializer / Field에 대한 'source'kwarg를 사용하는 경우도 있습니다. DRF는get_attribute 함수를 사용할 때 찾으면 자동으로 함수 / 호출 가능을 호출 합니다.
class Zone(models.Model):
name = models.SlugField()
def current_user_zone_permission(self):
return ZonePermission.objects.get(zone=self, user=user)
이 방법은 HTTP를 통한 API를 사용하여 API를 내부에서 일관되게 유지하기 때문에 좋아합니다.
class ZoneSerializer(serializers.HyperlinkedModelSerializer):
current_user_zone_permission = ZonePermissionSerializer()
class Meta:
model = Zone
fields = ('name', 'current_user_zone_permission')
바라건대 이것은 어떤 사람들에게 도움이되기를 바랍니다!
참고 : 이름이 일치 할 필요 는 없습니다 . 필요하거나 원하는 경우 소스 kwarg를 계속 사용할 수 있습니다.
편집 : 방금 모델의 기능이 사용자 나 요청에 액세스 할 수 없다는 것을 깨달았습니다. 따라서 사용자 지정 모델 필드 / ListSerializer가이 작업에 더 적합 할 것입니다.
두 가지 방법 중 하나로 할 것입니다.
1)보기에서 미리 가져 오기를 통해 수행합니다.
serializer = ZoneSerializer(Zone.objects.prefetch_related(
Prefetch('zone_permission_set',
queryset=ZonePermission.objects.filter(user=request.user),
to_attr='current_user_zone_permission'))
.get(id=pk))
2) 또는 .to_representation을 통해 수행하십시오.
class ZoneSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Zone
fields = ('name',)
def to_representation(self, obj):
data = super(ZoneSerializer, self).to_representation(obj)
data['current_user_zone_permission'] = ZonePermissionSerializer(ZonePermission.objects.filter(zone=obj, user=self.context['request'].user)).data
return data
'ProgramingTip' 카테고리의 다른 글
OCaml 프로젝트를 구성하고 빌드하는 데 선호되는 방법은 무엇입니까? (0) | 2020.12.27 |
---|---|
Quartz.NET 구성 파일에 대한 문서는 어디에 있습니까? (0) | 2020.12.27 |
Android에서 최고의 REST 클라이언트 프레임 워크 / 유틸리티 (0) | 2020.12.27 |
Scala : mapValues가 뷰를 생성하는 이유는 무엇이며 대안이 있습니까? (0) | 2020.12.27 |
AsyncTask와 Thread / Runnable의 차이점 (0) | 2020.12.27 |