views:

90

answers:

2

The use case I am try to address is a requirement for a user to have downloaded a file before being permitted to proceed to the next stage in a form process.

In order to achieve this, I have a Django Form to capture the user's general information which POSTS to Django view 'A'. The Form is displayed using a template which also includes an iFrame with a simple embedded button which links to the URL of Django view 'B'.

View 'B' simply sets a session variable to indicate that the download has occurred, and returns the URL of the file for download, thereby triggering the download.

As part of the validation of Form 'A' (the main Form), I need to check whether the session variable indicating file download is set.

My question is, is this best done using Form 'A' validation process, and if so, how is this best achieved?

If this is not a good approach, where should validation of this event take place?

A: 

Why not, it looks OK to me. The most convenient way of accessing request inside Form, that I know, is embedding it (i.e. Form) inside a function:

    def formX(request):
        class FormX(forms.Form):
            def clean(self):
                if not request.session.get('file_downloaded', False):
                    raise ValidationError('File not downloaded!')
        return FormX

(Note that regarding clean(), this is pseudocode - I was writing out of my head and I probably don't remember details of form cleaning)

Then in view you just write:

    def my_view(request):
        form = formX(request)(...)
Tomasz Zielinski
Thanks. I think I have two options for validation. Either extend the 'clean' function of the Form Class, which will need to access the request.session data, or check for the request.session data in the View and raise a ValidationError on the form. I'd like to keep all the validation in one place (in the Form Class), which is why I'm not using other methods such as JavaScript.
Rik Wade
+1  A: 

You could override the __init__ method for your form so that it takes request as an argument.

class MyForm(forms.Form):
    def __init__(self, request, *args, **kwargs)
        self.request = request
        super(MyForm, self).__init__(*args, **kwargs)

    def clean(self):
        if not self.request.session.get('file_downloaded', False):
            raise ValidationError('File not downloaded!)

def my_view(request):
    form = MyForm(request, data=request.POST)

This keeps all the validation logic in the form.

Alasdair