PUT请求Django API更新具有多对多关系的嵌套对象列表



我有一个与另一个模型具有ManyToMany关系的用户模型

class User(AbstractUser):
countries = models.ManyToManyField(Country, blank=True)
count = models.IntegerField(blank=True, default=0)
def save(self, *args, **kwargs):
# Must save model before Many To Many relationship can be used.
super(User, self).save(*args, **kwargs)
self.count = self.countries.count()
super(User, self).save(*args, **kwargs)

我的国家模型是一个相当大的模型:

class Country(models.Model):
'''
Describes the countries, as well as territories of the world.
'''
name = models.CharField(max_length=255, null=True, blank=True)
top_level_domain = JSONField(null=True, blank=True)
alpha2code = models.CharField(max_length=255, null=True, blank=True)
alpha3code = models.CharField(max_length=255, null=True, blank=True)
calling_codes = JSONField(null=True, blank=True)
capital = models.CharField(max_length=255, null=True, blank=True)
alt_spellings = JSONField(null=True, blank=True)
region = models.CharField(max_length=255, null=True, blank=True)
subregion = models.CharField(max_length=255, null=True, blank=True)
population = models.IntegerField(null=True, blank=True)
latlng = JSONField(null=True, blank=True)
demonym = models.CharField(max_length=255, null=True, blank=True)
area = models.FloatField(null=True, blank=True)
gini = models.FloatField(null=True, blank=True)
timezones = JSONField(null=True, blank=True)
borders = JSONField(null=True, blank=True)
native_name = models.CharField(max_length=255, null=True, blank=True)
numeric_code= models.CharField(max_length=255, null=True, blank=True)
currencies = models.ManyToManyField(Currency)
languages = models.ManyToManyField(Language)
flag = models.CharField(max_length=255, null=True, blank=True)
regional_blocs = models.ManyToManyField(RegionalBloc, blank=True)
cioc = models.CharField(max_length=255, null=True, blank=True)
def __str__(self):
return self.name

我正试图从我的前端发出一个put请求,以更新与之相关的国家列表(数据以对象数组的形式从React with axios发送(。我得到错误"断言错误:默认情况下,.update()方法不支持可写嵌套字段。为序列化程序api.serializers.UserDetailSerializer编写一个显式.update()方法,或在嵌套的序列化程序字段上设置read_only=True。"由于我显然无法使我的国家/地区read_only=True,我正在尝试为我的序列化程序添加一个更新方法

class UserDetailSerializer(UserDetailsSerializer):
countries = CountrySerializer(many=True)
count = serializers.IntegerField(read_only=True)
class Meta:
model = User
fields = ('pk', 'username', 'email', 'count', 'countries')
# Update the instance upon Put Request from frontend.
def update(self, instance, validated_data):
instance.countries = validated_data['countries']
instance.save()
return instance

这个更新方法给了我一个错误"禁止直接分配给多对多集合的前端"。请改用countries.set((。'

当我将更新方法更改为时

instance.countries.set(validated_data['countries'])

我收到错误"TypeError:不可处理的类型:"collections.OrderDict"。我开始感到有点失落,好像在兜圈子。如何正确编写更新方法?

edit:我想做的只是在用户国家/地区列表中添加/删除一个国家/地区对象。实际上,我不想编辑任何一个乡村对象。

我发布的国家数据将是一个国家对象列表,看起来像这个

{
"id": 6,
"currencies": [
{
"code": "EUR",
"name": "European Euro",
"symbol": "€"
}
],
"languages": [
{
"iso639_1": "ca",
"name": "Catalan",
"native_name": "Català"
}
],
"regional_blocs": [],
"name": "Andorra",
"top_level_domain": [
".ad"
],
"alpha2code": "AD",
"alpha3code": "AND",
"calling_codes": [
"376"
],
"capital": "Andorra la Vella",
"alt_spellings": [
"AD",
"Principality of Andorra",
"Principat d'Andorra"
],
"region": "Europe",
"subregion": "Southern Europe",
"population": 78014,
"latlng": [
42.5,
1.5
],
"demonym": "Andorran",
"area": 468.0,
"gini": null,
"timezones": [
"UTC+01:00"
],
"borders": [
"FRA",
"ESP"
],
"native_name": "Andorra",
"numeric_code": "020",
"flag": "https://restcountries.eu/data/and.svg",
"cioc": "AND"
}

您得到TypeError: unhashable type: 'collections.OrderedDict'是因为您试图将类型为collections.OrderedDict的对象分配给国家/地区,这是一个ManyToManyField

请执行以下操作:

def update(self, instance, validated_data):
country_names = [cdata['name'] for cdata in validated_data['countries']]
countries = Country.objects.filter(name__in=country_names)
instance.countries.set(countries)
return instance

最新更新