How to pass URL Vars to from InlineFormSetFactory (views.py) to ModelForms (forms.py)
Maximost opened this issue · 6 comments
This is probably an easy question but I am wondering how to pass URL variables from InlineFormSetFactory classes in views.py to the respective ModelForm in forms.py. The specific scenario I'm having trouble with is in relation to UpdateWithInlinesView. I have tried the various kwarg.get/kwarg.pop approaches but these lead to key errors. Is it not possible to propagate url vars to the inline formsets in this way?
Thank you for any insight you might have.
Hi! self.kwargs
should work just fine. In fact ModelFormWithInlinesMixin.construct_inlines()
already passes them directly into the constructor of each InlineFormSetFactory
subclass defined in the inlines
attribute of the view. Can you post the code which isn't working?
E.g.
class MyFactory(InlineFormSetFactory):
def some_method(self):
foo = self.kwargs.get("my_url_variable")
...
class MyView(UpdateWithInlinesView):
inlines = [MyFactory]
...
Thank you for the quick response. Basically, I am trying to filter the option select user list based on a combined list of user ids. I have this working fine in all my add and edit views. It is the UpdateWithInlinesView that does not seem to be working. I suspect there is something simple that I'm missing.
The code I'm wrestling with is below:
# VIEWS.PY
# Inline Form Constructor
class task_edit_inline(InlineFormSetFactory):
form_class = taskEditForm
model = Tasks
factory_kwargs = {'extra': 0, 'max_num': None, 'can_order': False, 'can_delete': True}
def get_formset_kwargs(self, **kwargs):
kwargs = super(task_edit_inline, self).get_formset_kwargs(**kwargs)
# Create user list for option select filtering in forms.py
project_id = self.object.id
pp = Project.objects.filter(id = project_id).values_list('parent_project_id', flat=True)[0]
users_1 = ParentTeam.objects.filter(parent = pp).values_list('user', flat=True)
users_2 = ProjectTeam.objects.filter(project = project_id).values_list('user', flat=True)
kwargs["my_users"] = list(chain(users_1, users_2))
# Order tasks
kwargs["queryset"] = self.object.tasks_set.order_by("task_order", "task_due")
return kwargs`
# Grid editing view
class task_grid_edit_if_view(SuccessMessageMixin, UpdateWithInlinesView):
model = Project
template_name = 'otis/edit_task_grid-if.html'
form_class = TaskGridForm
inlines = [task_edit_inline]
success_message = "Tasks updated"
def get_context_data(self, **kwargs):
context = super(task_grid_edit_if_view, self).get_context_data(**kwargs)
return context
# FORMS.PY
# Edit Form
class taskEditForm(ModelForm):
def __init__(self, *args, **kwargs):
my_users = kwargs.pop('my_users')
self.base_fields['user'].queryset = User.objects.filter(id__in=my_users).order_by('first_name')
super(taskEditForm, self).__init__(*args, **kwargs)
self.label_suffix = ""
class Meta:
model = Tasks
fields = ('task_order','user','task_type','task_note','task_due','task_effort','is_complete')
widgets = {
'task_order': NumberInput(attrs={'size': '2'}),
'task_due': NumberInput(attrs={'type': 'date'}),
'task_note': Textarea(attrs={'cols': 20, 'rows': 5, 'placeholder': 'Task details...'}),
}
Looks like you're passing my_users
to the formset constructor but you want to process it in the form constructor. I think you're looking for the below?
https://django-extra-views.readthedocs.io/en/latest/pages/formset-customization.html?highlight=form_kwargs#passing-arguments-to-the-form-constructor
Thank you so much for your help! I clearly did not understand how to pass vars to the form constructor. So just to clarify for my own sanity (and maybe others who stumble on this), I made the following modifications to the get_formset_kwargs function in the inlineformset constructor:
def get_formset_kwargs(self, **kwargs):
kwargs = super(task_edit_inline, self).get_formset_kwargs(**kwargs)
# Create user list for option select filtering in forms.py
project_id = self.object.id
pp = Project.objects.filter(id = project_id).values_list('parent_project_id', flat=True)[0]
users_1 = ParentTeam.objects.filter(parent = pp).values_list('user', flat=True)
users_2 = ProjectTeam.objects.filter(project = project_id).values_list('user', flat=True)
user_list = list(chain(users_1, users_2))
# change here --- \/
kwargs['form_kwargs'] = ({'my_users': user_list})
# Order tasks
kwargs["queryset"] = self.object.tasks_set.order_by("task_order", "task_due")
return kwargs
Everything is working as expected.
Great. You're welcome :-)