Search code examples
pythondjangodjango-formsdjango-class-based-viewsformview

exposing data with django form get request


I'm building a small form on which I'm displaying some data in the table, addition to that I have two dropdown, with which you can select current data or year for the data you want to see in the table.

My question is how can I populate dropdown with current month and year, using django form get request, I'm little confused how to process this in my view, note that I'm using CBV FormView.

I've tried something like this form.py

from django import forms

import datetime


class StatisticsForm(forms.Form):
    """TODO: Simple form with two field, one for year
    other for month, so user can list Statistics for
    current month and year.
    :returns: TODO"""
    invoice_month = forms.CharField(label="month", max_length=225)
    invoice_year = forms.CharField(label="year", max_length=225)

    def get_initial(self):
        initial = super(StatisticsForm, self).get_initial()
        initial["invoice_month"] = datetime.date.today()
        initial["invoice_year"] = datetime.date.today()
        return initial

and in my view I'm displaying table and I need to do the rest to.

view.py

from django.views.generic.edit import FormView

from .models import Rate
from statistics.forms import StatisticsForm
from statistics.services import StatisticsCalculation


class StatisticsView(FormView):
    """
    TODO: We need to handle
        Total Invoice - no matter how old, basically all of them
        Current month Total Invoice
    """
    template_name = "statistics/invoice_statistics.html"
    form_class = StatisticsForm

    def get_context_data(self, **kwargs):
        context = super(StatisticsView, self).get_context_data(**kwargs)

        def_currency = Rate.EUR

        context["can_view"] = self.request.user.is_superuser
        context["currency"] = def_currency
        context["supplier_statistic"] = StatisticsCalculation.statistic_calculation(default_currency)
        return context

Solution

  • When the FormView creates the actual form object, it gets the arguments to pass to the form from get_form_kwargs():

    def get_form_kwargs(self):
        """
        Returns the keyword arguments for instantiating the form.
        """
        kwargs = {
            'initial': self.get_initial(),
            'prefix': self.get_prefix(),
        }
        if self.request.method in ('POST', 'PUT'):
            kwargs.update({
                'data': self.request.POST,
                'files': self.request.FILES,
            })
     return kwargs
    

    Notice how it's calling the get_initial() on itself (the view) rather than the form. It can't call it on the form because it's not initialized yet. Move your method into the view and you're good to go.

    As a sidenote, use django.utils.timezone.now() as opposed to stdlib datetime.date.today() since it respects your django timezone settings and you may occasionally see some off-by-one quirks otherwise.

    Edit: You should also update your form to use ChoiceField, and set the defaults with timezone.now().month and timezone.now().year.

    Happy coding.