Django Rest Framework的UpdateAPIView要求一个字段,但该字段已存在。

huangapple go评论65阅读模式
英文:

Django Rest Framework UpdateAPIView is saying a field is required but the field is there

问题

The error you're encountering seems to be related to the campaign field in your BigAd model. It's expecting a campaign object, but you're providing a string value, which is causing the error.

You mentioned that it doesn't give you the same error for the audience field, which suggests that the audience field might be set up differently, possibly allowing a string value.

To resolve this issue, you should make sure that the campaign field in your request data is a valid campaign object, not just its ID as a string. You may need to change the way you pass the campaign value in your request data to provide a valid campaign object.

If you continue to face issues, please check your serializer and view logic to ensure that the campaign field is being handled correctly in the update process.

英文:

I have this model that represents an Ad:

class BigAd(models.Model):
    DA = 'DA'
    WE = 'WE'
    MO = 'MO'
    INTERVAL = [
        (DA, 'Day'),
        (WE, 'Week'),
        (MO, 'Month'),
    ]
    IM = 'IM'
    VI = 'VI'
    TYPES = [
        (IM, 'Image'),
        (VI, 'Video'),
    ]
    title = models.CharField(max_length=50, default=None)
    campaign = models.ForeignKey(Campaign, on_delete=models.CASCADE)
    audience = models.ForeignKey(AdAudience, on_delete=models.CASCADE, default=None)
    active = models.BooleanField(default=False)
    body = models.TextField(max_length=255, null=True, blank=True)
    ad_image = models.FileField(upload_to=bigad_directory_path, null=True, blank=True)
    ad_type = models.CharField(max_length=2, choices=TYPES, default=IM)
    big_image = models.FileField(upload_to=bigad_directory_path, null=True, blank=True)
    video = models.FileField(upload_to=bigad_video_path, null=True, blank=True)
    link = models.URLField(max_length=256, null=True, blank=True)
    budget_interval = models.CharField(max_length=2, choices=INTERVAL, default=DA)
    budget = models.DecimalField(max_digits=30, decimal_places=0, default=200)
    lowest_bid = models.DecimalField(max_digits=20, decimal_places=2)
    highest_bid = models.DecimalField(max_digits=20, decimal_places=2)
    includes_products = models.BooleanField(default=False)
    product_list = ArrayField(models.IntegerField(), null=True, blank=True)
    user = models.ForeignKey(User, on_delete=models.CASCADE, default=None)


    created_at = models.DateTimeField(auto_now_add=True, verbose_name="created at")
    updated_at = models.DateTimeField(auto_now=True, verbose_name="updated at")

    class Meta:
        verbose_name = "big ad"
        verbose_name_plural = "big ads"
        db_table = "big_ads"
        ordering = ["created_at"]

    def __str__(self):
            return self.title

    def get_absolute_url(self):
        return self.slug    

and this serializer for serializing the data:

class BigAdSerializer(serializers.ModelSerializer):
    campaign = ShortCampaignSerializer()
    class Meta:
        model = BigAd
        fields = [
            "id",
            "title",
            "campaign",
            "audience",
            "ad_image",
            "ad_type",
            "big_image",
            "active",
            "body",
            "video",
            "link",
            "budget_interval",
            "budget",
            "lowest_bid",
            "highest_bid",
            "user",
            "includes_products",
            "product_list",
            "active",
            "created_at",
            "updated_at",
        ]

and this view for processing the data:

class UpdateBigAd(generics.UpdateAPIView):
    permission_classes = [IsAuthenticated]
    serializer_class = AdSerializer
    def get_queryset(self):
        id = self.kwargs["pk"]
        return BigAd.objects.all().filter(id=id)

I am trying to update the ad model but I get an error saying campaign is required but the data is there and campaign has a value. Here is the data in the backend received:

(Pdb) print(request.data)
<QueryDict: {'active': ['on'], 'title': ['First Big AD'], 'campaign': ['20'], 'audience': ['10'], 'body': ['This is the first bog ad'], 'ad_image': [''], 'big_image': [''], 'link': ['https://post.com'], 'budget_interval': ['DA'], 'budget': ['200'], 'lowest_bid': ['10.00'], 'highest_bid': ['20']}>

I thought it could be that because campaign value is a string but then it would give me the same error for 'audience' which it doesn't. It also cannot be that it requires and object because then again it would give me the same error for audience.

Why then am I getting this error please?

答案1

得分: 0

你定义了campaign = ShortCampaignSerializer(),所以你的BigAdSerializer期望的是一个对象而不是一个ID。请查看DRF文档中有关嵌套序列化器的部分。

我建议你在读取和写入操作时使用两个不同的序列化器:

class BigAdWriteSerializer(serializers.ModelSerializer):
   ... 

class BigAdReadSerializer(BigAdWriteSerializer):
    campaign = ShortCampaignSerializer()

然后,你需要覆盖你的更新视图方法,使用BigAdWriteSerializer来写入数据,然后使用BigAdReadSerializer来返回数据。

英文:

As you defined campaign = ShortCampaignSerializer() your BigAdSerializer expects an object not an ID. Have a look to DRF documentation regarding nested serializers.

I suggest that you use two differents serializers for read and write operations :

class BigAdWriteSerializer(serializers.ModelSerializer):
   ... 

class BigAdReadSerializer(BigAdWriteSerializer):
    campaign = ShortCampaignSerializer()

You then need to override you update view method to use BigAdWriteSerializer to write data and then use BigAdReadSerializer to return data.

huangapple
  • 本文由 发表于 2023年5月25日 16:30:35
  • 转载请务必保留本文链接:https://go.coder-hub.com/76330294.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定