2016-01-25 3 views
15

У меня есть модели, как это:Запись только, только для чтения поля в рамках Джанго отдыха

class ModelA(models.Model): 
    name = models.CharField() 


class ModelB(models.Model): 
    f1 = models.CharField() 
    model_a = models.ForeignKey(ModelA) 

сериализаторы:

class ASerializer(serializers.ModelSerializer): 
    model_b_ids = serializers.CharField() 
    class Meta: 
     model = ModelA 
     write_only_fields = ('model_b_ids',) 

просмотров:

class AView(CreateModelMixin, GenericViewSet): 

    def perform_create(self, serializer): 
     model_b_ids = parse_somehow(serializer.validated_data["model_b_ids"]) 
     #do something... 

Проблема я получаю с «model_b_ids»

Пользователь должен отправить его при отправке почтовых данных.

Я использую его в файле perform_create для ссылки на связанные модели.

Но это не «настоящий столбец» в ModelA, поэтому, когда я пытаюсь сохранить его, возникает исключение.

Я пробовал его всплывать из validated_data, но затем снова получал ошибку где-то, что не может прочитать model_b_ids из модели. Любая идея по правильному использованию этого поля?

ответ

0

Возможно, вы наблюдаете за тем, что у вашего ModelA есть свойство modelb_set. В Django вы описываете отношения в одном классе модели. Django предлагает обратную связь по нижнему корпусу целевой модели и суффикс его с _set. Таким образом, вы можете сделать:

a = ModelA.objects.get(pk=1) 
a.modelb_set.all() 

Это позволит получить элемент с идентификатором (или первичным ключом) 1 из Modela и получить все связанные элементы ModelB.

Вы можете установить значение для related_name перезаписать значения по умолчанию:

class ModelB(models.Model): 
    f1 = models.CharField() 
    model_a = models.ForeignKey(ModelA, related_name='model_b') 

В ФПИ вы можете слегка адаптировать сериалайзер:

class ASerializer(serializers.ModelSerializer): 
    model_b = serializers.PrimaryKeyRelatedField(many=True, read_only=False) 

    class Meta: 
     model = ModelA 
     write_only_fields = ('model_b',) 

С serializers.CharField() Вы не можете добавлять значения и писать их к модели, потому что это не модельное поле.

Попробуйте этот пример. Тинкер и эксперимент. Это должно приблизить вас к решению.

EDIT: Я не совсем уверен, как Django создает имя для обратной связи для имен классов PascalCase. Это model_b_set для ModelB? Или это modelb_set? Вы можете попытаться это выяснить.

0

Ну, вы можете переопределить метод serializer.save() на ASerializer, чтобы создать экземпляр объекта modelA, установить его атрибуты, сохранить его, а затем установить отношения с существующими объектами modelB, сохранить их и использовать для успеха. Но я думаю, может быть, установив, что related_name и RelatedField на сериализаторе, как было предложено, будут делать то же самое ... с меньшим количеством ввода.и в целом лучше :)

22

Поправьте меня, если им неправильно, но я не думаю, что Джанго рамки остальное имеет мета атрибут

write_only_fields

Согласно их docs вы установили писать только поля в extra_kwargs

например

class UserSerializer(ModelSerializer): 
    """ 
    ``Serializer`` for ``User`` .. 
    """ 

    class Meta: 
     model = User 
     fields = ('id', 'email', 'first_name', 'last_name' ,'security_question', 'security_question_answer', 'password', 'is_active', 'is_staff') 
     read_only_fields = ('is_active', 'is_staff') 
     extra_kwargs = { 
      'security_question': {'write_only': True}, 
      'security_question_answer': {'write_only': True}, 
      'password': {'write_only': True} 
     } 
15

В соответствии с требованиями ч Django REST Framework documentation:

Опция write_only_fields на ModelSerializer был перемещен в PendingDeprecation и заменен более общим extra_kwargs

, поэтому рекомендуется сделать так: вы должны использовать extra_kwargs:

extra_kwargs = {'model_b_ids': {'write_only': True}} 

или:

model_b_ids = serializers.IntegerField(write_only=True) 
+0

Я только что обновил DRF с 3.1.3 до 3.3.3, и вдруг мои пароли пользователей были отправлены обратно (у меня было до атрибута «write_only» Meta. Решение устраняет эту проблему. Благодаря! – vabada

Смежные вопросы