django - verifying data - django

in my django application, I allow users to cut and paste some json data into a textbox, to be uploaded to the database for saving.
I would like to verify the json data before saving them into my database. Do I have to write custom code to check every field or is there some form api I can use to check the data ?

Create a form with validation methods
http://docs.djangoproject.com/en/dev/topics/forms/
or use a model form:
http://docs.djangoproject.com/en/dev/topics/forms/modelforms/

If it decodes, then I guess it's json...
However one wonders why you'd put that straight into your database without parsing it? Are you planning to do something like serve it straight back to them later? If so then you can validate it client side.

Since you are allowing user to enter (basically) arbitrary data care must be taken against SQL InJection or XSS. Django has support for both, here's how -
In your template, next to the form place a csrf_token which prevents CSRF.
To prevent SQL Injection attacks, place urlencode filter in your templates wherever applicable. Well not much but it protects against cases like - turns your apostrophes ' into %27, rendering them harmless
Also if you have your form.py like ./app/form.py, then while defining a form -
class RegistrationForm(forms.Form):
username = forms.CharField(label='Username', max_length=30)
def clean_username(self):
username = self.cleaned_data['username']
# do any more processing you need.
Also if you are using JSON, then be sure to use inbuilt modules for this for the risk of reinventing the wheel.

Related

Django: Send posted files to a different form

Well, I have to send files posted by one form to other form, I have to read an XML file first, if the file is valid I'll redirect to the next form, which has to have the valid file received in the past form. I tried with sessions but I'm not sure if it's the right way to go, here my models.
class InitialForm(models.Model):
...
name = models.CharField(max_length=50)
xml = models.FieldField(label='Please choose an XML file')
...
class SecondForm(models.Model):
...
name = models.CharField(max_length=50)
pdf = models.FieldField(label='Please choose a PDF file')
...
The reason I got two forms is because I've got to read the XML first and validate it, and then in the next form 'SecondForm' show the data I just parse from the XML in order to verify and give feedback to the user. Then both files must be inserted in a database, only if the first one is valid.
Any help will be welcome.
Thanks in advance.
I think what you need is a form wizard that Django offers for situations when you need to build a form that is split into multiple requests.
From their docs this is how it works:
The user visits the first page of the wizard, fills in the form and
submits it.
The server validates the data. If it’s invalid, the form
is displayed again, with error messages. If it’s valid, the server
saves the current state of the wizard in the backend and redirects to
the next step.
Step 1 and 2 repeat, for every subsequent form in the
wizard.
Once the user has submitted all the forms and all the data has
been validated, the wizard processes the data – saving it to the
database, sending an email, or whatever the application needs to do.

Customizing Django.contrib.comments honeypot

