Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/xpath/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Django 如何使用输入值在序列化程序中获取外键引用_Django_Django Models_Django Rest Framework - Fatal编程技术网

Django 如何使用输入值在序列化程序中获取外键引用

Django 如何使用输入值在序列化程序中获取外键引用,django,django-models,django-rest-framework,Django,Django Models,Django Rest Framework,要创建产品对象,我们只需发送通道obj的id,序列化程序就可以获得引用的对象。 我有一个公开端点的服务,客户端只需发布创建对象的请求。客户端不知道通道ID,它只知道通道的名称 在这种情况下,是否可能有一个序列化程序,其中客户端仍然可以在请求中发送通道名称,但在创建产品obj时在数据库中获得正确的外键引用?有人能给我举一些例子或文档来处理这个问题吗 编辑 如果我在post请求中提供id,视图和序列化程序如下所示 class Channel(models.Model): name = mod

要创建产品对象,我们只需发送通道obj的id,序列化程序就可以获得引用的对象。 我有一个公开端点的服务,客户端只需发布创建对象的请求。客户端不知道通道ID,它只知道通道的名称

在这种情况下,是否可能有一个序列化程序,其中客户端仍然可以在请求中发送通道名称,但在创建产品obj时在数据库中获得正确的外键引用?有人能给我举一些例子或文档来处理这个问题吗

编辑 如果我在post请求中提供id,视图和序列化程序如下所示

class Channel(models.Model):
    name = models.CharField(max_length=20)

class Product(models.Model):
    channel = models.Foreignkey(Channel, on_delete=models.PROTECT)

id | name
-------------
1  | Channel1
2  | Channel2
3  | Channel3
4  | Channel4

请求机构将是

class ProductsViewSet(viewsets.ModelViewSet):
    queryset = models.Product.objects.all()
    serializer_class = serializers.ProductSerializer

class ProductSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Product
        fields = "__all__"
但我希望发送如下请求,但仍然能够使用上面的序列化程序,希望有一些小改动

{
    "channel": 1
}
进一步编辑 下面是Sasja给我的答案。我必须提供一个额外的参数queryset,完整的序列化程序如下所示

{
    "channel": "Channel1"
}
如果要创建引用模型的对象(如果该模型不存在),则必须扩展SlugRelatedField,因为默认情况下它无法创建对象。我发现下面有一个例子


如果我理解正确,您应该在序列化程序上实现.create方法。然后,您可以访问已验证的_数据以获取通道,并创建带有引用的产品

class ProductSerializer(serializers.ModelSerializer):
    channel = serializers.SlugRelatedField(
        many=False,
        read_only=False,
        slug_field='name',
        queryset=models.Channel.objects.all()
    )

    class Meta:
        model = models.Product
        fields = "__all__"
如果要对名称进行搜索,应确保通道模型上的名称字段具有unique=True

供参考:

编辑: 编辑问题后,似乎有一些内置解决方案是默认读/写的SlugRelatedField。另请注意,根据:

当使用SlugRelatedField作为读写字段时,通常需要确保slug字段对应于unique=True的模型字段


您能展示您的序列化程序和视图吗?谢谢您的时间。是的,这就是我想要继续的方式,但我认为由于你已经提到的原因,这有点脆弱。仅当名称与大小写完全匹配时,它才起作用。我有多个序列化程序需要这样做,所以我想避免重复,并想知道是否有任何内置的这种情况。
class CreateProductSerializer(serializers.Serializer):
    name = serializers.CharField(max_length=20)

    def create(self, validated_data):
        name = validated_data.get('name', False)

        # naive implementation, should still handle errors (eg. not found)
        # you need to be sure that only 1 object with that name will exist (see comment below)
        channel = Channel.objects.get(name=name)
        return Product(channel=channel)
class ProductSerializer(serializers.ModelSerializer):
    channel = serializers.SlugRelatedField(
        many=False,
        read_only=False,
        slug_field='name'
    )

    class Meta:
        model = models.Product
        fields = "__all__"