I develop a Django project with inlineformset nested using FormView.
I first develop my form using CreateView/UpdateView and it works but when I use FormView I got an error
'UtilisateurUpdateView' object has no attribute 'object'
Why I can get access 'object' when I use UpdateView but not with FormView ?
I have read that it could come from override method but here doesn't seems to be the case ?
forms.py
NAME = Thesaurus.options_list(2,'fr')
ACCESS = Thesaurus.options_list(3,'fr')
ApplicationFormset = inlineformset_factory(
UtilisateurProjet, Application, #Utilisateur, Application,
fields=('app_app_nom','app_dro'),
widgets={
'app_app_nom': forms.Select(choices=NAME),
'app_dro': forms.Select(choices=ACCESS)
},
extra=3,
can_delete=True,
)
class UtilisateurProjetUpdateForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
self.request = kwargs.pop("request")
super(UtilisateurProjetUpdateForm, self).__init__(*args, **kwargs)
self.fields["pro_ide"] = forms.ModelChoiceField(queryset = PROJETS, label = "Nom projet", widget = forms.HiddenInput(), initial = Projet.objects.get(pro_ide=self.request['projet']))
self.fields["uti_ide"] = forms.ModelChoiceField(queryset = UTILISATEURS, label = "Nom, prénom de l'utilisateur", widget = forms.Select, initial = Utilisateur.objects.get(uti_ide=self.request['utilisateur']))
class Meta:
model = UtilisateurProjet
fields = ('pro_ide','uti_ide',)
views.py
class UtilisateurUpdateView(FormView):
template_name = 'project/utilisateurprojet_form.html'
form_class = UtilisateurProjetUpdateForm
def get_form_kwargs(self):
kwargs = super(UtilisateurUpdateView, self).get_form_kwargs()
kwargs['request'] = dict(utilisateur = self.kwargs['pk'], projet = self.kwargs['projet'])
# kwargs['request'] = self.request
# print('projet',self.kwargs['projet'])
# print('utilisateur',self.kwargs['pk'])
return kwargs
def get_context_data(self, **kwargs):
data = super(UtilisateurUpdateView,self).get_context_data(**kwargs)
# print('projet',self.kwargs['projet'])
# print('utilisateur',self.kwargs['pk'])
instance = UtilisateurProjet.objects.get(pro_ide=self.kwargs['projet'],uti_ide=self.kwargs['pk'])
data['projet'] = Projet.objects.get(pro_ide=self.kwargs['projet'])
data['utilisateur_app'] = Utilisateur.objects.get(uti_ide=self.kwargs['pk'])
if self.request.POST:
data["utilisateur"] = self.request.user.username
data["user_profil"] = self.request.session.get('user_profil')
data["application"] = ApplicationFormset(self.request.POST, instance=instance)
else:
data["application"] = ApplicationFormset(instance=instance)
return data
def form_valid(self, form):
# Setting commit to False will return the object without saving it to the Database.
self.object = form.save(commit=False)
context = self.get_context_data()
application = context["application"]
user_profil = context["user_profil"]
if user_profil == 'Investigateur':
self.object.uti_val = 0 # demande modifiée par investigateur -> repasse à non validée + envoie de mail
elif user_profil == 'Moniteur':
self.object.uti_val = 1 # demande validée par moniteur -> validée + envoie de mail
self.object.uti_val_dat = timezone.now()
else:
self.object.uti_val = 0
# After doing our own changes to the object, we can save it.
self.object.save()
if application.is_valid():
# Not sure what is happening here, but this statement does nothing by itself.
# form.instance = self.object
application.save()
return super().form_valid(form)
def get_success_url(self):
return reverse("project:index")
FormView and DetailView are different classes from different packages: django.views.generic.edit.FormView
and django.views.generic.detail.DetailView
respectively.
From the docs of DetailView:
While this view is executing, self.object will contain the object that the view is operating upon.
FormView doesn't have an object property, because it doesn't necessarily work with an object.
However, since you're using ModelForms, you should be able to access the Form's object after calling form.save():
def form_valid(self, form):
# Setting commit to False will return the object without saving it to the Database.
self.object = form.save(commit=False)
context = self.get_context_data()
application = context["application"]
user_profil = context["user_profil"]
self.object.uti_val = 1
self.object.uti_val_dat = timezone.now()
else:
self.object.uti_val = 0
# After doing our own changes to the object, we can save it.
self.object.save()
if application.is_valid():
# Not sure what is happening here, but this statement does nothing by itself.
form.instance = self.object
application.save()
return super().form_valid(form)