Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django: How to check if data is correct before saving it to a database on a post request?

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.

like image 406
Marco Fernandes Avatar asked Apr 02 '19 12:04

Marco Fernandes


People also ask

When saving How can you check if a field has changed Django?

Since Django 1.8 released, you can use from_db classmethod to cache old value of remote_image. Then in save method you can compare old and new value of field to check if the value has changed. @classmethod def from_db(cls, db, field_names, values): new = super(Alias, cls).

How does Django save data to database?

Creating objects To create an object, instantiate it using keyword arguments to the model class, then call save() to save it to the database. This performs an INSERT SQL statement behind the scenes. Django doesn't hit the database until you explicitly call save() . The save() method has no return value.

How is data stored in Django?

Django uses databases to store data. More specifically, Django uses relational databases. Covering relational databases would be a gigantic topic so you'll have to settle for a very abridged version. A relational database is like a collection of spreadsheets.


4 Answers

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
          )
like image 98
ruddra Avatar answered Oct 24 '22 11:10

ruddra


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.

like image 35
Dwight Gunning Avatar answered Oct 24 '22 09:10

Dwight Gunning


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]
like image 25
ritlew Avatar answered Oct 24 '22 11:10

ritlew


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.

like image 1
Nelson Sequiera Avatar answered Oct 24 '22 09:10

Nelson Sequiera