Django Rest Framework의 응답에 중간자(모델을 통해) 포함
장고레스트 프레임워크에서 모델과 그들의 발표를 통해 m2m/를 다루는 것에 대해 질문이 있습니다.고전적인 예를 들어 보겠습니다.
models.py :
from django.db import models
class Member(models.Model):
name = models.CharField(max_length = 20)
groups = models.ManyToManyField('Group', through = 'Membership')
class Group(models.Model):
name = models.CharField(max_length = 20)
class Membership(models.Model):
member = models.ForeignKey('Member')
group = models.ForeignKey('Group')
join_date = models.DateTimeField()
serializers.py :
imports...
class MemberSerializer(ModelSerializer):
class Meta:
model = Member
class GroupSerializer(ModelSerializer):
class Meta:
model = Group
views.py :
imports...
class MemberViewSet(ModelViewSet):
queryset = Member.objects.all()
serializer_class = MemberSerializer
class GroupViewSet(ModelViewSet):
queryset = Group.objects.all()
serializer_class = GroupSerializer
구성원 인스턴스를 가져올 때 구성원의 모든 필드와 그룹을 성공적으로 수신하지만 구성원 모델에서 추가 세부사항 없이 그룹의 세부사항만 수신합니다.
즉, 다음과 같은 혜택을 받을 수 있을 것으로 기대합니다.
{
'id' : 2,
'name' : 'some member',
'groups' : [
{
'id' : 55,
'name' : 'group 1'
'join_date' : 34151564
},
{
'id' : 56,
'name' : 'group 2'
'join_date' : 11200299
}
]
}
join_date를 기록합니다.
저는 물론 그것에 대한 장고 레스트 프레임워크 공식 페이지를 포함하여 너무 많은 해결책을 시도했지만 아무도 그것에 대해 적절한 답을 하지 않는 것 같습니다. 이러한 추가 필드를 포함하려면 제가 무엇을 해야 합니까?저는 장고 맛 파이가 더 간단하다는 것을 알았지만 다른 문제가 있었고 휴식 프레임을 선호했습니다.
그럼...
MemberSerializer에서 다음과 같은 필드를 정의합니다.
groups = MembershipSerializer(source='membership_set', many=True)
그런 다음 구성원 자격 직렬화 프로그램에서 다음을 생성할 수 있습니다.
class MembershipSerializer(serializers.HyperlinkedModelSerializer):
id = serializers.Field(source='group.id')
name = serializers.Field(source='group.name')
class Meta:
model = Membership
fields = ('id', 'name', 'join_date', )
그러면 사용자가 원하는 멤버 자격을 소스로 갖는 일련화된 값, 그룹이 생성되고 사용자 지정 일련화기를 사용하여 표시할 비트가 추출됩니다.
편집: @bryanph가 언급했듯이,serializers.field
로 이름이 변경되었습니다.serializers.ReadOnlyField
DRF 3.0에서는 다음과 같이 표시됩니다.
class MembershipSerializer(serializers.HyperlinkedModelSerializer):
id = serializers.ReadOnlyField(source='group.id')
name = serializers.ReadOnlyField(source='group.name')
class Meta:
model = Membership
fields = ('id', 'name', 'join_date', )
현대적인 실행을 위하여.
저는 이 문제에 직면했고 (DRF 3.6을 사용하여) 제 해결책은 객체에서 SerializerMethodField를 사용하고 Membership 테이블에 다음과 같이 명시적으로 쿼리하는 것이었습니다.
class MembershipSerializer(serializers.ModelSerializer):
"""Used as a nested serializer by MemberSerializer"""
class Meta:
model = Membership
fields = ('id','group','join_date')
class MemberSerializer(serializers.ModelSerializer):
groups = serializers.SerializerMethodField()
class Meta:
model = Member
fields = ('id','name','groups')
def get_groups(self, obj):
"obj is a Member instance. Returns list of dicts"""
qset = Membership.objects.filter(member=obj)
return [MembershipSerializer(m).data for m in qset]
그러면 각 딕트가 MembershipSerializer에서 직렬화된 그룹 키에 대한 딕트 목록이 반환됩니다.쓰기 가능하도록 하려면 MemberSerializer 내에서 입력 데이터를 반복하고 MemberSerializer 모델 인스턴스를 명시적으로 생성하거나 업데이트하는 고유한 생성/업데이트 방법을 정의할 수 있습니다.
저도 같은 문제가 있었는데 결국 그룹 쿼리 세트에 주석을 달아서 해결했습니다.
from django.db.models import F
class MemberSerializer(ModelSerializer):
groups = serializers.SerializerMethodField()
class Meta:
model = Member
def get_groups(self, instance):
groups = instance.groups.all().annotate(join_date=F(membership__join_date))
return GroupSerializer(groups, many=True).data
class GroupSerializer(ModelSerializer):
join_date = serializers.CharField(required=False) # so the serializer still works without annotation
class Meta:
model = Group
fields = ..., 'join_date']
참고: 소프트웨어 엔지니어로서 아키텍처를 사용하는 것을 좋아하고 계층화된 개발 접근 방식에 대해 깊이 연구했기 때문에 계층과 관련하여 답변할 예정입니다.
문제를 이해한 대로 솔루션을 소개합니다. models.py
class Member(models.Model):
member_id = models.AutoField(primary_key=True)
member_name = models.CharField(max_length =
class Group(models.Model):
group_id = models.AutoField(primary_key=True)
group_name = models.CharField(max_length = 20)
fk_member_id = models.ForeignKey('Member', models.DO_NOTHING,
db_column='fk_member_id', blank=True, null=True)
class Membership(models.Model):
membershipid = models.AutoField(primary_key=True)
fk_group_id = models.ForeignKey('Group', models.DO_NOTHING,
db_column='fk_member_id', blank=True, null=True)
join_date = models.DateTimeField()
serializers.py
import serializer
class AllSerializer(serializer.Serializer):
group_id = serializer.IntegerField()
group_name = serializer.CharField(max_length = 20)
join_date = serializer.DateTimeField()
CustomModels.py
imports...
class AllDataModel():
group_id = ""
group_name = ""
join_date = ""
BusinessLogic.py
imports ....
class getdata(memberid):
alldataDict = {}
dto = []
Member = models.Members.objects.get(member_id=memberid) #or use filter for Name
alldataDict["MemberId"] = Member.member_id
alldataDict["MemberName"] = Member.member_name
Groups = models.Group.objects.filter(fk_member_id=Member)
for item in Groups:
Custommodel = CustomModels.AllDataModel()
Custommodel.group_id = item.group_id
Custommodel.group_name = item.group_name
Membership = models.Membership.objects.get(fk_group_id=item.group_id)
Custommodel.join_date = Membership.join_date
dto.append(Custommodel)
serializer = AllSerializer(dto,many=True)
alldataDict.update(serializer.data)
return alldataDict
기술적으로 데이터 액세스 계층에서 필터링된 개체를 반환하는 데이터 액세스 계층에 대한 요청을 전달해야 하지만 질문에 빠른 방식으로 답변해야 하므로 비즈니스 논리 계층에서 코드를 조정했습니다!
언급URL : https://stackoverflow.com/questions/17256724/include-intermediary-through-model-in-responses-in-django-rest-framework
'programing' 카테고리의 다른 글
파이썬에서 문자열 리터럴을 탈출하지 않고 작성하는 방법은 무엇입니까? (0) | 2023.09.04 |
---|---|
CSS: 애니메이션 vs.전이 (0) | 2023.09.04 |
원격 시스템에서 사용할 수 있는 파워셸 스크립트를 실행하는 방법은 무엇입니까? (0) | 2023.09.04 |
공백/빈 공간의 유효성을 검사하는 방법은 무엇입니까?[각도 2] (0) | 2023.09.04 |
@Cacheable 히트 시 스프링 캐시 로깅 (0) | 2023.09.04 |