无法使用Django Rest框架创建记录

时间:2019-03-15 10:04:29

标签: python django django-rest-framework django-serializer

我试图通过从Visit模型中获取一个对象来在Status模型中创建一条记录,但是在传递值以创建记录时会出错,因为所需的归档数据很少。下面是我的代码以及正在传递的数据。

models.py

class Visit(models.Model):
   name = models.CharField(max_length=200, name="name")
   gender = models.CharField(choices=GENDER_CHOICE, max_length=1, name="gender")
   mobile = models.CharField(max_length=18,default="", name="mobile")
   email = models.CharField(max_length=256, null=True, blank=True, name="email")
   address = models.TextField(null=True, blank=True, name="address")
   visit_type = models.IntegerField(choices=VISIT_TYPE, name="visit_type")
   visit_purpose = models.CharField(max_length=250, name="visit_purpose")
   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)

     def __str__(self):
         return self.name

    def save(self, *args, **kwargs):
        if not self.id:
          self.date_created = timezone.now()
        super(Visit, self).save(*args, **kwargs)

class Status(models.Model):
    visit = models.ForeignKey(Visit,on_delete=models.CASCADE)
    description = models.CharField(name="description",max_length=200)
    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)

    def __str__(self):
        return self.visit.name

    def save(self, *args, **kwargs):
        if not self.id:
           self.date_created = timezone.now()
        super(Status, self).save(*args, **kwargs)

serializer.py

class VisitSerializers(serializers.ModelSerializer):
    class Meta:
       model = Visit
       fields = ('name','gender','mobile','email','address','visit_type','visit_purpose','visitor_photo','id_photo')


class StatusSerializers(serializers.ModelSerializer):
    visit = VisitSerializers(required=True)

    class Meta:
       model = Status
       fields = ('visit', 'description','time','aproved','visit_complete','exit_time')

    def create(self, validated_data):
       visit_data = validated_data.pop('visit')
       visit = VisitSerializers.create(VisitSerializers(), validated_data=visit_data)
       status, created =  StatusSerializers.objects.update_or_create(visit=visit,
                                description=validated_data.pop('description'))
    return status

views.py

@api_view(['GET', 'POST'])
def create_visitor(request):
   if request.method == 'GET':
      visitor = Visit.objects.all()
      serializer = VisitSerializers(visitor, many=True)
      return Response(serializer.data)
   elif request.method == 'POST':
     serializer = VisitSerializers(data=request.data)
     if serializer.is_valid(raise_exception=ValueError):
         serializer.create(validated_data=request.data)
         return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.error_messages,
                     status=status.HTTP_400_BAD_REQUEST)

Data i posted

  {
    "visit":{
       "name":"Alian",
       "gender": "M",
        "mobile":"97437000",
       "visit_type":"1",
      "visit_purpose":"vvvvvvv"
   },
   "description":"this is testing!!!!!"
 }

Error I got

{
"name": [
    "This field is required."
],
"gender": [
    "This field is required."
],
"visit_type": [
    "This field is required."
],
"visit_purpose": [
    "This field is required."
]

}

我遵循了这个check this link教程,但是当我使用该代码时,它工作得很好。但是当我自定义它不起作用时。

2 个答案:

答案 0 :(得分:1)

您正在将create_visitor方法与VisitSerializers一起使用。因此您发布的数据应该是

{
    "name":"Alian",
    "gender": "M",
    "mobile":"97437000",
    "visit_type":"1",
    "visit_purpose":"vvvvvvv"
}

或者,如果您希望将数据发送为;

{
    "visit":{
       "name":"Alian",
       "gender": "M",
       "mobile":"97437000",
       "visit_type":"1",
       "visit_purpose":"vvvvvvv"
    },
    "description":"this is testing!!!!!"
}

然后像这样更改您的POST逻辑;

@api_view(['GET', 'POST'])
def create_visitor(request):
   if request.method == 'GET':
      visitor = Visit.objects.all()
      serializer = VisitSerializers(visitor, many=True)
      return Response(serializer.data)
   elif request.method == 'POST':
     serializer = VisitSerializers(data=request.data.get('visit')) # <-- here get visit object
     if serializer.is_valid(raise_exception=ValueError):
         serializer.create(validated_data=request.data)
         return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.error_messages,
                     status=status.HTTP_400_BAD_REQUEST)

,但是您发送的数据中的其他字段(例如description)将未被使用。您还应该更改代码。

答案 1 :(得分:1)

这可以通过不同的方法解决。

您的VisitSerializers与Visit Model链接,您的VisitSerializers应该可以预期。

fields = ('name','gender','mobile','email','address',
'visit_type','visit_purpose','visitor_photo','id_photo')

但是您只发送两个字段

Visit作为对象。它包含姓名,性别,移动visit_type和visit_purposes。
description为文本

但是您的VisitSerializers无法理解visitdescription数据

1。如果您不想更改发送和接收数据的方式

因此,一种方法是从请求数据中提取必要的数据。

visit_serializer_data = request.data.get('visit')

然后您将获得

{ "name":"Alian", "gender": "M", "mobile":"97437000", "visit_type":"1", "visit_purpose":"vvvvvvv" }

然后通过visit_serializer_data


     serializer = VisitSerializers(data=visit_serializer_data)
     serializer.is_valid(raise_exception=True)
     instance = serializer.save()
        # handle you remaining logic here 
     ....
     ...

2如果要更改传递的数据。

更改为以下内容。由于您的VisitSerializer数据需要它们。

{
       "name":"Alian",
       "gender": "M",
        "mobile":"97437000",
       "visit_type":"1",
      "visit_purpose":"vvvvvvv"
   }

3您正在传递数据VisitSerializers将其更改为StatusSerializers(data = request.data)

您正在将数据发送到VisitSerializers。查看您的serializerscreate_visitordata。您应该在StatusSerializers方法中使用POST