多个模型保存在 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
我有两个模型。偏好和客户偏好。我想一次保存多个 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