0

For example I have the ff:

models:

class Store(models.Model):
    name = models.CharField(max_length = 20)

class Product(models.Model):
    name = models.CharField(max_length = 20)

class StoreProducts(models.Model):
    store = models.ForeignKey(Store)
    product = models.ForeignKey(Product)
    qty = models.IntegerField()

serializer:

class StoreProductsSerializer(serializers.ModelSerializer):
    class Meta:
        model = StoreProducts
        fields = ('store', 'product', 'qty')

And defined values:

Store (id, name):
 1, store_1
 2, store_2

Product (id, name):
 1, product_1
 2, product_2

Now in the views, I want to add into the StoreProducts from post request without querying the ids of Store and Product like this:

data = {
'store': 'store_1',
'product': 'product_1',
'qty': 1
}

serializer = StoreProductsSerializer(data=data)
    if serializer.is_valid():
        serializer.save()

Is this possible and how? Thanks

ACD
  • 1,431
  • 1
  • 8
  • 24
  • Does this answer your question? [Rest Framework deserialize one field and serialize model object](https://stackoverflow.com/questions/60256462/rest-framework-deserialize-one-field-and-serialize-model-object) – JPG Feb 17 '20 at 06:20

2 Answers2

1

You have to use nested serializers in that case. DRF does not provide create and update functionality with nested serializers, so you will have to take care of that as well.

class StoreSerializer(serializers.ModelSerializer):
    class Meta:
        model = Store
        fields = ('name',)

class ProductSerializer(serializers.ModelSerializer):
    class Meta:
        model = Product
        fields = ('name',)

class StoreProductsSerializer(serializers.ModelSerializer):
    store = StoreSerializer()
    product = ProductSerializer()

    class Meta:
        model = StoreProducts
        fields = ('store', 'product', 'qty')

    def create(self, validated_data):
        store = Store.objects.create(validated_data.pop('store'))
        product = Product.objects.create(validated_data.pop('product'))
        return super().create({**validated_data, 'store': store, 'product': product}) 
Nafees Anwar
  • 6,324
  • 2
  • 23
  • 42
  • works fine but overriding create ignores the model's field attributes, example nullable fields needs to be filled. – ACD Feb 17 '20 at 07:02
1

You can take value that you want and in validate method you can change it with object. But you must use unique field for this method.I'm not sure whether it is a good way There is a sample:

class StoreProductsSerializer(serializers.ModelSerializer):
    class Meta:
        model = StoreProducts
        fields = ('store', 'product', 'qty')

    def validate(self, attrs):
        attrs['product'] = Product.objects.get(name=attrs['product'])
        attrs['store'] = Store.objects.get(name=attrs['store'])
        return attrs
kamilyrb
  • 2,502
  • 3
  • 10
  • 25
  • 1
    have to unpack the values instead of using as direct search string. but everything works fine. Thanks! – ACD Feb 17 '20 at 07:00
  • technically still queries for the ID but it's cleaner than querying it on the view functions. – ACD Feb 17 '20 at 07:04