как добавить данные в дочернюю модель вместе с родительским режимом?

Я работаю с фреймворком Django REST. Я хочу добавить данные в дочернюю модель вместе с родительской моделью. В основном создание двух записей одновременно.

models.py

class Visit(models.Model):
   name = models.CharField(max_length=200)
   gender = models.CharField(choices=GENDER_CHOICE, max_length=1)
   mobile = models.CharField(max_length=18,default="")
   email = models.CharField(max_length=256, null=True, blank=True)
   address = models.TextField(null=True, blank=True)
   visit_type = models.IntegerField(choices=VISIT_TYPE)
   visit_purpose = models.CharField(max_length=250)
   visitor_photo = models.FileField(upload_to="visitor/",null=True, blank=True)
   id_photo = models.FileField(upload_to="id_card/",null=True, blank=True)
   date_created = models.DateTimeField(default=timezone.now, editable=False)

class Status(models.Model):
   visit = models.ForeignKey(Visit,on_delete=models.CASCADE)
   description = models.CharField(max_length=200)
   from_time = models.DateField()
   to_time = models.DateTimeField(null=True, blank=True)
   aproved = models.BooleanField(default=False)
   visit_complete = models.BooleanField(default=False)
   exit_time = models.DateTimeField(null=True, blank=True)
   date_created = models.DateTimeField(default=timezone.now, editable=False)

сериализаторы.py

class StatusSerializers(serializers.ModelSerializer):
       class Meta:
         model = Status
         fields = "__all__"
class VisitSerializers(serializers.ModelSerializer):
   visit = StatusSerializers(many=True)
   class Meta:
       model = Visit
       fields = "__all__"

   def create(self, validated_data):
      print(validated_data)
      model_b = Visit.objects.create(**validated_data)
      # print(self.context.request.data.get('description'))
      child_model_data = {
         'description': self.context.request.data.get('description'),
      }
      child_model_serializer = StatusSerializers(data=child_model_data)
      child_model_serializer.is_valid(raise_exception=True)
      child_model_serializer.save(status=model_b)

      return model_b

views.py

  @api_view(['GET', 'POST'])
  def create_visitor(request):
    if request.method == 'GET':
       visitor = Visit.objects.all()
       serializer = VisitSerializers(visitor,context={'request': request},many=True)
       return Response(serializer.data)
    elif request.method == 'POST':
       serializer = VisitSerializers(data=request.data,context={'request': request})
    if serializer.is_valid():
        serializer.save()
        return Response(serializer.data, status=status.HTTP_201_CREATED)
    return Response(serializer.errors,

status=status.HTTP_400_BAD_REQUEST) В приведенном выше коде я могу создать дочернюю запись, т.е. запись модели состояния, но я не знаю, как добавить к ней другие поля во время ее создания.


person Clifton Avil D'Souza    schedule 14.03.2019    source источник
comment
Вы хотите добавить записи в модель статуса, а также в модель посещения?   -  person Nafees Anwar    schedule 14.03.2019
comment
да, мне нужно создать обе записи за один раз. Я могу создать запись в модели состояния (игнорируя другие поля), но не знаю, как добавить данные других полей в поле записи состояния.   -  person Clifton Avil D'Souza    schedule 14.03.2019


Ответы (2)


В вашей дочерней модели serializer данные можно найти в self.context.request.data, и вы можете просто использовать дочерний сериализатор для проверки и сохранения в БД.

class VisitSerializers(serializers.ModelSerializer):
   class Meta:
       model = Visit
       fields = "__all__"

   def create(self, validated_data):
      print(validated_data)
      model_b = Visit.objects.create(**validated_data)
      child_model_data = {
         'field': self.context['request'].data.get('your_field');
         .....
      }
      child_model_serializer = ChildSerializer(data=child_model_data)
      child_model_serializer.is_valid(raise_exception=True)
      child_model_serializer.save()

      return model_b

Обновление, которое нужно изменить в нескольких местах

Во-первых, на ваш взгляд, при инициализации сериализатора метода post вам нужно передать объект контекста.

  @api_view(['GET', 'POST'])
  def create_visitor(request):
     if request.method == 'GET':
        visitor = Visit.objects.all()
        serializer = VisitSerializers(visitor,context={'request': request},many=True)
        return Response(serializer.data)
    elif request.method == 'POST':
        serializer = VisitSerializers(data=request.data, context={'request': request})
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

А затем в вашем VisitSerializer

class VisitSerializers(serializers.ModelSerializer):
   visit = StatusSerializers(many=True)  # not sure why you did this, this should be removed i guess
   class Meta:
       model = Visit
       fields = "__all__"

   def create(self, validated_data):
      print(validated_data)
      model_b = Visit.objects.create(**validated_data)
      # print(self.context.request.data.get('description'))
      child_model_data = {
         'description': self.context.request.data.get('description'),
          'status': model_b
          # and make sure all other necessary fields.
      }
      child_model_serializer = StatusSerializers(data=child_model_data)
      child_model_serializer.is_valid(raise_exception=True)
      child_model_serializer.save()

      return model_b
