2015-10-12 5 views
4

Я немного расстроен с этой проблемой, используя Django Framework Rest:Джанго Rest Framework - Обновление внешнего ключа

Я использую Viewset с custom serializer. Этот сериализатор имеет depth set to 1. Когда я запросить эту Viewset я получить правильное представление данных, например:

data = { 
    id: 1, 
    issue_name: 'This is a problem', 
    status: { 
    id: 3, 
    name: 'todo' 
    } 
} 

проблема приходит, когда мне нужно обновить статус. Например, если я хочу, чтобы выбрать другой статус этого вопроса, например:

status_new = { 
    id: 4, 
    name: 'done' 
} 

Я посылаю следующий ЗАПЛАТУ обратно на сервер, это выход:

data = { 
    id: 1, 
    issue_name: 'This is a problem', 
    status: { 
    id: 4, 
    name: 'done' 
    } 

} 

Однако статус делает не обновляется. Infact, он даже не является частью словаря validated_data. Я прочитал, что вложенные отношения доступны только для чтения. Может кто-нибудь, пожалуйста, скажите мне, что мне нужно сделать это простым способом?

Действительно будет обязан.

Заранее спасибо

+0

У меня тоже есть эта проблема. –

ответ

6

Как указано в documentation, вам нужно будет написать свою собственный create() и update() методы в вашем сериализаторе для поддержки перезаписываемых вложенных данных.

Вам также нужно будет явно добавить поле состояния вместо использования аргумента depth, иначе я считаю, что он не будет автоматически добавлен в validated_data.

EDIT: Возможно, я был немного короче в деталях: что вы хотите сделать, это переопределить обновление в ModelIssueSerializer. Это будет в основном перехватывать запросы PATCH/PUT на уровне сериализатора. Затем получить новый статус и назначить его к экземпляру, как это:

class StatusSerializer(serializers.ModelSerializer): 
    class Meta: 
     model = Status 

class ModelIssueSerializer(serializers.ModelSerializer): 
    status = StatusSerializer() 
    # ... 
    def update(self, instance, validated_data): 
     status = validated_data.pop('status') 
     instance.status_id = status.id 
     # ... plus any other fields you may want to update 
     return instance 

причина, почему я упомянул в комментариях, что вам может понадобиться добавить StatusSerializer поля для получения статуса в validated_data. Если я правильно помню, если вы используете только depth, тогда вложенные объекты не могут быть сериализованы внутри методов update()/create() (хотя я могу ошибаться в этом). В любом случае добавление поля StatusSerializer - это просто явный вид использования depth=1

+0

Если я не использую глубину, то как мне получить полную структуру, как: статус: { id: 4, имя: 'done' }. Можете ли вы дать мне или указать мне пример или ресурс, который делает обновление, о котором вы говорите? – Nav

+0

Просто определите ModelSerializer для состояния и включите его в качестве поля в другой сериализатор, например. 'status = StatusSerializer()'. Что касается примеров для 'update()', то в документации DRF есть несколько (см. Ссылку в моем ответе). – gbs

+0

Я попытался это сделать, но определение сериализатора для полей состояния приводит к тому, что сама запись состояния обновляется сама, не то, что я хочу .. Позвольте мне привести пример: 'класс ModeIIssue (модели): имя = models.CharField (max_length = 30) статус = ForeignKey (ModelStatus) ' Я хочу, чтобы обновить ссылку поля статуса, а не самой записи состояния. – Nav

0

Я бы предположил, что ваши модели имитируют данные вашего сериализатора. Кроме того, я бы предположил, что у вас есть отношение «один к большому» со статусом (состояниями), но вам не нужно создавать их с помощью сериализатора проблем, у вас есть другая конечная точка для этого. В таком случае вы можете уйти с SlugRelatedField.

from rest_framework import serializers 


class StatusSerializer(serializers.ModelSerializer): 
    class Meta: 
     model = MyStatusModel 
     fields = (
      'id', 
      'status', 
     ) 


class IssueSerializer(serializers.ModelSerializer): 
    status = serializers.SlugRelatedField(slug_field='status', queryset=MyStatusModel.objects.all()) 

    class Meta: 
     model = MyIssueModel 
     fields = (
      'issue_name', 
      'status', 
     ) 

Другое верным решением было бы оставить здесь значение внешнего ключа и иметь дело с именем дисплея на переднем конце, через пользовательский интерфейс, выберите или Выбор2 компонента - подход RESTfull: вы регулируете объекты Issue, которые имеют ссылки на объекты состояния. В приложении с угловым интерфейсом вы будете запрашивать все статусы из внешнего контура по определенному маршруту, а затем отобразите надлежащее описательное имя на основе формы значения внешнего ключа Issue.

Дайте мне знать, как это работает для вас.

+0

Идея заключается в том, что у меня есть проблема, у которой есть статус. Статус может быть новым, в процессе, разрешенным и т. Д. С фронтальной стороны я могу выбрать другой статус, например, разрешить, а затем нажать «Сохранить». Я хочу, чтобы, когда я ударил, проблема должна обновляться через ajax. Этот поток отлично работает для других полей модели выпуска, но не обновляет поле состояния. Я бы добавил код ** update **, но поле ** status ** не отображается в словаре validated_data. – Nav

+0

Список статусов «фиксирован» или настраивается в приложении в другом месте? Вам нужно только указать статус здесь в проблеме, не так ли? – Roba

+0

Да, статус настраивается в другом месте приложения, и мне нужно сослаться и изменить статус проблемы здесь. – Nav