DRF中POST创建新Beer对象关联已有对象报错问题
Django DRF创建Beer对象时关联已有BeerType/Brewery的问题及后续疑问
问题场景
我是Django和Django Rest Framework(DRF)新手,在通过POST请求创建新的Beer对象时,尝试关联已存在的BeerType和Brewery对象遇到了问题。
Beer模型定义
class Beer(models.Model): id = models.BigAutoField(primary_key=True) name = models.CharField(max_length=255) brewery = models.ForeignKey(Brewery, on_delete=models.CASCADE) beer_type = models.ForeignKey(BeerType, on_delete=models.PROTECT) class Meta: db_table = "beer"
BeerSerializer定义
class BeerSerializer(serializers.ModelSerializer): brewery = BrewerySerializer() beer_type = BeerTypeSerializer() class Meta: model = Beer fields = ['id', 'name', 'brewery', 'beer_type'] def create(self, validated_data): brewery_data = validated_data.pop('brewery') beer_type_data = validated_data.pop('beer_type') beer = Beer.objects.create(**validated_data) beer.brewery = Brewery.objects.get_or_create(**brewery_data) beer.beer_type = BeerType.objects.get_or_create(**beer_type_data) return beer
BeerViewSet的create方法
class BeerViewSet(viewsets.GenericViewSet): permission_classes = [permissions.IsAuthenticated] serializer_class = BeerSerializer ... def create(self, request): pdb.set_trace() serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True) serializer.save() return Response(serializer.data, status=status.HTTP_201_CREATED)
POST请求数据
{ "beer_type": { "id": 154, "name": "Beer Type 1" }, "brewery": { "country": "c1", "id": 929, "location": "l1", "name": "Brewery1" }, "name": "Beer1" }
错误响应
{ "beer_type": { "name": [ "beer type with this name already exists." ] } }
该BeerType确实已存在,但我希望创建新Beer对象时直接关联已有对象,请问哪里出错了?
更新1:修改后的代码
根据建议修改了序列化器:
class BeerSerializerGet(serializers.ModelSerializer): brewery = BrewerySerializer() class Meta: model = Beer fields = ['id', 'name', 'brewery', 'beer_type'] depth = 1 validators = [] class BeerSerializerCreate(BeerSerializerGet): brewery = PrimaryKeyRelatedField(queryset=Brewery.objects)
同时修改了ViewSet,通过传入的ID获取已有对象:
class BeerViewSet(viewsets.GenericViewSet): permission_classes = [permissions.IsAuthenticated] def list(self, request): queryset = Beer.objects.all() serializer_context = {'request': request} serializer = BeerSerializerGet(queryset, many=True, context=serializer_context) return Response(serializer.data) def retrieve(self, request, pk=None): queryset = Beer.objects.all() beer = get_object_or_404(queryset, pk=pk) serializer_context = {'request': request} serializer = BeerSerializerGet(beer, context=serializer_context) return Response(serializer.data) def create(self, request): beerName = request.data['name'] pdb.set_trace() breweryId = request.data['brewery_id'] beerTypeId = request.data['beer_type_id'] brewery = get_object_or_404(Brewery.objects.all(), pk=breweryId) beerType = get_object_or_404(BeerType.objects.all(), pk=beerTypeId) beer = Beer.objects.create(name = beerName, brewery=brewery, beer_type=beerType) serializer_context = {'request': request} serializer = BeerSerializerGet(beer, context=serializer_context) return Response(serializer.data, status=status.HTTP_201_CREATED)
更新2:疑问
我发现上述代码并未使用两个不同的序列化器,仅使用了GET序列化器,由ViewSet处理关联对象的获取,请问这是否属于不良实践?还是一种可行的方案?
内容的提问来源于stack exchange,提问作者Svend Hansen
相关产品推荐
相关产品推荐

