Я знаю, что в этой теме уже есть ответ, но я начал работать над решением этой проблемы, и, поскольку этот пост был одним из моих источников вдохновения, я хотел бы поделиться своим окончательным решением. Это может быть полезно кому-то. У меня есть модели, поэтому родительский класс:
#parent model class
class Parent(models.Model):
id = models.AutoField(primary_key=True)
field = models.CharField(max_length=45)
class Meta:
managed = False
db_table = 'parent'
затем дочерний класс:
#child model class
class Child(models.Model):
id = models.AutoField(primary_key=True)
field = models.CharField(max_length=45)
parent = models.ForeignKey(Parent, related_name='children')
class Meta:
managed = False
db_table = 'child'
Мне пришлось определить сериализаторы, так как я не хотел создавать URL-адрес, доступный для маршрутизатора, для прямого управления дочерними объектами, но я хотел создать их через ModelViewSet родительского ModelViewSet, это то, что мне нужно:
class ChildSerializer(serializers.ModelSerializer):
class Meta:
model = Child
read_only_fields = ('id',)
class ParentSerializer(serializers.ModelSerializer):
class Meta:
model = Banner
read_only_fields = ('id',)
class ParentSerializerNested(ParentSerializer):
children = ChildSerializer(many=True)
Затем я был готов создать ModelViewSet, переопределив/расширив миксины создания/обновления и сделав его универсальным, чтобы повторно использовать его для других случаев:
class ParentChildViewSet(viewsets.ModelViewSet):
def create(self, request, *args, **kwargs):
serializer = self.serializer_parent(data=request.DATA,
files=request.FILES)
try:
if serializer.is_valid():
with transaction.commit_on_success():
self.pre_save(serializer.object)
parent = serializer.save(force_insert=True)
self.post_save(parent, created=True)
# need to insert children records
for child in request.DATA[self.child_field]:
child[self.parent_field] = parent.id
child_record = self.serializer_child(data=child)
if child_record.is_valid():
child_record.save(force_insert=True)
else:
raise ValidationError('Child validation failed')
headers = self.get_success_headers(serializer.data)
serializer.data[self.child_field] = self.serializer_child(
self.model_child.objects.filter(
**{self.parent_field: parent.id}).all(),
many=True).data
return Response(serializer.data,
status=status.HTTP_201_CREATED,
headers=headers)
except ValidationError:
pass
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
Поэтому я могу повторно использовать его для каждого случая вложенных отношений, который у меня есть в моем приложении, например:
class ParentViewSet(ParentChildViewSet):
child_field = 'children'
parent_field = 'parent'
model = Parent
model_child = Child
serializer_class = ParentSerializerNested
serializer_parent = ParentSerializer
serializer_child = ChildSerializer
И, наконец, маршрутизация:
router = routers.DefaultRouter()
router.register(r'parents', ParentViewSet)
Работает как часы!
person
gigaDIE
schedule
22.05.2014