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?
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
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
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.