retegi
August 22, 2021, 10:32am
1
Hi! I need to pass a url argument as a form initial value:
How can i do that? Y need to get the argument in view but i can’t.
Error:
Thanks!
urls:
path('add_imageWithInstallationId/<int:id>/',
views.ImageWithInstallationIdAddView.as_view(),
name='add_imageWithInstallationId'
),
views:
def getId(request, *args, **kwargs):
installationId = request.GET.get(id)
return installationId
class ImageWithInstallationIdAddView(LoginRequiredMixin, CreateView):
template_name = "installation/add_image.html"
model = ImageInstallation
form_class = AddImageForm(initial={'image_imageInstallation':getId})
success_url = '/installation/'
forms:
class AddImageForm(forms.ModelForm):
class Meta:
model = ImageInstallation
fields = ('__all__')
def __init__(self, *args, **kwargs):
super(AddImageForm, self).__init__(*args, **kwargs)
self.fields['installation'].widget.attrs.update({'class': 'form-control'})
self.fields['installation'].label="Instalación"
self.fields['image_imageInstallation'].widget.attrs.update({'class': 'form-control'})
self.fields['image_imageInstallation'].label="Archivo de imagen"
The issue you’re facing is here:
The form_class
attribute is looking for a class, not an instance of a class.
What you’re looking to do is change an individual instance of that class, not the class itself.
Instead of overriding the form_class
attribute, you want to override the get_form()
method to create the instance of the form desired.
retegi
August 22, 2021, 8:23pm
3
Thanks KenWhitesell. I am not sure if you say that:
View:
class ImageWithInstallationIdAddView(LoginRequiredMixin, CreateView):
template_name = "installation/add_image.html"
model = ImageInstallation
form_class = AddImageForm
success_url = '/installation/'
login_url = reverse_lazy('users_app:user-login')
def get_form_kwargs(self, *args, **kwargs):
kwargs = super(ImageWithInstallationIdAddView, self).get_form_kwargs(*args, **kwargs)
print(kwargs)
kwargs['id'] = self.kwargs['id']
return kwargs
When i print kwargs i can see that:
{'initial': {}, 'prefix': None, 'instance': None}
Not get_form_kwargs
, get_form
.
The get_form
function returns the form for the CreateView class.
The default implementation returns an instance of the form_class
. Instead of that, you want to return the instance of form_class
, but with whatever fields you want initialized set to the desired values.
Two resources I recommend for understanding the Generic Class-Based Views is the Classy Class-Based View web site and the CBV Diagrams site. In particular, the classy class-based view site makes it easy to follow the chain of function calls.
retegi
August 22, 2021, 8:53pm
5
Mmm Ok, but i need to use the url argument as initial value. Thatś posible with get_form() ? I am trying that… ; )
Urls:
path('add_imageWithInstallationId/<int:id>/',
views.ImageWithInstallationIdAddView.as_view(),
name='add_imageWithInstallationId'
),
Views:
class ImageWithInstallationIdAddView(LoginRequiredMixin, CreateView):
template_name = "installation/add_image.html"
model = ImageInstallation
form = get_form
form['image_imageInstallation'] = self.get_form_kwargs('id')
form_class = form
login_url = reverse_lazy('users_app:user-login')
def get_form(self, form_class=None):
if form_class is None:
form_class = self.get_form_class()
return form_class(**self.get_form_kwargs())
Ok, let’s look at this from another direction.
First:
You were more correct with your earlier version
This is all you need at the class level.
Now, much earlier, you had:
This is essentially what you want to return from get_form
So, you want to replace that generic **self.get_form_kwargs
with whatever parameters you need to pass to the constructor.