无法使用 Django REST 框架从多个选择元素中发布 JSON 数据

Posted

技术标签:

【中文标题】无法使用 Django REST 框架从多个选择元素中发布 JSON 数据【英文标题】:Unable to POST JSON data from multiple select element with Django REST Framework 【发布时间】:2019-12-29 18:47:54 【问题描述】:

我希望能够向我的 API 端点发送 AJAX POST 请求,以创建我的Asset 模型的新实例,其中在我的Asset 模型中引用了多个类别实例,因此是多对多字段输入我的Asset 模型。

我能够成功发布并创建新的Asset 实例,但是我的category 字段根本不接受任何数据。创建新的Asset 实例时,类别字段保持为空。我认为这与我的CategorySerializer 有关。我仍在学习如何使用 Django REST Framework,所以如果我能得到一些帮助来弄清楚如何在 Django REST Framework 中使用序列化程序,我将不胜感激。

我已经尝试修改 AssetSerializer create 方法来处理解析 JSON 和验证数据,但没有奏效。我还尝试了我在 *** 上找到的其他帖子中建议的其他解决方案,但没有找到适合我情况的任何解决方案。

这是我的serializers.py 文件:

class CategorySerializer(serializers.ModelSerializer):
    name = serializers.CharField(required=False, read_only=True)

    class Meta:
        model = Category
        fields = ('id', 'name')

class AssetSerializer(serializers.ModelSerializer):
    name = serializers.CharField(allow_null=True)
    description = serializers.CharField(allow_null=True)
    manufacturer = serializers.CharField(allow_null=True)
    uid = serializers.UUIDField(read_only=True, allow_null=True)
    borrower = BorrowerSerializer(allow_null=True, read_only=True)
    condition = serializers.ChoiceField(choices=Asset.CONDITION_TYPE, default='g', allow_null=True)
    owner = serializers.ReadOnlyField(source='owner.username')
    return_date = serializers.DateField(allow_null=True)
    checked_out = serializers.BooleanField(allow_null=True)
    category = CategorySerializer(required=False, many=True)


    class Meta:
        model = Asset
        fields = ('uid',
                  'name', 
                  'manufacturer', 
                  'model',
                  'description',
                  'owner',
                  'condition',
                  'category',
                  'borrower',
                  'checked_out',
                  'return_date',
                  'is_dueback',
        )

    def update(self, instance, validated_data):
        instance.borrower = validated_data.get('borrower', instance.borrower)
        instance.return_date = validated_data.get('return_date', instance.return_date)
        instance.checked_out = validated_data.get('checked_out', instance.checked_out)

        instance.name = validated_data.get('name', instance.name)
        instance.manufacturer = validated_data.get('manufacturer', instance.manufacturer)
        instance.model = validated_data.get('model', instance.model)
        instance.description = validated_data.get('description', instance.description)
        instance.condition = validated_data.get('condition', instance.condition)
        instance.category = validated_data.get('category', instance.category)
        instance.save()
        return instance

    def create(self, validated_data):
        return Asset.objects.create(**validated_data)

这是我的Asset 模型:

class Asset(models.Model):
    """Model representing an Asset"""
    uid = models.UUIDField(primary_key=True, default=uuid.uuid4)
    name = models.CharField(max_length=200)
    manufacturer = models.CharField(max_length=64)
    model = models.CharField(max_length=128)
    description = models.TextField()
    category = models.ManyToManyField(Category)
    owner = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    borrower = models.ForeignKey(Borrower, on_delete=models.CASCADE, null=True, blank=True)
    checked_out = models.BooleanField(default=False)
    return_date = models.DateField(null=True, blank=True)    

    CONDITION_TYPE = (
        ('e', 'Excellent'),
        ('g', 'Good'),
        ('f', 'Fair'),
        ('p', 'Poor'),
    )

    condition = models.CharField(
        max_length=1,
        choices=CONDITION_TYPE,
        blank=True,
        help_text='Asset condition')

    class Meta:
            ordering = ['return_date']

    @property
    def is_dueback(self):
        if self.return_date and date.today() > self.return_date:
            return True
        return False

    def display_category(self):
        """Create a string for the Category. This is required to display category in Admin."""
        return ', '.join(category.name for category in self.category.all())

    display_category.short_description = 'Category'

    def __str__(self):
        return f'self.uid - self.name'

    def get_absolute_url(self):
        return reverse('asset-detail', args=[str(self.uid)])

这是我的Category 模型:

class Category(models.Model):
    """Model representing an Asset category"""
    name = models.CharField(max_length=128)

    def __str__(self):
        return self.name

如果您能提供任何帮助,我将不胜感激。提前谢谢你。

【问题讨论】:

所以你的问题是ManyToManyField 不起作用? 您知道您不需要在序列化程序类中定义每个字段,对吧?你只需创建class Meta,至少我就是这样创建我的 API 【参考方案1】:

我几乎是 DRF 的新手,但我会尽力提供帮助。为什么在使用ModelsSerializer 时在序列化程序中编写所有字段?不需要告诉ModelSerializer 应该是什么类型的字段,因为您指向class Meta 中的模型并且DRF 知道字段和类型等。第二个关于序列化程序中的allow_null=True,当模型没有null=True时,你不能除了DRF可以创建一个不可为空的字段,例如null=True所以如果你不想一个字段可以为空,只需添加null=TrueModel 类中。对于您关于 ManytoMantry 字段的问题,请尝试在序列化程序中将 Primary key relation 用于 ManyToMany 字段,然后在列表中传递 Category 实例的 id:

class AssetSerializer(serializers.ModelSerializer):
    borrower = BorrowerSerializer(allow_null=True, read_only=True)
    category =  serializers.PrimaryKeyRelatedField(many=True, queryset=Category.objects.all())


    class Meta:
        model = Asset
        fields = ('uid',
                  'name', 
                  'manufacturer', 
                  'model',
                  'description',
                  'owner',
                  'condition',
                  'category',
                  'borrower',
                  'checked_out',
                  'return_date',
                  'is_dueback',
        )
     read_only_fields = ( 'uid' , ) # this fields will be read_only 

取决于您在视图中如何使用此序列化程序,saveupdate 有不同的方式。如果您的视图是generics 类,那么createupdate 本身将通过POSTPUT 方法进行。对于不属于generics DRF 视图的其他类视图,您可以使用@987654340 @创建一个新的实例。希望对您有所帮助。 传递数据类似于:


  "name" : "foo",
  "manufacture" : "foo",
  .
  .
  .
  "category" : [1,2,3,24,65]

【讨论】:

以上是关于无法使用 Django REST 框架从多个选择元素中发布 JSON 数据的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 django rest 框架从 GET 请求的查询参数中过滤多个 id?

如何从序列化器字段订购 django rest 框架查询集?

django rest框架中的泛型与视图集,如何选择使用哪一个?

django rest框架中多个视图的相同验证

如何使用 django rest 框架和 angular 上传图片?

如何更新 django rest 框架中的多个对象?