Home > database >  Form Create View and 3 hierarchical models - Limit Choices for ForeignKey
Form Create View and 3 hierarchical models - Limit Choices for ForeignKey

Time:03-30

I am trying to create an 'Expense Tracker'. I have query regarding create view and Models with 3 hierarchical levels. For eg:-

class ExpenseYear(models.Model):
    year = models.PositiveIntegerField()
 
class ExpenseMonth(models.Model):
    month = models.CharField(max_length = 14,blank = False)
    month_year = models.ForeignKey(ExpenseYear,related_name = 'month',on_delete=models.CASCADE)
 
class Expenses(models.Model):
    expense = models.PositiveIntegerField()
    expense_month = models.ForeignKey(ExpenseMonth,related_name = 'expense', on_delete=models.CASCADE)

Now, while creating CreateView for 'Expenses' model, i am facing an issue. I want to display only the months in that particular year (in 'expense_month' foreignkey), but all months of all the years are being displayed in the 'expense_month' foreignkey.

This is what i am getting - CreateView

I searched stackoverflow about limiting foreignkey choices and ended up finally with another code, but now no months are displayed in the foreign key

Forms.py

#forms.py
class ExpensesForm(forms.ModelForm):
    class Meta():
        model = Expenses
        fields = ('expenses','expense_month')
    def __init__(self, *args, **kwargs):
        month_year_id = kwargs.pop('month_year_id')
        super(ExpensesForm, self).__init__(*args, **kwargs)
        self.fields['expense_month'].queryset = ExpenseMonth.objects.filter(month_year_id=month_year_id)

Views.py

#views.py
class ExpensesCreateView(CreateView):
    model = models.Expenses
    form_class = ExpensesForm
 
    def get_form_kwargs(self):
        kwargs = super(ExpensesCreateView, self).get_form_kwargs()
        kwargs.update({'month_year_id': self.kwargs.get('month_year_id')})
        return kwargs

However, as i said no months are displayed if i write this code.

This is what i am getting if i write the above code - CreateView

How to limit foreignkey choices? i checked Django Documentation, but i could find any particular answer for this. Can please Help me out. I have searched many questions related to this in stackoverflow and other websites. Can you please answer this question in this context itself (pls don't reply with a genenral code as, i am new to django and find it difficult to understand general answers)

Thanks in Advance !

Urls.py

#urls.py
urlpatterns = [         
path('year/<int:pk>/<int:pk2>/create_expense/',views.ExpensesCreateView.as_view(),name ='create_expense'),
]

CodePudding user response:

The issue is with the get_form_kwargs in your view:

def get_form_kwargs(self):
    kwargs = super(ExpensesCreateView, self).get_form_kwargs()
    kwargs.update({'month_year_id': self.kwargs.get('month_year_id')})
    return kwargs

If you print(self.kwargs.get('month_year_id')) it will probably be None.

self.kwargs are the URL keyword arguments you provide to the view, in your case your url is providing two arguments pk and pk2 here:

path('year/<int:pk>/<int:pk2>/create_expense/',views.ExpensesCreateView.as_view(),name ='create_expense'),

So you have two choices, either rename the argument in the path so it is <int:month_year_id> (I'm not sure whether you should rename pk or pk2 just from your code snippets).

or

In get_form_kwargs get either pk or pk2 from self.kwargs instead of month_year_id, for example:

kwargs.update({'month_year_id': self.kwargs.get('pk2')})
  • Related