Search code examples
djangodjango-sessions

Django - How to call a session in a module different than views.py?


I'd like to call a session that was set at views.py in my forms.py. Is that possible?

I tried to do that but I faced some issues with 'request'.

forms.py

from django import forms


class NormalForm(forms.Form):

   options = [
       ('TEST','TEST'),
   ]

   options_normalform = forms.ChoiceField(required=False, choices=options,widget=forms.RadioSelect(attrs={'class':'example_form'}), label='')

class ExampleForm(forms.Form):

   def __init__(self, *args, **kwargs):
       self.request = kwargs.pop('request', None)
       super(ExampleForm, self).__init__(*args, **kwargs)

       self.option_a = self.request.session['my_session']

    self.options_list = [
        ('a', self.option_a),
        ('b', 'b'),
        ('c', 'c'),
    ]

    self.options_form = forms.ChoiceField(required=False, choices=self.options_list,widget=forms.RadioSelect(attrs={'class':'example_form'}), label='')

views.py

from django.shortcuts import render
from .forms import ExampleForm, NormalForm

def example(request):
    option_a = '123'
    request.session['my_session'] = option_a

    normalform = NormalForm
    form = ExampleForm(request=request)
    context = {
        'form': form,
        'normalform': normalform,
    }

    return render(request, 'index.html', context)

template

<!DOCTYPE html>
<html>
    <head>
        <title>My App</title>
    </head>
    <body>       
        <!-- Header -->
        <header>
            <h1 id="logo">MY APP</h1>
        </header>


        <!-- Options form -->
        <div id="forms">
            <form id="normalform" method="post">
                {% csrf_token %}
                {{normalform}}
            </form>
            <form id="form" method="post">
                {% csrf_token %}
                {{form}}
            </form>
        </div>
        <!-- End of options form -->


        <!-- Footer -->
        <footer id="main-footer">
            <p>Copyright &copy; 2017-2017 | my APP </p>
        </footer>
        <!-- End of Footer -->
    </body>
</html>

I don't try to import the value instead of make a session, because this value will be created inside the same view that I call the form. Therefore I would get a circular error.

I hope that to store this value in a session, and then send it to my form will not raise this circular issue.

P.S. I'm a beginner on programming.

[EDITED] It was included the template and a new form to test if the view is able to find the template.


Solution

  • First of all, we rewrite the form class so it receives the request object in the constructor and stores it in a field. All the other properties will be initialized after that:

    class ExampleForm(forms.Form):
    
        def __init__(self, *args, **kwargs):
            self.request = kwargs.pop('request', None)
            super(ExampleForm, self).__init__(*args, **kwargs)
    
            self.option_a = self.request.session['my_session']
    
            self.options_list = [
                ('a', self.option_a),
                ('b', 'b'),
                ('c', 'c'),
            ]
    
            self.fields['options_form'] = forms.ChoiceField(required=False, choices=self.options_list, widget=forms.RadioSelect(attrs={'class':'example_form'}), label='')
    

    Now, in your view you have to instantiate a form object and pass the request in the constructor call. Note that the context should receive a form instance and not the class or the form will not be rendered:

    def example(request):
        option_a = '123'
        request.session['my_session'] = option_a
        form = ExampleForm(request=request)
        context = {
            'form': form,
        }
        return render(request, 'example/index.html', context)