I'm using Django's standard comment system and I would like to extend its anti-spam honeypot capability.
I thought of changing the default "name" and "id" of the field to something more alluring for spam-bots such as "website". I checked the html and this looks like this:
<p style="display:none;">
<label for="id_honeypot">Never send a human to do a machine's job</label>
<input type="text" name="honeypot" id="id_honeypot" />
</p>
Am I correct in thinking that changing the defaults of this element would boost its anti-spam capabilities? I tried modifying it in the django/contrib/comments/forms.py like this:
class CommentForm(CommentDetailsForm):
#use to be honeypot = forms.CharField(...
website = forms.CharField(required=False,
label=_('Never send a human to do a machines job')
def clean_honeypot(self):
"""Check that nothing's been entered into the honeypot."""
value = self.cleaned_data["website"]
if value:
raise forms.ValidationError(self.fields["website"].label)
return value
And this successfully changes the name and id in the html generated by django BUT then the whole mechanism stops working - I tried populating this invisible field, submitted and the comment was added.
I have a few other ideas as well, but first I'd really like to get this working - is it possible to modify the default honeypot name and id AND have it working like it should?
P.S I believe a more elegent way of doing this would be to extend django.contrib.comments and code the modification there instead of working on actual django code - what would be the best way of accomplishing this?
Given a bit more time to tinker around I found the answer to both of my questions:
In order to modify the standard honeypot or to create your own, you have to extend the CommentForm class by adding a clean_NAME_OF_HONEYPOT function as well as a NAME_OF_HONEYPOT variable both of which look similar to the standard ones and you also have to override the security_errors function to include the name of your new/modified honeypot in the dictionary.
The best way to do this is to create your custom comments app as described here: https://docs.djangoproject.com/en/dev/ref/contrib/comments/custom/ .
I hope this answer helps anyone else in my situation.

'Hiding' form query from URL (Django 1.3)

I have a form with 6-7 fields. After user input, my webapp searches for those fields in a database and displays the results.
Now the issue is, that the URL ends up having all the form field names and their values in it.
result/?name=lorem&class=arc&course=ipsum
Now with the form having 7-8 fields the url ends up looking ugly.
Is there a Django technique to 'hide' these from the URL? Quotes around hide because I'd be okay with a completely different way to pass the objects to my database from the form as well.
Use a POST request. Here's the django docs on forms and a specific example using POST>. HTML-wise, all you need to do is change the method on the form tag.
I do not recommend to use POST requests for search. If you'll use GET it will be easer for user, he can just bookmark a link and save search or share search results with friends.

Alternative form for Django's `ChoiceField` that can handle thousands of entries

I have a form with a ChoiceField in it. It is rendered to the user as a dropdown box.
Problem is, I have thousands of entries in this field, which is causing the page to (a) load very slowly and (b) be sluggish.
I want an alternative widget, instead of Select, that could handle more than 10,000 choices.
Something like the admin's raw_id_fields would be good (if only it were usable in general forms...) but I'm open to ideas.
If autocomplete is an option for your UI you can take a look to django-simple-autocomplete:
App enabling the use of jQuery UI autocomplete widget for
ModelChoiceFields with minimal configuration required.
EDITED (reply OP comment)
I have not tested this solution, but digging documentation and source it seems that not all data is loaded at a time:
The ability to specify an URL for the widget enables you to hook up to
other more advanced autocomplete query engines if you wish.
Source code:
def get_json(request, token):
"""Return matching results as JSON"""
...
di = {'%s__istartswith' % fieldname: searchtext} # <- look here!
items = queryset.filter(**di).order_by(fieldname)[:10]
Widget source code
$("#id_%(name)s_helper").autocomplete({
source: function(request, response){
$.ajax({ # <-- look here
url: "%(url)s",
data: {q: request.term},
success: function(data) {
I don't know what is the raw_id_fields but why not use a model to store all your choices ?
class Choice(models.Model):
value = models.CharField()
class MyModel(models.Model):
choice = models.ForeignKey(Choice)
It would then be easy to select it if you want to display only 20 at a time for example.
Based on this comment (which really, you should have included in your question):
Let me clarify my task: I have 10,000 users. I have a form in which
you choose a user. You need to be able to choose any user you want.
You can't just load 20, because then you won't be able to choose the
other 9,980 users.
If you want something built-in, you can use the FilteredSelectMultiple widget from django.contrib.admin.widgets, which puts a filter on your select.
You should also cache the results of the 10,000 users so you don't hit your db everytime. This is what is causing your delay, not the number of users (which is tiny, for practical performance problems).

Validating URL slugs

I'm creating an app in which many urls are using a pattern like /foo/bar/<object_id>/<object_name_slug>/, like many applications (SO included), which is itself a straightforward pattern to implement. However, I don't want to just blindly ignore the contents of the slug field and open the app up to stupid stuff like people distributing a doctored URL (e.g. the recently popular http://www.independent.co.uk/life-style/food-and-drink/utter-PR-fiction-but-people-love-this-shit-so-fuck-it-lets-just-print-it-2269573.html).
My plan is to validate the slug an issue a redirect to the correct URL if someone reaches a page via a bad slug (again, like SO). This would be trivial to implement in the view, but since this will be a pattern used on many views, I'd like to factor it out into something reusable--probably a decorator or a middleware.
What's the best way to do this? Could a decorator determine which url pattern was matched by a particular request so that it could generate a reverse if necessary?
Thanks for the ideas.
You could use middleware for this. Cross-check the Entry id (let's just suppose you use the Entry model for content. The ID in the URL you mention would be 2269573 for example) with its slug (supposing your Entry model has a slug field of course). If the slug is incorrect, just redirect to the correct page.
In order to do this, create a class, and give it the process_request method. Then add this class to your settings' MIDDLEWARE_CLASSES.
The process_request takes a "request" parameter (a HttpRequest object), and this object has a path attribute that will give you the URL that was requested.
Based on that URL you can define the actions to be undertaken.
The method of your middleware class should return None or a HttpRequest object. The latter can be a django.http.HttpResponseRedirect instance, meaning you can redirect to the correct URL (thereby ignoring the incorrect slug).