Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django Form validation including the use of session data

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?

like image 941
Rik Wade Avatar asked Dec 10 '22 13:12

Rik Wade


2 Answers

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.

like image 195
Alasdair Avatar answered Feb 02 '23 16:02

Alasdair


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)(...)
like image 25
Tomasz Zieliński Avatar answered Feb 02 '23 16:02

Tomasz Zieliński