Showing posts with label bleach. Show all posts
Showing posts with label bleach. Show all posts

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.

Monday, June 13, 2011

News Forum Rich Text Sanitizing with Bleach

Bleach github
       - Is bleach already in django?
       - Example of bleach
- Make a news forum


Bleach
- Get the bleach module


(playdoh)haoqili@host-3-248:11:50:59:~/dev/playdoh/playdoh/playdoh$ ./manage.py shell
Python 2.7.1 (r271:86832, Jun  6 2011, 13:57:48)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> import bleach
Traceback (most recent call last):
  File "<console>", line 1, in <module>
ImportError: No module named bleach
>>>
KeyboardInterrupt
>>>
(playdoh)haoqili@host-3-248:12:00:06:~/dev/playdoh/playdoh/playdoh$ pip install -e git://github.com/jsocol/bleach.git#egg=bleach
Obtaining bleach from git+git://github.com/jsocol/bleach.git#egg=bleach
  Cloning git://github.com/jsocol/bleach.git to /Users/haoqili/.virtualenvs/playdoh/src/bleach
  Running setup.py egg_info for package bleach
   
Downloading/unpacking html5lib (from bleach)
  Downloading html5lib-0.90.zip (99Kb): 99Kb downloaded
  Running setup.py egg_info for package html5lib
   
Installing collected packages: bleach, html5lib
  Running setup.py develop for bleach
   
    Creating /Users/haoqili/.virtualenvs/playdoh/lib/python2.7/site-packages/bleach.egg-link (link to .)
    Adding bleach 1.0.2 to easy-install.pth file
   
    Installed /Users/haoqili/.virtualenvs/playdoh/src/bleach
  Running setup.py install for html5lib
   
Successfully installed bleach html5lib
Cleaning up...
(playdoh)haoqili@host-3-248:12:00:54:~/dev/playdoh/playdoh/playdoh$ ./manage.py shellPython 2.7.1 (r271:86832, Jun  6 2011, 13:57:48)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> import bleach
>>> bleach.clean('an <script>evil()</script> example')
u'an &lt;script&gt;evil()&lt;/script&gt; example'
>>> bleach.linkify('an http://example.com url')
u'an <a href="http://example.com" rel="nofollow">http://example.com</a> url'

==========
jsocol: the "u" indicates that it's a unicode string instead of a simple bytestring, it's a python thing
==========

jsocol: haoqili: there's no Bleach() class anymore, it's just "import bleach" or "from bleach import clean, linkify"









haoqili: I'm looking at __init__.py
[12:25pm] jsocol: ok
[12:25pm] haoqili: What is the significance of TLDS = """ac ad ae aero af ag ai al am an ao aq ar arpa as asia at au aw ax az
[12:25pm] haoqili: ba bb bd be bf bg bh bi biz bj bm bn bo br bs bt bv bw by bz ca cat?
[12:25pm] haoqili: i.e. what is TLDS?
[12:26pm] jsocol: TLD = Top Level Domain, it's supposed to be an exhaustive list of all the current, valid TLDs
[12:26pm] jsocol: so that, for example, "example.com" or "example.co.uk" gets linkified, but "example.txt" does not
[12:26pm] haoqili: ah
[12:26pm] haoqili: okay
[12:27pm] haoqili: I'm also trying to understand how clean's ALLOWED_TAGS get added to the pre-defined ALLOWED_TAGS
[12:28pm] haoqili: is it added or replaced?
[12:28pm] haoqili: I guess it's replaced?
[12:28pm] jsocol: replaced. if you pass in a tags= kwarg, your list supercedes the default list, so you can be more restrictive