Django - 带有序列化程序的可选字段

Posted

技术标签:

【中文标题】Django - 带有序列化程序的可选字段【英文标题】:Django - Optional field with Serializer 【发布时间】:2021-07-11 18:02:26 【问题描述】:

我想在使用序列化程序的 create 方法时自动生成模型的“路径”字段。否则,我希望能够在我的请求中传递此字段,以便稍后对其进行修改。 我还没有找到使模板的单个字段可选的方法。 这是我的模型:

models.py

class Shop(models.Model):
    name = models.CharField(max_length=255)
    category = models.ForeignKey(ShopCategory, on_delete=models.SET_NULL, null=True, blank=True)
    description = models.TextField(blank=True, null=True)
    path = models.CharField(max_length=255, unique=True)
    mustBeLogged = models.BooleanField(default=False)
    deliveries = models.FloatField(default=7)

    def __str__(self):
        return self.name

这是我的代码:

serializer.py

class ShopSerializer(serializers.ModelSerializer):
    class Meta:
        model = Shop
        exclude = ['path']

    def create(self, validated_data):
        path = validated_data["name"].replace(" ", "-").lower()
        path = unidecode.unidecode(path)
        unique = False
        while unique == False:
            if len(Shop.objects.filter(path=path)) == 0:
                unique = True
            else:
                # Generate a random string
                char = "abcdefghijklmnopqrstuvwxyz"
                path += "-".format("".join(random.sample(char, 5)))
        shop = Shop.objects.create(**validated_data, path=path)
        shop.save()
        return shop

views.py

def post(self, request):
        """For admin to create shop"""
        serializer = ShopSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        return Response(serializer.errors)

【问题讨论】:

这部分我没看懂:if len(Shop.objects.filter(path=path)) == 0: @Neeraj 我检查是否已经有相同的路径,并根据它在后面添加一个字符串(因为链接必须是唯一的) 你不能保存路径吗?你在 serailizer 中做得正确你的代码有什么问题? @Neeraj 是的,我的代码适用于 create 方法,但我想设置一个 PUT 方法,重用相同的序列化程序来更改路径 @Neeraj create 方法是唯一不需要在参数中传递路径的方法 【参考方案1】:

您可以将路径设置为 Null 并在 create 方法中弹出它。这样就不用在exclude中添加了。

class ShopSerializer(serializers.ModelSerializer):
    path = serializers.CharField(allow_blank=True, allow_null=True)
    
    class Meta:
        model = Shop
        fields = '__all__'

    def create(self, validated_data):
        validated_data.pop('path')
        path = validated_data["name"].replace(" ", "-").lower()
        path = unidecode.unidecode(path)
        unique = False
        while unique == False:
            if len(Shop.objects.filter(path=path)) == 0:
                unique = True
            else:
                # Generate a random string
                char = "abcdefghijklmnopqrstuvwxyz"
                path += "-".format("".join(random.sample(char, 5)))
        shop = Shop.objects.create(**validated_data, path=path)
        shop.save()
        return shop
    
    def update(self, instance, validated_data):
        #You will have path in validated_data
        #And you may have to check if the values are null
        return super(ShopSerializer, self).update(instance, validated_data)

除此之外,在您的代码中:

while unique == False:
                if len(Shop.objects.filter(path=path)) == 0:

这将是非常昂贵的操作。在每个循环中它都会触发一个查询,我不确定它背后的逻辑,但您可能想要更改它。

【讨论】:

我收到此错误:AssertionError at /v1/shops ("Creating a ModelSerializer without either the 'fields' attribute or the 'exclude' attribute has been deprecated since 3.3.0, and is now disallowed. Add an explicit fields = '__all__' to the ShopSerializer serializer.",) 哎呀,请在您的 serailizer 中添加字段 = '__all__' 当我添加字段 = 'all' 时,我收到同样的错误,告诉我需要字段“路径”。我认为这些更改并不直接应用于模型 你在serializer里改了,model跟它没关系 我认为是因为你的路径是独一无二的字段

以上是关于Django - 带有序列化程序的可选字段的主要内容,如果未能解决你的问题,请参考以下文章

Django Rest Framework:具有通用外键的可写嵌套序列化程序

带有默认字段的Django模型序列化问题

Django 过滤器是不是存在 json 中的可选键

django 模型中的可选字段

使用 Django Rest Framework 3.2.2 具有现有对象的可写嵌套序列化程序

提供“ManyRelatedManager”对象的列表字段序列化程序不是 M2M 字段的可迭代错误