无法使用 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=True
在Model
类中。对于您关于 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
取决于您在视图中如何使用此序列化程序,save
和 update
有不同的方式。如果您的视图是generics
类,那么create
和update
本身将通过POST
和PUT
方法进行。对于不属于generics
DRF 视图的其他类视图,您可以使用@987654340 @创建一个新的实例。希望对您有所帮助。
传递数据类似于:
"name" : "foo",
"manufacture" : "foo",
.
.
.
"category" : [1,2,3,24,65]
【讨论】:
以上是关于无法使用 Django REST 框架从多个选择元素中发布 JSON 数据的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 django rest 框架从 GET 请求的查询参数中过滤多个 id?
如何从序列化器字段订购 django rest 框架查询集?
django rest框架中的泛型与视图集,如何选择使用哪一个?