Reputation: 1487
I want to automatically generate the "path" field of my model when I use the create method of my serializer. Otherwise I would like to be able to pass this field in my request to be able to modify it later. I haven't found a way to make a single field of my template optional. Here is my model :
models.py
class Shop(models.Model):
name = models.CharField(max_length=255)
category = models.ForeignKey(ShopCategory, on_delete=models.SET_NULL, null=True, blank=True)
description = models.TextField(blank=True, null=True)
path = models.CharField(max_length=255, unique=True)
mustBeLogged = models.BooleanField(default=False)
deliveries = models.FloatField(default=7)
def __str__(self):
return self.name
Here is my code :
serializer.py
class ShopSerializer(serializers.ModelSerializer):
class Meta:
model = Shop
exclude = ['path']
def create(self, validated_data):
path = validated_data["name"].replace(" ", "-").lower()
path = unidecode.unidecode(path)
unique = False
while unique == False:
if len(Shop.objects.filter(path=path)) == 0:
unique = True
else:
# Generate a random string
char = "abcdefghijklmnopqrstuvwxyz"
path += "-{}".format("".join(random.sample(char, 5)))
shop = Shop.objects.create(**validated_data, path=path)
shop.save()
return shop
views.py
def post(self, request):
"""For admin to create shop"""
serializer = ShopSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response(serializer.errors)
Upvotes: 0
Views: 2729
Reputation: 997
You can set path to be accepted as Null and pop it in create method. In this way you won't have to add it in exclude
.
class ShopSerializer(serializers.ModelSerializer):
path = serializers.CharField(allow_blank=True, allow_null=True)
class Meta:
model = Shop
fields = '__all__'
def create(self, validated_data):
validated_data.pop('path')
path = validated_data["name"].replace(" ", "-").lower()
path = unidecode.unidecode(path)
unique = False
while unique == False:
if len(Shop.objects.filter(path=path)) == 0:
unique = True
else:
# Generate a random string
char = "abcdefghijklmnopqrstuvwxyz"
path += "-{}".format("".join(random.sample(char, 5)))
shop = Shop.objects.create(**validated_data, path=path)
shop.save()
return shop
def update(self, instance, validated_data):
#You will have path in validated_data
#And you may have to check if the values are null
return super(ShopSerializer, self).update(instance, validated_data)
Apart from this, in your code:
while unique == False:
if len(Shop.objects.filter(path=path)) == 0:
This would be very costly operation. In every loop it would fire a query, I'm not sure about the logic behind it but you may want to change this.
Upvotes: 1