PUT / Обновление внешнего ключа и отношения «многие ко многим» только с pk, а НЕ со всем объектом - PullRequest
0 голосов
/ 13 ноября 2018

У меня есть модель 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, и я могу отправить pk обновленной страны / стран из моего запроса React axios, но затем, когда я axios GET, мой пользовательский объект, отображает только страну / страны.

С другой стороны, я могу сериализовать объекты своей страны как вложенные объекты со всеми их полями и подполями, а затем получить требуемые данные из GET-запроса axios, но затем, когда я хочу обновить свой пользовательский объект, у меня появляется чтобы передать в стране объект для моего аксиума PUT, а не просто ПК.

Можно ли сериализовать объекты моей страны в их полной вложенности, НО ТАКЖЕ обновлять / ПОСТАВЛЯТЬ мою пользовательскую модель, просто передавая только ПК?

Я обновляю свой пользовательский объект с помощью форм выбора, и поэтому легко иметь опцию со значением = 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 в настоящее время, что, как я упоминал, облегчает PUT, но затем в React пользовательский объект, который я ПОЛУЧУ, имеет

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 голосов
/ 14 ноября 2018

Мне удалось перезаписать функцию to_representation в моем сериализаторе, как показано в следующих инструкциях: Django Rest Framework получает значение первичного ключа в POST и возвращает объект модели как вложенный сериализатор

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...