4👍
I prefer to use the following approach where I have 2 serializer fields for 1 model field (one read only field for details and one id/url field for creates and updates):
class CartProductSerializer(serializers.HyperlinkedModelSerializer):
product_detail = ProductSerializer(source='product', read_only=True)
class Meta:
model = CartProduct
fields = ('url', 'cart', 'product', 'product_detail')
Note that this assumes ProductSerializer
is already defined elsewhere. And I’m omitting id because we don’t really need it but you can still add it if you want.
This has the following advantages:
- You can use the same serializer for all CRUD operations.
- You get the nested field details on GET but can just provide ids for those nested fields on POST / PUT.
- You don’t have to write any custom logic in your views to parse etc. – you can stick with the default generic view functionality that you get out of the box
So in your specific case, the JSON you’ll get back for a GET will be:
{
"url": "http://localhost:8000/appUsers/1/cart/products/16/",
"product": "http://localhost:8000/products/1/"
"product_detail": {
"url": "http://localhost:8000/products/1/",
"name": "Tomatoes",
},
"cart": "http://localhost:8000/carts/1/"
}
And for POSTs you’ll only need to send:
{
"product": "http://localhost:8000/products/2/"
"cart": "http://localhost:8000/carts/1/"
}
For PUTs, include the CartProduct
object’s own url
in the above JSON.
1👍
So you want the deserialized CartProductSerializer
to include a nested representation of Product
, while on the other hand, when serializing, you wish to provide only an id of an existing Product
? You’re right that creating an additional field is one solution, and I like it best.
- Set
product
as read-only, since you do not actually accept a nestedproduct
dictionary in your serializer (you can, though). - Create a new field,
product_id = ModelField(model_field=Product()._meta.get_field('id'))
. This will allow you to passproduct_id
when serializing. If you want to exclude this when deserializing, you can set it as write-only. See this answer.
- [Django]-.js files not included in page when using Django Form Assets (Media class) with crispy forms
- [Django]-Error in django interactive shell on pydev eclipse
1👍
You can change serializer behaviour by overriding to_representation
method
class CartProduct(models.Model):
cart = models.ForeignKey('Cart', on_delete=models.CASCADE)
product = models.ForeignKey('Product', on_delete=models.CASCADE)
class CartProductSerializer(serializers.HyperlinkedModelSerializer):
id = serializers.ReadOnlyField()
class Meta:
model = CartProduct
fields = ('id', 'url', 'product')
def to_representation(self, instance):
self.fields['product'] = ProductSerializer(read_only=True)
return super().to_representation(instance)
This way your serializer will use PrimaryKeyRelatedField
by default and on showing representation it will use nested ProductSerializer
NOTE: also you don’t need to explicitly supply id
field if it is default AutoField
, just adding it in fields
meta option should be enough
- [Django]-Django virtualenv – Error: No module named south
- [Django]-Django ForeignKey field required despite blank=True and null=True