Reputation: 13216
How can I prevent a POST request from being saved if the following items: 'email', 'youtube_channel_username', 'youtube_channel_url', 'youtube_channel_title'
already exist in the database? In effect, I want to add a validation step that ensures that what the user is trying to post is unique for the above-mentioned. Ideally the server should send back an error message to the user informing them that their request failed for whatsoever reason.
Here is my code so far. I am not sure where to add this feature, so I would appreciate some help!
serializers.py
class CreatorSignupSerializer(serializers.Serializer):
"""
Create Creator profile
"""
first_name = serializers.CharField(required=True, write_only=True)
last_name = serializers.CharField(required=True, write_only=True)
email = serializers.CharField(required=True, write_only=True)
youtube_channel_username = serializers.CharField(required=True, write_only=True)
youtube_channel_url = serializers.CharField(required=True, write_only=True)
youtube_channel_title = serializers.CharField(required=True, write_only=True)
youtube_channel_description = serializers.CharField(required=True, write_only=True)
photo = serializers.CharField(required=True, write_only=True)
youtube_channel_start_date = serializers.CharField(required=True, write_only=True)
keywords = serializers.CharField(required=True, write_only=True)
no_of_subscribers = serializers.IntegerField(required=True, write_only=True)
no_of_videos = serializers.IntegerField(required=True, write_only=True)
no_of_views = serializers.IntegerField(required=True, write_only=True)
no_of_likes = serializers.IntegerField(required=True, write_only=True)
no_of_dislikes = serializers.IntegerField(required=True, write_only=True)
location = serializers.CharField(required=True, write_only=True)
avg_views = serializers.IntegerField(required=True, write_only=True)
gender = serializers.IntegerField(required=True, write_only=True)
password = serializers.CharField(required=True, write_only=True)
class Meta:
model = Creator
fields = (
'first_name', 'last_name', 'email', 'youtube_channel_username', 'youtube_channel_url',
'youtube_channel_title', 'youtube_channel_description', 'photo', 'youtube_channel_start_date', 'keywords',
'no_of_subscribers', 'no_of_videos', 'no_of_views', 'no_of_dislikes', 'no_of_likes' 'location', 'avg_views',
'gender', 'password',
)
read_only_fields = 'id'
def create(self, validated_data):
creator = Creator.objects.create(**validated_data)
creator.save()
return creator
def update(self, instance, validated_data):
pass
views.py
class CreatorSignup(generics.CreateAPIView):
"""
Creator signup
HTTP POST
"""
queryset = Creator.objects.all()
serializer_class = CreatorSignupSerializer
def post(self, request, *args, **kwargs):
return self.create(request, *args, **kwargs)
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
return Response(data=serializer.data, status=status.HTTP_201_CREATED)
Upvotes: 1
Views: 48
Reputation: 5919
You can achieve unique validation at the Model level very easily. You just have to override save to call the full_clean method (if you have any other validation at the model level). Moreover, as a note, it will throw django.exceptions.ValidationError
and you can configure DRF to catch django.exceptions.ValidationError
and convert it to rest_framework.exceptions.ValidationError
and then DRF will automatically send a good error message back with 400.
# models.py
class User(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(max_length=255, unique=True) # NOTE unique=True
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
phone = models.CharField(max_length=20)
def save(self, *args, **kwargs):
self.full_clean()
return super().save(*args, **kwargs)
Upvotes: 3
Reputation: 88569
What about adding unique_together
in models' Meta class, as below
class Creator(models.Model):
email = models.EmailField()
youtube_channel_username = some_field
youtube_channel_url = some_field
youtube_channel_title = some_field
# etc
class Meta:
unique_together = ('email', 'youtube_channel_username', 'youtube_channel_url', 'youtube_channel_title')
Note : If you add this, you dont have to define any special validator method in your serializers
Upvotes: 2