Reputation: 553
I would like to be able to parse the data from a post request in my django rest api project by sending it to my function that will return true or false if the number is valid before saving it to the database and if it's wrong send a custom bad request message to the client that did the request.
I've been told I can overwrite the create method todo this but I'm not sure how to go about it.
My code so far looks like this:
class Messages(models.Model):
phone_number = models.CharField(max_length=256, default='')
message_body = models.CharField(max_length=256, default='')
created = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.phone_number + ' ' + self.message_body + ' ' + self.created
def save(self, force_insert=False, force_update=False, using=None, update_fields=None):
# I assume this is where I would do the check before saving it but not sure how? example would be like:
# if numberValid(self.phone_number):
# then save to the database
# else:
# then send back a bad request?
super(Messages, self).save(force_update=force_update)
send_sms(self.phone_number, self.message_body)
def delete(self, using=None, keep_parents=False):
super(Messages, self).delete(using=using, keep_parents=keep_parents)
So basically just would like some direction on how to solve this problem. Even helpful links would be appreciated. I did look on stackoverflow but was not successful, maybe I don't know how to phrase the question right when searching.
Upvotes: 6
Views: 10471
Reputation: 51938
You can use DRF Serializer's validation. For example, create a serializer, and add a validation method naming validate_<field_name>
. Then add the validation code there:
import re
class MessagesSerializer(serializers.ModelSerializer):
class Meta:
model = Messages
fields = "__all__"
def validate_phone_number(self, value):
rule = re.compile(r'(^[+0-9]{1,3})*([0-9]{10,11}$)')
if not rule.search(value):
raise serializers.ValidationError("Invalid Phone Number")
return value
And use it in the view:
class SomeView(APIView):
def post(self, request, *args, **kwargs):
serializer = MessagesSerializer(
data=request.data
)
if serializer.is_valid(): # will call the validate function
serializer.save()
return Response({'success': True})
else:
return Response(
serializer.errors,
status=status.HTTP_400_BAD_REQUEST
)
Upvotes: 8
Reputation: 1374
You want to validate the fields before saving.
There are quite a few techniques to do that.
using serializers. If you are using django rest framework, then you can easily use serilizers for validating. https://www.django-rest-framework.org/api-guide/validators/
django model validation. This is by overriding some of the available methods in models class. https://docs.djangoproject.com/en/2.2/ref/models/instances/#validating-objects
For your scenario i would suggest second option. Override the method clean_fields as in documentation. Then call the method just before saving.
Upvotes: 1
Reputation: 1682
Check the official documentation for how this is to be done: https://docs.djangoproject.com/en/2.2/ref/models/instances/#django.db.models.Model.clean
This method should be used to provide custom model validation, and to modify attributes on your model if desired. For instance, you could use it to automatically provide a value for a field, or to do validation that requires access to more than a single field:
def clean(self):
# Don't allow draft entries to have a pub_date.
if self.status == 'draft' and self.pub_date is not None:
raise ValidationError(_('Draft entries may not have a publication date.'))
# Set the pub_date for published items if it hasn't been set already.
if self.status == 'published' and self.pub_date is None:
self.pub_date = datetime.date.today()
Implement a clean
method that will raise a ValidationError
if it detects a problem with the data. You can then catch this in the view by calling model_obj.full_clean()
:
from django.core.exceptions import NON_FIELD_ERRORS, ValidationError
try:
article.full_clean()
except ValidationError as e:
non_field_errors = e.message_dict[NON_FIELD_ERRORS]
Upvotes: 2
Reputation: 2525
Model.save() is an option although it's more common to validate input data, like a phone number being posted, in the DRF Serializer.
Where to perform checks is a decision you can make based on the principal of separation of concerns.
Upvotes: 1