问题
I am using Django Rest Framework in my app, and I need to create new model instances which contain foreign keys. These refer to existing objects in another table, so I don't want new instances of these foreign objects to be created. Also I cannot access these objects via their primary keys, as that information is not submitted (I need to filter on certain fields which are included in the POST request).
How do I do this? This question seems to address the same issue, though it's not clear to me that the accepted answer actually solves the problem. Suppose I have two models, Category and Item, with a ForeignKey field in the latter specifying the category:
class Category(models.Model):
name = models.TextField()
format = models.TextField()
page = models.IntegerField(default=1)
order = models.IntegerField(default=1)
class Item(models.Model):
username = models.TextField()
title = models.TextField()
category = models.ForeignKey('Category', null=True)
data = JSONField(null=True, blank=True)
The body of the POST request consists of a JSON payload, with the category defined as an object specifying the format, page and order fields:
POST /api/items
{
"username" : "test",
"title" : "foo",
"category" : {
"format" : "A",
"page" : 2,
"order" : 1
},
"data" : [1,2,3,4,5]
}
Then I suppose I might define my Item serializer as follows, overriding create so that it retrieves the right Category instance by filtering on the appropriate fields, and setting it into the returned Item instance:
class ItemSerializer(serializers.ModelSerializer):
category = CategorySerializer()
data = serializers.ListField()
class Meta:
model = Item
fields = ('username', 'title', 'category', 'data')
def create(self, validated_data):
category_dict = validated_data.pop('category')
item = Item.objects.create(**validated_data)
format = category_dict.format
page = category_dict.page
order = category_dict.order
item.category = Category.objects.get(format=format, page=page, order=order)
return item
Is this the right way to do it?
回答1:
It will be like
try:
category = Category.objects.get(format=format, page=page, order=order)
except Category.DoesNotExist:
# either make it None or create new category, depends on your requirement
category = None
# or create new category
except Category.MultipleObjectsReturned:
category = category.first() # it depends on your requirement
item.category = category
回答2:
At least there is one error,you should use get to get only one category as you item's category instead of use filter to get queryset.
class ItemSerializer(serializers.ModelSerializer):
category = CategorySerializer()
data = serializers.ListField()
class Meta:
model = Item
fields = ('username', 'title', 'category', 'data')
def create(self, validated_data):
category_dict = validated_data.pop('category')
item = Item.objects.create(**validated_data)
format = category_dict.format
page = category_dict.page
order = category_dict.order
try:
item.category = Category.objects.get(format=format, page=page, order=order)
except Category.DoesNotExist:
pass
except Category.MultipleObjectsReturned:
pass
return item
来源:https://stackoverflow.com/questions/47974094/django-rest-framework-serializer-access-existing-foreign-key