Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

django- why after redirecting, the form display "None"

I have a form, after entering the information, based on infomation it filters the database and do some calculation and finally displays the result to a redirected url.

I can indeed redirect to another url and displays the result successfully. But the issue is in the form it cannot display any data submitted by user, just show nothing for every field and the result is not based on fitered queryset. Let's say the sum, it just sum up all the columns in the database, without using the filtered result.

I suspect that the queryset doesn't pass the filtered result to def get_context_data, therefore the queryset in get_context_data doesn't work.

Really thank you a lot if you solve my doubt.

(I made a EDIT version based on suggestion to combine 2 classes, hope someone can correct this EDIT version,thanks)

enter image description here

urls.py

url(r'^result_list/$',ResultView.as_view(),name='result'),
url(r'^input/$',InputFormView.as_view(),name='input'),

views.py

class InputFormView(request):
#class InputFormView(FormView):
    template_name = 'inputform.html'
    form_class = InputForm

    response = HttpResponse( 'result' )
    request_form_data = request.POST #you need to sanitize/clear this data
    response.set_cookie('form_data', request_form_data)

#redirect to result page with submitted form information

    def get_success_url(self):
        return ''.join(
        [
            reverse('result'),
            '?company=',self.request.POST.get('company'),  <--do I need to change "POST" into "USER"?
            '&region=',self.request.POST.get('region')
        ]
        )

#class ResultView(ListView):
class ResultView(request):
    context_object_name = 'result_list'
    template_name = 'result_list.html'
    model = Result

    def get_context_data(self, **kwargs):
        context = super(ResultView, self).get_context_data(**kwargs)
        context["sales"] = self.get_queryset().aggregate(Sum('sales'))
        context["company"] = self.request.POST.get("company")
        context["region"] = self.request.POST.get("region")

        return context

    def get_queryset(self):
        if self.request.method == 'POST': 
            form = InputForm(self.request.POST)
            if form.is_valid():
                company = form.cleaned_data['company']
                region = form.cleaned_data['region']

                queryset=Result.objects.filter(region=region)
                return queryset
        return Result.objects.all()

    if request.COOKIES.has_key('form_data'):
        value = request.COOKIES['form_data'] #this data also should be sanitized

html

<div class="basicinfo">         <!--Entry Form information submitted by user-->
    <table border="1" cellpadding="1">
    <tr>
        <td align="left">Company</td>
        <td>{{ company }}</td>
    </tr>
    <tr>
        <td align="left">Region</td>
        <td>{{ region }}</td>
    </tr>
  </table>
</div>     

<!--Showing the filtered result in database-->  
<td><table border="0" cellspacing="10" cellpadding="10">
<tr><b>Sales</b></tr>
<td bgcolor="#F0F0F0"> {{ sales.sales__sum }}</td>

</tr>
<tr><b>Employee</b></tr>
<tr>
<td bgcolor="#F0F0F0"> {{ employee.employee__sum }}</td>

</table>

EDIT- combining the 2 class views

import urllib

#@csrf_exempt

class ResultView(ListView):
    context_object_name = 'result_list'
    template_name = 'result_list.html'
    model = Result

    def get_queryset(self):
        form = InputForm(self.request.GET)
        if form.is_valid():
            company = form.cleaned_data['company']
            region = form.cleaned_data['region']         
            queryset=Result.objects.filter(region=region)
            return queryset
        return Result.objects.all()

    def get_success_url(self):
        params = {
            'company': self.request.POST.get('company'),
            'region': self.request.POST.get('region')
        }
        return ''.join([reverse('result'), '?', urllib.urlencode(params.items())])

    def get_context_data(self,**kwargs):
            context = super(ResultView, self).get_context_data(**kwargs)
            context["sales"] = self.get_queryset().aggregate(Sum('sales'))         
            context["company"] = self.request.GET.get("company")
            context["region"] = self.request.GET.get("region")       
            return context

**EDIT- urls.py **

url(r'^result_list/$',ResultView.as_view(),name='result'),----for the result page
url(r'^input/$',result.views.get_success_url,name='input') -----for the form, I am not sure if this line correct or not?
like image 374
Héléna Avatar asked Sep 27 '22 10:09

Héléna


1 Answers

Your code should work if you change your get_queryset method to:

def get_queryset(self):
    # You are sending GET params here, not POST
    form = InputForm(self.request.GET)
    if form.is_valid():
        company = form.cleaned_data['company']
        region = form.cleaned_data['region']

        queryset=Result.objects.filter(region=region)
        return queryset
    return Result.objects.all()

and your get_context_data method to:

def get_context_data(self, **kwargs):
    context = super(ResultView, self).get_context_data(**kwargs)
    context["sales"] = self.get_queryset().aggregate(Sum('sales'))
    # Your variables are in GET, not POST
    context["company"] = self.request.GET.get("company")
    context["region"] = self.request.GET.get("region")
    return context

That said, your code could do with some refactoring. Do you really need the FormView that accepts a POST request? You could instead have a form that submits directly via GET to your result view.

With your current approach you are actually processing the form twice - once in each of your views.

Edit: also, they way you are generating your redirect url isn't safe. You should so something like this instead:

import urllib
def get_success_url(self):
    params = {
        'company': self.request.POST.get('company'),
        'region': self.request.POST.get('region')
    }

    return ''.join([reverse('result'), '?', urllib.urlencode(params.items())])
like image 190
solarissmoke Avatar answered Sep 30 '22 05:09

solarissmoke