0

So basic task is: add the template name and text to the choices in the ChoiceField with Selector widget to the form using the data from dB linked to the authenticated User only. Template is a model linked to user as a ForeignKey.

I'd like to access the request data(user) via the Form class linked to the connected view as django.views.generic.View class.

I've checked similar questions here: Curious about get_form_kwargs in FormView

and here: Sending request.user object to ModelForm from class based generic view in Django

and here: Django: Accessing request in forms.py clean function

However they don't touch base with non-FormView classes. And as it's fairly old solutions, I was curious if there's more likely approach to reach request from forms.Form class.

Here's my code:

views.py

class InformFill(View):
form_class = InformForm
temlate_name = 'distrib_db/inform_fill.html'

def get(self, request):
    if request.user.is_authenticated():
        form = self.form_class(None)
        return render(request, self.temlate_name, context={'form': form})
    else:
        return redirect('distrib_db:login')

def post(self, request):
    if request.user.is_authenticated():
        form = self.form_class(request.POST)
        if form.is_valid():
            inform = Inform(flt_numbr=form.cleaned_data['flight_number'], date=form.cleaned_data['date'],
                            template=form.cleaned_data['text'], user=request.user)
            inform.save()
            date = form.cleaned_data['date']
            flt_numbr = form.cleaned_data['flight_number']
            try:
                emails, contacts = get_mail_cnt(date, flt_numbr)
                # inform = get_object_or_404(Inform, pk=request['pk'])
                paxdata = PaxData(inform=inform, emails=' '.join(emails), contacts=' '.join(contacts))
                paxdata.save()
                return redirect('/inform/{0}/'.format(inform.pk))
            # 'distrib_db:detail', context={'pk': inform.id}
            except Exception as e:
                return render(request, 'distrib_db/sample.html',
                              context={'date': date, 'flight_number': flt_numbr, 'error': e})

                # return render(request, 'distrib_db/sample.html', context={'date': date, 'flt_numbr': flt_numbr})

        return render(request, self.temlate_name, context={'form': form})
    else:
        return redirect('distrib_db:login')

forms.py

class InformForm(forms.Form):
flight_number = forms.CharField(5, widget=forms.TextInput())
date = forms.DateField(widget=forms.DateInput(attrs={'class': 'datepicker'}))
template = forms.ChoiceField(choices=templates, widget=forms.Select(attrs={'id': 'select_box',
                                                                          'onchange': 'javascript:changer();'}))
text = forms.CharField(widget=forms.Textarea(attrs={'id': 'txt_box', 'class': 'latin',
                                                    'maxlength': "160", 'onchange': 'javascript:validateTextArea();'}))

Generally speaking i'd like to achieve smth like this:

`class InformForm(forms.Form):
    def get_template_choices(self):
        templates = self.request.user.template_set.all()
        choices = []
        for t in templates: 
            choices.append((t.text, t.name))
        return choices

    flight_number = forms.CharField(5, widget=forms.TextInput())
    date = forms.DateField(widget=forms.DateInput(attrs={'class':                                                    
                                                      'datepicker'}))
    template = forms.ChoiceField(choices=get_template_choices(), 
                                         widget=forms.Select(attrs=
                                        {'id': 'select_box',

                                         'onchange': 'javascript:changer();'}))
    text = forms.CharField(widget=forms.Textarea(attrs={'id': 'txt_box', 
                                                    'class': 'latin',
                                                    'maxlength': "160", 
                              'onchange': 'javascript:validateTextArea();'}))`

I'd appreciate any approach, mb I lack knowledge and asking newbie questions, sorry about it.

I just wanna get the python-way solution rather then build some js/jinja walk-arounds.

Thank you for your time!

#

After @Danielius comments, I've made some adjustments:

`class InformForm(forms.Form):
    def __init__(self, user=None, *args, **kwargs):
        if user:
            self.fields['template'] = forms.ChoiceField(choices=tuple([(template.text, template.name) for template in user.template_set.all()]),
                                                        widget=forms.Select(attrs={'id': 'select_box', 'onchange': 'javascript:changer();'}))

    flight_number = forms.CharField(5, widget=forms.TextInput())
    date = forms.DateField(widget=forms.DateInput(attrs={'class': 'datepicker'}))
    # template = forms.ChoiceField(choices=templates, widget=forms.Select(attrs={'id': 'select_box',
    #                                                                           'onchange': 'javascript:changer();'}))
    text = forms.CharField(widget=forms.Textarea(attrs={'id': 'txt_box', 'class': 'latin',
                                                        'maxlength': "160", 'onchange': 'javascript:validateTextArea();'}))`

Got an error AttributeError: 'InformForm' object has no attribute 'fields'

Community
  • 1
  • 1
Aleks_Saint
  • 67
  • 1
  • 2
  • 12

1 Answers1

1

You can pass request to your form by changing your __init__ method like this :

class InformForm(forms.Form):
...
   def __init__(self, user=None,*args, **kwargs):
        super(InformForm, self).__init__(**kwargs)
        if user:  
            self.fields['somefield'] = forms.ChoiceField()                  
            self.fields['somefield'].widget = forms.Select()
            self.fields['somefield'].queryset = Someobject.objects.filter(User=user)
...

If the User is linked to other object in db by Foreign key, then you will get all the values of other object as select items.

Also , when creating form you could pass user like this :

form= InformForm(user=request.user,data=request.POST)
Danielius
  • 165
  • 11
  • got an error: 'InformForm' object has no attribute 'fields', are you sure that it works this way, or mb I'm not doing it right... – Aleks_Saint May 13 '17 at 11:16
  • probably that's cos I'm using Form, not ModelForm for example, there's no fields pre-defined. – Aleks_Saint May 13 '17 at 11:21
  • It's not because its not ModelForm, it was my mistake i forgot to add super method in __init__ before the clause, now i edited it ,check it ,maybe it will help – Danielius May 13 '17 at 11:47
  • as I've edited the questions itself - you can find the code. I've added super, it throws no error, however, the field is not populated at all. I mean there's no such field. does it need to be saved or smth in order for it to stay? – Aleks_Saint May 13 '17 at 11:55
  • I see , you commented your # template field, so yea, basicly we were just setting parameters for it, try now i edited it a bit - you should see the ChoiseField now, and the values should be okay – Danielius May 13 '17 at 12:13
  • Hello Danielius, tried the way you told me, nothing appeared, so i removed the condition - it doesn't pass the parameter. Mb I should change smth in views.py? – Aleks_Saint May 15 '17 at 06:23
  • Thanks Danielius, it was my mistake not o change def get(request) in views.py ;) – Aleks_Saint May 15 '17 at 11:53