I am trying to create a multi-step form in django2.2. Apparently, the native FormWizard was deprecated in previous django versions so the only solution I have ran into is django-formtools. I have two Models that provide the FormWizard with the required fields. I have been able to make a dictionary of user input from the forms successfully. I intend to save this data to one of the models. However, the model requires a user.id field since it is a Foreign key to a CustomUser object and cannot thereby be null. I believe there is a way to add this user.id to the data dictionary then save the entire dict as an instance in my target model. This is where I have been struggling.
I have tried invoking user=request.user but an error occurs saying that 'request is not defined' since this is a class-based view(I guess that's why).
class Category(models.Model):
name= models.CharField(blank = True, max_length=500)
def __str__(self):
return self.name
class ModelsAd(models.Model):
title = models.CharField(max_length=500)
category = models.ForeignKey(Category,default=1, on_delete=models.CASCADE)
location = models.ForeignKey(Location,default=1, blank=True, on_delete=models.CASCADE)
description = models.CharField(max_length=1000)
price = models.PositiveIntegerField(default=1000)
user = models.ForeignKey(CustomUser, on_delete=models.CASCADE)
created_at = models.DateTimeField(default=timezone.now)
def __str__(self):
return self.title
all_categories = Category.objects.all()
class CategoryChoiceForm(forms.Form):
category = forms.ModelChoiceField(queryset = all_categories, to_field_name = "name", empty_label=None)
class ModelsAdForm(ModelForm):
class Meta:
model = ModelsAd
fields = ('title','location', 'description', 'price')
from formtools.wizard.views import SessionWizardView
class FormWizardView(SessionWizardView):
template_name = "post_ad.html"
form_list = [CategoryChoiceForm, ModelsAdForm]
def done(self, form_list, **kwargs):
form_data = [form.cleaned_data for form in form_list]
data_dict={}
for item in form_data:
data_dict.update(item)
add_data=ModelsAd(**data_dict)
# add_data.save()
test=ModelsAd.objects.all()
print(test)
return render(self.request, 'index.html',locals())
I need to pass user.id to the FormWizardView so that I can append it to the data_dict so that I can successfully save the dict as an instance in my db. So far, I am running in circles. Any help will be highly appreciated. Someone please at least point me in the right direction
I have to stop answering my own questions but what the heck.. I figured out what the problem was... when I tried invoking request.user
in the FormWizardView
, it was throwing a 'request' not defined
error, so I tried to give the class a request object via self
like, user=self.request.user
. However, this only produced a user instance belonging to the ModelsAdForm and not to the CustomUser model, as was required by the db... I can't believe it was as simple as calling an instance of CustomUser with the same value as the ModelsAdForm user... what I mean is user=CustomUser.objects.get(email=self.request.user)
I therefore amended my FormWizardView to look like this:
class FormWizardView(SessionWizardView):
template_name = "post_ad.html"
form_list = [CategoryChoiceForm, ModelsAdForm]
def done(self, form_list, **kwargs):
form_data = [form.cleaned_data for form in form_list]
data_dict={}
for item in form_data:
data_dict.update(item)
data_dict.update({'user':CustomUser.objects.get(email=self.request.user)})
add_data=ModelsAd(**data_dict)
add_data.save()
return render(self.request, 'index.html',locals())
and boom! a form that takes fields from three models and saves input data to one model... Now to make it more dynamic.. refactor hour :)