Tuesday, June 14, 2011

Tutorial: Make Ajax Form in Django + Bleach Sanitization on Playdoh + Jingo + Jinja

You can see the final version of complete files here.


1. Import bleach.

2. Make a new (dummy) url
2: in urls.py
(r'^richtext$', 'richtext'),

3. models.py: Make a new model. Go to SQL to add some initial entries into the model.

My model, RichText, looks like this:
3: in models.py:
from django.db import models
class RichText(models.Model):
    name = models.CharField(max_length=200)
    comment = models.TextField()

4. models.py: Make a form associated with that model, it's a Django ModelForm.

5. models.py: Clean the commented data through bleach.clean()


5a. clean_<fieldname>(): Note that the method name "clean_comment" is not chosen arbitrarily. It must start with "clean_" and the 2nd part must match with one of the fields of the model.


5b. cleaned_data[]: is like POST[] or REQUST[], but with cleaned_data, the "data has not only been validated but will also be converted in to the relevant Python types".

5c. Finally do a bleach.clean on the data before it's returned.

4+5: in models.py:
from django.forms import ModelForm
class RichTextForm(ModelForm):
    class Meta:
        model = RichText

    def clean_comment(self): #comment must match one of the fields of model
        data = self.cleaned_data['comment']
        return bleach.clean(data)

6. richtext.html: Make the Django form's html
<form id="myform" action="" method="post">
    {{ csrf() }}
    {{ form.as_p() }}
<input type="submit" value="Submit" />
</form>

You might get an CRSF error at this point... keep reading

Note that the "CSRF()" is different from how Django usually contains it, it's explained here and in the flip below:.
CSRF Explanation
Django's fix to CSRF can be found in [https://docs.djangoproject.com/en/dev/intro/tutorial04/ the tutorial]. Where you put in

template.html:
{% csrf_token %}

views.py:
from django.shortcuts import render_to_response
from django.template import RequestContext
def ...
    return render_to_response('template.html', {'var_name': var_value}, context_instance=RequestContext(request))

But in the demo's setup with jingo and other stuff:
template.html:
{{ csrf() }}
views.py:
import jingo
    return jingo.render(request, 'template.html', {"var_name": var_value})

7. richtext.html: add AJAX to submit form and display all results
<script src="http://code.jquery.com/jquery-latest.min.js" type="text/javascript">
</script>
    <div id="results">
    {% include 'msw/richtext_table.html' %}
</div>
    <script>
        $("#myform").submit(function(){
            $.post(location.href, $('#myform').serialize(), function(d) {
$('#results').html(d);   
});
            return false;
        })
    </script>

If the HTML is not rendered, use "|safe".
richtext_table.html:
    {% if all_richtext_list %}
        {% for richtext in all_richtext_list %}
            <p>Name title: <b>{{ richtext.name|safe }}</b> says: <b>{{ richtext.comment|safe }}</b></p>
        {% endfor %}
    {% else %}
        <p>No comments are available.</p>
    {% endif %}

8. views.py: Save new Django AJAX form inputs

NOTE: There are 2 different template filenames. The "_table.html" is there so that whenever there is a post, ONLY the output table is rendered. Without that line, the entire page would be rendered!!

import bleach
from msw.models import RichText, RichTextForm
...

def richtext(request):
    file = 'msw/richtext.html'
    if request.method == "POST":
        form = RichTextForm(request.POST)
        if form.is_valid():
            form.save()
        file = 'msw/richtext_table.html'
    else:
        form = RichTextForm()
    return jingo.render(request, file, {"form": form, "title_chunk" : "Bleach Testing:", "all_richtext_list": RichText.objects.all()})


You can see the final version of complete files here.

No comments:

Post a Comment