PUT /更新外键和多对多关系仅包含pk,而不是整个对象

时间:2018-11-13 17:58:08

标签: django reactjs django-rest-framework axios

我有一个User模型,该模型具有一个外键,并且与另一个模型有很多对许多的关系。

class User(AbstractUser):
    '''
    Custom User model. Countries is a list of countries associated with the
    user. Home country is a single country object
    '''
    countries = models.ManyToManyField(
        Country, blank=True, related_name='user_countries'
        )
    home = models.ForeignKey(
        Country, on_delete=models.PROTECT, null=True,
        related_name='home_country',
        )

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请求更新用户模型时,我可以序列化我的国家对象以仅显示pk,并且可以从我的React axios请求中发送更新后的国家/地区的pk,但是当我axios获取我的用户对象时,它仅显示国家/地区。

另一方面,我可以将国家对象序列化为带有其所有字段和子字段的嵌套对象,然后从axios GET请求中获取所需的数据,但是当我要更新用户对象时,将国家对象传递给我的axios PUT,而不仅仅是pk。

是否有可能将我的国家对象序列化为完全嵌套的美貌,同时也仅通过传入pk来更新/放置我的用户模型?

我正在使用选择表单更新我的用户对象,因此很容易使用value = pk的选项,然后我就可以仅使用该值来PUT请求。

<option value="6">Andorra</option>

这是我目前自定义的用户详细信息序列化程序:

class UserDetailSerializer(UserDetailsSerializer):
    '''
    Custom serializer for the /rest-auth/user/ User Details Serializer.
    '''
    countries = CountrySerializer(many=True)
    home = serializers.SlugRelatedField(slug_field='pk', queryset=Country.objects.all())

    class Meta:
        model = User
        fields = ('pk', 'username', 'email', 'countries', 'home',)

    '''
    Updates the users object in the database. The username, email, countries(a
    list of country objects) and home (country object), are set by a PUT
    request from the frontend.
    '''
    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.username = validated_data['username']
        instance.email = validated_data['email']
        instance.countries.set(countries)
        instance.home = validated_data['home']
        instance.save()
        return instance

我目前仅通过pk序列化home字段,就像我提到的那样,这使得PUT变得很容易,但是随后在React中,我的GET用户对象

home: 6

代替

{
    "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"
}

1 个答案:

答案 0 :(得分:0)

类似于以下说明,我能够在序列化程序中覆盖to_representation函数:Django Rest Framework receive primary key value in POST and return model object as nested serializer