Django rest framework, изменить ForeignKey

Я слишком долго борюсь с DRF, так что теперь я должен задать вопрос .. Как поменять ForeignKey на другой? У меня есть профиль пользователя и отношение к статусной модели.

models.py

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    ldap_uid = models.CharField(max_length=100, blank=True, null=True, default=None)
    redmine_id = models.IntegerField(blank=True, null=True, default=None)
    status = models.ForeignKey(Status, models.SET_NULL, blank=False, null=True, default=DEFAULT_STATUS_ID)
    location = models.ForeignKey(Location, models.SET_NULL, blank=False, null=True, default=DEFAULT_LOCATION_ID)
    online = models.BooleanField(default=False)


class SelectValuesModel(models.Model):
    name = models.CharField(max_length=100)
    display_name = models.CharField(max_length=100)

    def __str__(self):
        return self.name

    class Meta:
        abstract = True


class Status(SelectValuesModel):
    pass


class Location(SelectValuesModel):
    pass

Как лучше изменить статус профиля на другой? Я безуспешно пытаюсь сделать что-то подобное

views.py

class UserStatusView(viewsets.ViewSet):
    def partial_update(self, request, pk=None):
        user = User.objects.get(pk=pk)
        user_profile = user.profile
        new_stauts = Status.objects.get(request.data.status)
        serialized_data = ProfileSerializer(user_profile)
        if (serialized_data.is_valid()):
            serialized_data.save(status=new_stauts)
        return Response(serialized_data.errors)

И пытаюсь отправить новый идентификатор через PATCH. Я пытаюсь найти решение, но и здесь безуспешно. А как это хорошо? Сделать другой маршрут для обновления статуса профиля? Или сделать что-то вроде profile / 1 / update_status / 2? Теперь моя маршрутизация выглядит так:

router = routers.DefaultRouter()
router.register(r'users', views.UserViewSet)
router.register(r'redmine', views.RedmineCurrentTaskView, base_name='redmine')
router.register(r'parameters', views.ParametersView, base_name='parameters')
router.register(r'update_status', views.UserStatusView, base_name='update_status')
router.register(r'debug', views.DebugStatus, base_name='debug')

urlpatterns = [
    path('', views.index, name='index'),
    path('api/', include(router.urls))
]

И serializers.py

class SelectValuesSerializer(serializers.ModelSerializer):
    class Meta:
        fields = ('pk', 'name', 'display_name')


class LocationSerializer(SelectValuesSerializer):
    class Meta(SelectValuesSerializer.Meta):
        model = Location


class StatusSerializer(SelectValuesSerializer):
    class Meta(SelectValuesSerializer.Meta):
        model = Status


class ProfileSerializer(serializers.ModelSerializer):
    status = StatusSerializer()
    location = LocationSerializer()

    class Meta:
        model = Profile
        fields = ('status', 'location', 'online', 'redmine_id')


class UserSerializer(serializers.ModelSerializer):
    profile = ProfileSerializer(read_only=True)

    class Meta:
        model = User
        fields = ('pk', 'first_name', 'profile')
        read_only_fields = ('first_name',)
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
278
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Просто передайте request.data сериализатору с аргументом partial=True:

class UserStatusView(viewsets.ViewSet):
    def partial_update(self, request, pk=None):
        user = User.objects.get(pk=pk)
        user_profile = user.profile
        serialized_data = ProfileSerializer(user_profile, data=request.data, partial=True)
        if serialized_data.is_valid():
            serialized_data.save()
            return Response(serialized_data.data)
        return Response(serialized_data.errors)

Вам нужно предоставить status_id с телом запроса следующим образом:

{"status": 1}

UPD

Чтобы передать статус как id, измените свой сериализатор на это:

class ProfileSerializer(serializers.ModelSerializer):
    location = LocationSerializer()

    class Meta:
        model = Profile
        fields = ('status', 'location', 'online', 'redmine_id')

    def to_representation(self, instance):
        self.fields['status'] = StatusSerializer()
        return super(ProfileSerializer, self).to_representation(instance)

Это позволяет публиковать status_id, но получать информацию о статусе с помощью вашего API.

Я связал это и всегда получаю ошибку: {"status": {"non_field_errors": ["Недействительные данные. Ожидал словарь, но получил int." ]}}

Sierran 19.05.2018 19:02

Я полагаю, вы установили в сериализаторе status=StatusSerializer()? Вы можете просто добавить его в метод to_representation, чтобы отображать детали статуса только для запроса GET.

neverwalkaloner 19.05.2018 19:04

@Sierran Я обновил ответ :) Вам нужно добавить to_representation и удалить status = StatusSerializer().

neverwalkaloner 19.05.2018 19:09

Боже мой! Оно работает! Спасибо! Но на будущее .. Это хорошее решение? Я не могу найти это в документации DRF. И как лучше всего создавать маршрутизацию?

Sierran 19.05.2018 19:13

@Sierran, да, это обычная практика, чтобы переопределить to_representation. Что касается маршрутизации, я предлагаю вам использовать DefaultRouter, как вы это уже сделали. Проверить ссылку о переопределении метода to_presentation: django-rest-framework.org/api-guide/relations/#example_1

neverwalkaloner 19.05.2018 19:16

Спасибо! Я знаю, что это неубедительный вопрос .. Но вы можете объяснить мне to_presentation в моем примере? В документации 100% создано для меня, как его использовать, но в моем примере? Я не понимаю разницы с to_presentation и без него в моей проблеме, в чем разница между status = StatusSerializer () и self.fields ['status'] = StatusSerializer (). А почему мы используем супер?

Sierran 19.05.2018 19:28

Позвольте нам продолжить обсуждение в чате.

neverwalkaloner 19.05.2018 19:30

Другие вопросы по теме