person Shakil    schedule 14.03.2019
comment
Не могли бы вы увидеть этот пост stackoverflow.com/questions/55161052/ @shakil - person Huzaif Sayyed; 14.03.2019
comment
как передать данные {parent_files:something} как передать дочернюю модель. также я не вижу, чтобы родительская модель была связана с дочерним режимом через FK - person Clifton Avil D'Souza; 14.03.2019
comment
@CliftonAvilD'Souza, вы используете drf-serializer, верно? то в вас request вы можете передать относительные поля как вашей родительской, так и дочерней модели. - person Shakil; 14.03.2019
comment
Файл /home/netzary/cliftonprojects/mvisiter/api/views.py, строка 25, в файле create_visitor serializer.save() /home/netzary/cliftonprojects/venvs/mvisiter/lib/python3.6/site-packages/rest_framework/ serializers.py, строка 214, в save self.instance = self.create(validated_data) File /home/netzary/cliftonprojects/mvisiter/api/serializer.py, строка 30, в create print(self.context.request.data. get('description')) AttributeError: объект 'dict' не имеет атрибута 'запрос' - person Clifton Avil D'Souza; 14.03.2019
comment
@CliftonAvilD'Souza, пожалуйста, убедитесь, что вы передаете context={'request': request} в свой сериализатор сообщений, как и в методе get. - person Shakil; 14.03.2019
comment
я ничего не менял в views.py то же самое - person Clifton Avil D'Souza; 14.03.2019
comment
В вашем методе публикации `serializer = VisitSerializers(data=request.data)` должен измениться на `serializer = VisitSerializers(data=request.data,context={'request': request})` - person Shakil; 14.03.2019
comment
{ статус: [ Это поле обязательно для заполнения. ] } в почтальоне - person Clifton Avil D'Souza; 14.03.2019
comment
что я вижу в вашем посте, что status=model_b так что вам нужно сделать вас, вы добавляете это в свои child_model_data. - person Shakil; 14.03.2019
comment
'description': self.context.request.data.get('description'), AttributeError: 'dict' object has no attribute 'request' теперь я понимаю это. @Shakil - person Clifton Avil D'Souza; 14.03.2019
comment
@CliftonAvilD'Souza, не могли бы вы обновить свой код для этого. Мне будет полезно дать вам соответствующий ответ. - person Shakil; 14.03.2019
comment
@CliftonAvilD'Souza отредактировал мой ответ. Пожалуйста, не стесняйтесь спрашивать, если у вас есть какие-либо сомнения. - person Shakil; 14.03.2019
comment
на данный момент нет ни одной ошибки. подскажите, как передать поля в Postman или в веб-интерфейсе DRF. когда я отправляю сообщение, я получаю сообщение об ошибке, как в почтальоне { "visit": [ "This field is required." ] } - person Clifton Avil D'Souza; 14.03.2019
comment
@CliftonAvilD'Souza, почему вы вообще добавили поле посещения в свой сериализатор. Я просто указываю комментарий, который кажется ненужным. - person Shakil; 14.03.2019
comment
@Shakil, если я удалю эту строку, я получу File "/home/netzary/cliftonprojects/mvisiter/api/views.py", line 60, in create_visitor serializer.save() File "/home/netzary/cliftonprojects/venvs/mvisiter/lib/python3.6/site-packages/rest_framework/serializers.py", line 214, in save self.instance = self.create(validated_data) File "/home/netzary/cliftonprojects/mvisiter/api/serializer.py", line 57, in create 'description': self.context.request.data.get('description'), AttributeError: 'dict' object has no attribute 'request' - person Clifton Avil D'Souza; 14.03.2019
comment
Клифтон, пожалуйста, убедитесь, что вы передаете serializer = VisitSerializers(data=request.data, context={'request': request}) это в своем методе публикации. Если вы сделаете его, эта ошибка не должна появиться. - person Shakil; 14.03.2019
comment
пожалуйста, просмотрите это для получения более подробной информации. - person Shakil; 14.03.2019
comment
@CliftonAvilD'Souza, не могли бы вы попробовать self.context['request'].data.get('description') в своем сериализаторе. - person Shakil; 14.03.2019

У вас могут быть дополнительные поля в вашем сериализаторе вместе с полями по умолчанию. Для обратных отношений вы можете добавить такое поле

class VisitSerializers(serializers.ModelSerializer):
   status = StatusSerializer(many=True)
   class Meta:
       model = Visit

Вы можете передавать данные в VisitSerializer следующим образом. {, статус: [, ]}

person Nafees Anwar    schedule 14.03.2019
comment
{имя: Клифтон, пол: M, тип_посещения: 1, назначение_посещения: ххххххх, статус: [описание: ххххххх,] } получил ошибку как деталь: ошибка синтаксического анализа JSON - Ожидается имя свойства, заключенное в двойные кавычки: строка 6, столбец 1 (символ 77 ) } - person Clifton Avil D'Souza; 14.03.2019
comment
статус должен быть в кавычках. статус - person Nafees Anwar; 14.03.2019