N:M 관계의 두 모델이 있다. Device 모델이 Group 모델에 대해 realted_name='devices'라고 정의하였기 때문에, Group Object는 'devices'라는 이름으로 관련된 Device 객체들에 접근할 수 있다.
class Group(models.Model):
name = models.CharField(max_length=32, null=True)
class Device(models.Model):
name = models.CharField(max_length=32, null=True)
owner = models.ForeignKey(UserModel, on_delete=models.CASCADE)
group = models.ManyToManyField(Group, related_name='devices')
Group을 Serializer하면서 관련된 Device들과 Device의 Owner의 정보까지 한 번에 Serializer하려고 한다.
그러려면 해당 필드들을 Nested Serializer로 정의해야 한다. GroupSerializer 수행 시 1+N Select 증상이 발생하지 않도록 하려면 관련 객체들을 모두 Prefetch 해둬야 한다.
queryset = Group.objects.filter(name='my_group')
queryset = queryset.prefetch_related('devices')
queryset = queryset.prefetch_related('devices__owner')
serializer = GroupSerializer(queryset, many=True)
print(serializer.data)
Group Serializer의 구현을 보면... queryset에 관련 객체들이 prefetch 되어있기 때문에 DeviceSerializer와 UserSerializer 수행 시 별도로 select를 수행하지 않는다.
class GroupSerializer(serializers.ModelSerializer):
devices = DeviceSerializer(many=True)
class Meta:
model = Group
fields = ('id', 'name', 'devices')
class DeviceSerializer(serializers.ModelSerializer):
owner = UserSerializer(many=True)
class Meta:
model = Device
fields = ('id', 'name', 'owner')
serializer.SerializerMethodField를 사용하여 prefetch된 데이터를 가공하려는 경우를 보자.
마찬가지로 group.devices.all()을 호출했지만 실제로는 select가 발생하지 않고 prefetch된 데이터를 사용한다.
class GroupSerializer(serializers.ModelSerializer):
devices = serializers.SerializerMethodField('get_devices_prefetch_related')
def get_devices_prefetch_related(self, group):
devices = group.devices.all()
datas = []
for device in devices:
data = {'id': device.id, 'name':device.name}
datas.append(data)
return datas
class Meta:
model = Group
fields = ('id', 'name', 'devices')
'Django' 카테고리의 다른 글
PyCharm manage.py 메뉴가 사라진 경우 (0) | 2018.06.21 |
---|---|
Django logger 설정 (0) | 2018.05.10 |
Django Custom Auth (로그인 인증, API 인증) (0) | 2017.01.24 |
Django Rest Framework 인증 관련 설정 (0) | 2017.01.23 |
윈도우에서 django mysql 설정하기 (0) | 2015.12.27 |