多个模型保存在 POST 请求中。 (无效数据。需要字典,但得到了列表。)

Multiple models save in a POST request. (Invalid data. Expected a dictionary, but got list.)

我有两个模型。偏好和客户偏好。我想一次保存多个 customer_preferences。现在我收到以下错误。

{
  "customer_preferences": {
    "non_field_errors": [
      "Invalid data. Expected a dictionary, but got list."
    ]
  }
}

models.py

class Preferences(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    title = models.CharField(max_length=100, unique=True)


class CustomerPreferences(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    preference = models.ForeignKey(Preferences, db_index=True, on_delete=models.CASCADE,
                                   related_name='customer_preferences')
    customer = models.ForeignKey(Customer, db_index=True, on_delete=models.SET_NULL,
                                 related_name='customer_customer_preferences', null=True)
    status = models.CharField(max_length=100, null=True)

    user = models.ForeignKey(settings.AUTH_USER_MODEL, db_index=True, on_delete=models.CASCADE,
                             related_name='customer_preference_creator')

views.py

class PreferencesViewSet(viewsets.ModelViewSet):
    serializer_class = PreferencesSerializer
    queryset = Preferences.objects.all()


class CustomerPreferenceViewSet(viewsets.ModelViewSet):
    serializer_class = CustomerPreferencesSerializer
    queryset = CustomerPreferences.objects.all()

    model = CustomerPreferences

    def get_queryset(self):
        queryset = CustomerPreferences.objects.all()
        customer_id = self.request.query_params.get('customer_id', None)
        if customer_id is not None:
            queryset = queryset.filter(customer=customer_id)
        return queryset

    def get_serializer_class(self):
        if self.action == 'list' or self.action == 'retrieve':
            return CustomerPreferencesListSerializer
        return CustomerPreferenceSaveSerializer

serialzers.py

class PreferencesSerializer(serializers.ModelSerializer):
    model = Preferences

    class Meta:
        model = Preferences
        fields = '__all__'


class CustomerPreferencesListSerializer(serializers.ModelSerializer):
    model = CustomerPreferences
    preference = PreferencesSerializer()

    class Meta:
        model = CustomerPreferences
        exclude = ('id','user',)


class CustomerPreferencesSerializer(serializers.ModelSerializer):
    model = CustomerPreferences
    user = serializers.CharField(read_only=True)

    class Meta:
        model = CustomerPreferences
        fields = '__all__'


class CustomerPreferenceSaveSerializer(serializers.ModelSerializer):
    customer_preferences = CustomerPreferencesSerializer()

    class Meta:
        model = Preferences
        fields = ( 'customer_preferences',)

    def create(self, validated_data):
        request = self.context.get('request')
        customer_preferences_data = validated_data.pop('customer_preferences')
        customer_id = request.POST.get('customer', None)

        for cust_prefernce in customer_preferences_data:
            cust_prefernce_obj = CustomerPreferences.objects.create(
                preference_id=cust_prefernce['preference'],
                status=cust_prefernce['status'],
                customer = customer_id,
                user = request.user
            )
        return CustomerPreferences.objects.all()

urls.py

router.register(r'customer-preference', views.CustomerPreferenceViewSet, 'customers')
router.register(r'preference', views.PreferencesViewSet, 'preferences')

我想提交多个 customer_preferences 如下。 Aslo 'customer' 无法从我的序列化器

访问

POST请求

{
  "customer":"ddf30356-9dba-4e0b-9ae7-9c589dff004",
  "customer_preferences":  [
    {
      "id": "20d1a84a-bde8-45dd-81bc-ce2fda855a91",
      "status": "like"
    },
    {
      "id": "df791115-dd5b-4446-b954-24f7c1bbc4f4",
      "status": "dislike"
    },
    {
      "id": "4a3c317f-f202-4b6f-ae9d-598c7aff5fe7",
      "status": ""
    },
    {
      "id": "9ac24dda-df86-4f11-a18d-6f438929751d",
      "status": "neutral"
    }
  ]
}

您发布了模型 CustomerPreferences,它定义了客户和偏好之间的映射。

您发布的序列化程序就是用于此映射的序列化程序 - 它序列化了一种偏好与一位客户之间的关系。

我想你想 display/update 一个客户的偏好,所以我的回答是基于这个假设。

使用您当前的模型结构,您可以获得一位客户的 CustomerPreferences customer.customer_customer_preferences.all()。您需要一个使用 CustomerPreferencesSerializer(many=True) 来处理多个首选项的 CustomerSerializer:

class CustomerSerializer(Serializer):
     model = Customer
     # ... more fields
     customer_preferences = CustomerPreferencesSerializer(source='customer_customer_preferences', many=True)

代码未经测试。您可能需要自定义代码才能保存。

http://www.django-rest-framework.org/api-guide/relations/#nested-relationships

我已经通过如下更新序列化程序解决了这些问题。

serializers.py

class CustomerPreferencesSerializer(serializers.ModelSerializer):
    model = CustomerPreferences
    user = serializers.CharField(read_only=True)
    class Meta:
        model = CustomerPreferences
        fields = '__all__'


class CustomerPreferencesListSerializer(serializers.ModelSerializer):
    model = Preferences
    customer_preferences = serializers.SerializerMethodField()

    def get_customer_preferences(self, obj):
        request = self.context.get('request')
        customer_id = request.query_params.get('customer_id', None)
        customer_pref = CustomerPreferences.objects.filter(preference_id=obj, customer=customer_id)
        serializer = CustomerPreferencesSerializer(customer_pref, many=True)
        return serializer.data



    class Meta:
        model = Preferences
        fields = ('id', 'title','status')


class CustomerPreferenceSaveSerializer(serializers.Serializer):
    model = Customer
    customer_preferences = CustomerPreferencesSerializer(source='customer_customer_preferences', many=True,read_only=True)

    class Meta:
        model = Customer
        fields = ('customer','customer_preferences',)

    def create(self, validated_data):
        request = self.context.get('request')
        customer = request.data.get('customer', None)
        customer_preferences_data = request.data.get('customer_preferences', [])

        # first delete all entries of the given customer
        customer_preferences_obj = CustomerPreferences.objects.filter(customer=customer)
        customer_preferences_obj.delete()

        for cust_prefernce in customer_preferences_data:
            cust_prefernce_obj = CustomerPreferences.objects.create(
                preference_id=cust_prefernce['preference'],
                status=cust_prefernce['status'],
                customer_id = customer,
                user = request.user
            )

        return Customer.objects.all().get(id=customer)

views.py

class PreferencesViewSet(viewsets.ModelViewSet):
serializer_class = PreferencesSerializer
queryset = Preferences.objects.all()


class CustomerPreferenceViewSet(viewsets.ModelViewSet):
    serializer_class = CustomerPreferencesSerializer
    queryset = CustomerPreferences.objects.all()

    model = CustomerPreferences

    def get_queryset(self):
        queryset = Preferences.objects.all()
        return queryset

    def get_serializer_class(self):
        if self.action == 'list' or self.action == 'retrieve':
            return CustomerPreferencesListSerializer
        return CustomerPreferenceSaveSerializer