Невозможно сохранить объекты, используя вложенный сериализатор в django rest framework - PullRequest
0 голосов
/ 13 июня 2019

Я должен сохранять объекты двух разных моделей и использовать вложенные сериализаторы.Я использую следующие django rest docs: - https://www.django -rest-framework.org / api-guide / Relations / # Writable% 20nested% 20serializers

Я следовал многим решениям по stackoverflowоднако я не могу понять следующую ошибку: -

Bad Request: /api/register
"POST /api/register HTTP/1.1" 400 50

Я проверил сериализаторы, напечатав request.data, и они работают нормально.Однако serializer.is_valid(raise_exception=True) вызывает вышеуказанную ошибку.

serializers.py

# Serializer for report

class ReportAPISerializer(serializers.ModelSerializer):
    latitude = serializers.FloatField()
    longitude = serializers.FloatField()

    class Meta:
        model = Property
        fields = ('longitude', 'latitude', 'consumer_type', 'area', 'avg_monthly_bill',)


# Serializer to get user details

class UserSerializer(serializers.ModelSerializer):
    property = ReportAPISerializer()

    class Meta:
        model = InterestedUser
        fields = ('full_name', 'phone_no', 'email', 'property')

    def create(self, validated_data):
        property_data = validated_data.pop('property')
        user = InterestedUser.objects.create(**validated_data)
        Property.objects.create(
            owner=user,
            location=Point(property_data['latitude'], property_data['longitude']),
            area=property_data['area'],
            consumer_type=property_data['consumer_type'],
            avg_monthly_bill=property_data['avg_monthly_bill']
        )
        return user

views.py

class RegisterAPIVIew(CreateAPIView):
    serializer_class = UserSerializer

models.py

class InterestedUser(AbstractBaseUser, PermissionsMixin):
    user_id = models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True)

    date = models.DateTimeField(auto_now_add=True, null=True, blank=True)
    full_name = models.CharField(max_length=50, default="")
    email = models.EmailField(blank=False, unique=True)
    phone_no = models.CharField(max_length=10, default="")
    active = models.BooleanField(default=False)
    staff = models.BooleanField(default=False)
    admin = models.BooleanField(default=False)
    password = models.CharField(default="", max_length=128)
    is_superuser = None

    objects = InterestedUserManager()

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = []

    class Meta:
        verbose_name = 'user'
        verbose_name_plural = 'users'

    def __str__(self):
        return "%s -- %s" % (self.full_name, self.email)

    def get_full_name(self):
        if self.full_name:
            return self.full_name

        return self.email

    def get_short_name(self):
        return self.email

    def has_perm(self, perm, obj=None):
        return True

    def has_module_perms(self, app_label):
        return True

    @property
    def is_staff(self):
        return self.staff

    @property
    def is_admin(self):
        return self.admin

    @property
    def is_active(self):
        return self.active



class Property(models.Model):
    property_id = models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True)
    owner = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)

    avg_monthly_bill = models.FloatField(default=0.0)
    consumer_type = models.CharField(max_length=15, null=True)
    location = models.PointField(null=True, blank=True)
    area = models.FloatField(null=True)

следующий код, который я использую на стороне интерфейса (usign Vue): -

createAccount(fullName, email, phoneNo, latitude, longitude, area, consummerType, avgMonthlyBill){
    console.log(fullName + " ", email + " " + phoneNo + latitude + " " + longitude + " " + area + " " + consummerType + " " + avgMonthlyBill)
    let property = {
      'latitude':latitude,
      'longitude':longitude,
      'area':area,
      'consumer_type':consummerType,
      'avg_monthly_bill':avgMonthlyBill
    }
    return session.post('register', {
                                'full_name':fullName, 
                                'email':email, 
                                'phone_no':phoneNo, 
                                'property':property
                              });
  },

1 Ответ

0 голосов
/ 14 июня 2019

В вашей модели InterestedUser нет атрибута property, но вместо этого property_set, и это потому, что вы использовали ForeignKey, поэтому InterestedUser <-> Property - это отношение 1: N.

Что вы можете сделать?

  • Добавьте related_name=properties в ваше поле owner в Property
  • На вашем UserSerializer, property = ReportAPISerializer(source='properties', many=True)

Существуют и другие вопросы, связанные с тем, как вы проектировали эти объекты, я бы предложил вам кое-что помнить:

  • Если несколько пользователей могут быть заинтересованы в многократных свойствах, перейдите к ManyToMany
  • Не используйте property в качестве имени поля сериализатора, property - зарезервированное слово Python.
...