Home > Software design >  Django - how to validate data from post that is not in a django form?
Django - how to validate data from post that is not in a django form?

Time:12-28

I am receiving post data from my template but it's being created with js, it is not a django form. I know that if I am posting a field using a django form I can use form.is_valid() or x = form.cleaned_data['field'] but I don't know how to validate/clean my data when not using a django form. The reason that I'm using js for this form/template is to get a specific look that I couldn't do with a standard django template/form.

models.py

class AssessComment(models.Model):
    assessment = models.ForeignKey(Assessment, on_delete=models.CASCADE)
    student = models.ForeignKey(Student, on_delete=models.CASCADE)
    comment = models.TextField(blank=True)

js snippet

// this js is appended to the grade-form element in the template
document.getElementById('grade-form').appendChild(table);
comment = document.createElement('td');
commentName = "row-"   n   "-comment";
commentText = document.createElement("textarea");
commentText.setAttribute("name", commentName);
rowName[n].appendChild(comment);
comment.appendChild(commentText);

The above js is putting a textarea in a table and giving it the name commentName. The template sends this as a post to my view. I iterate through several rows of n.

template

div >
  <form action="" method="post">{% csrf_token %}
    <div id="grade-form"></div> <!-- js is inserted here -->
      <div >
        <button type="submit" >Submit</button>
      </div>
  </form>
</div>

views.py

while s < len(cs):
    comment = "row-"   str(s)   "-comment"
    form_comment = request.POST[comment] # this gets the commentName element
    new_comment = AssessComment()
    new_comment.comment = form_comment
    new_comment.assessment = this_assessment
    new_comment.student = student_list[s]
    comment_list.append(new_comment)
    s =1
AssessComment.objects.bulk_create(comment_list)

This code works as intended. The user inputs text into the textarea and when the form is submitted, new AssessComment objects are created with the appropriate fields. However, I'm not doing any validation or cleaning. I don't know how important this is, I don't know what validation is even done on a TextField. If this wasn't a TextField but an EmailField, I can see how important it would be. I wonder if validation done on a TextField that helps prevent malicious code, which would be very important. I could maybe re-write all of this code to not use javascript. Since I first wrote this code I think I may have figured out a way to implement this form without needing js. Having said all this, I would still like to know how validate the form_comment field.

CodePudding user response:

You can create a form with whatever fields you want and as long as your JavaScript form that you will actually display on the page submits the correct data you can validate the form as usual as if it were sent by a {{ form }} in the template, just make sure the name of the textfield matches the one that would have been given by the {{ form }} if it were used instead.

# forms.py
class AssessCommentForm(forms.ModelForm):
    class Meta:
        model = AssessComment
        fields = ['comment',]

As long as the request.POST is giving the same name as would be submitted by a form created with {{ form }}, the AssessCommentForm will not know or care that it came from JavaScript.

# views.py
form = AssessCommentForm(request.POST or None)
if form.is_valid():
    # process form

I'm sure there are ways to validate a single field, but that I'm afraid I do not know how to do yet.

CodePudding user response:

You can just validate the field on model level something like this:

from django.core.exceptions import ValidationError

def validate_special_characters(value):
  if ['$', '/', '#'] in value:
     raise ValidationError("Special characters not allowed")          
  else:
     return value

class AssessComment(models.Model):
    assessment = models.ForeignKey(Assessment, on_delete=models.CASCADE)
    student = models.ForeignKey(Student, on_delete=models.CASCADE)
    comment = models.TextField(blank=True, validators=[validate_special_characters])

that will raise exception if the comment you are storing has the mentioned special characters present. Similarly you can add more validations by comma separated values in the validators.

read more about how validation is done in forms here and you can use same to add your own validation in your models.

  • Related