Trying to update two django forms at once - django

I am trying to use an UpdateView in Django to update two forms simultaneously. I have the get method working properly, but when I submit the update, the post method creates a new instance of the forms. How can I grab the forms from the get method and update them without creating a new instance? Everything is redirecting fine and I am getting no errors.
class MotionStudyInstanceUpdateView(UpdateView):
model = MotionStudyInstance
fields = ['height', 'weight', 'skin_type_score', 'fitzpatrick_skin_type']
template_name = 'data/motionstudyinstance_update.html'
success_url = reverse_lazy('data:motion-studies')
def get_context_data(self, **kwargs):
pass
def get(self, request, **kwargs):
pk = self.kwargs['pk']
item = MotionStudyInstance.objects.get(id=pk)
general_info = item.general_info
form = MotionStudyInstanceForm(
initial={'height': item.height, 'weight': item.weight, 'skin_type_score': item.skin_type_score,
'fitzpatrick_skin_type': item.fitzpatrick_skin_type})
form_two = GeneralInfoForm(initial={'case_report_form_number': general_info.case_report_form_number,
'form_type': general_info.form_type,
'study_start_date': general_info.study_start_date,
'signed_consent': general_info.signed_consent,
'gender': general_info.gender,
'miscellaneous_notes': general_info.miscellaneous_notes,
'adverse_events': general_info.adverse_events})
return render(request, self.template_name, {'form': form, 'foreign_form': form_two})
def post(self, request, **kwargs):
if request.method == 'POST':
form = MotionStudyInstanceForm(request.POST)
foreign_form = GeneralInfoForm(request.POST)
if form.is_valid() and foreign_form.is_valid():
general_info = foreign_form.save()
user_form = form.save(commit=False)
user_form.general_info = general_info
user_form.save()
return redirect('data:motion-studies')
else:
form = MotionStudyInstanceForm()
return render(request, self.template_name, {'form': form})
forms.py
class MotionStudyInstanceForm(forms.ModelForm):
class Meta:
model = MotionStudyInstance
exclude = ('general_info',)
widgets = {
'validation_status': forms.HiddenInput(),
'author': forms.HiddenInput(),
'sibling': forms.HiddenInput()
}
class GeneralInfoForm(forms.ModelForm):
class Meta:
model = GeneralInfo
fields = '__all__'
widgets = {
'form_type': forms.HiddenInput(),
}

Looks like you should be using the instance parameter on the forms.
So you can update it on the post, and display it on the get
something like this:
def post(self, request, **kwargs):
pk = self.kwargs['pk']
item = MotionStudyInstance.objects.get(id=pk)
if request.method == 'POST':
form = MotionStudyInstanceForm(request.POST, instance=item)

Related

How Do I Convert This Function Based View To An UpdateView?

I am trying to convert a function based view to a class based view. I've done it with the CreateView but the UpdateView is giving me grief. It won't take my update. I can get the view to take my update, but it doesn't save it.
Here's my function based view:
def update_task_update_view(request, pk):
task = Task.objects.get(id=pk)
form = TaskForm(request.POST or None, instance=task)
if request.method == "POST":
if form.is_valid():
form.save()
return redirect("MyTasks:task_detail", pk=task.id)
context = {
"form": form,
"task": task
}
return render(request, "partials/task_form.html", context)
And here was my attempt at a Class Based View.
class UpdateTaskUpdateView(LoginRequiredMixin,UpdateView):
model = Task
form_class = TaskForm
template_name = 'partials/task_form.html'
def post(self, request, *args, **kwargs):
form_class = self.get_form_class()
form = self.get_form(form_class)
if form.is_valid():
task = form.save()
task.save()
return redirect("MyTasks:task_detail", pk=task.id)
else:
return render(request, "partials/task_form.html", {
"form":form
})
This function based view is working fine, no issues with it.
Thanks to an assist from FB...Travis Tucker....
I did this instead and it seems to be working fine...
class UpdateTaskUpdateView(LoginRequiredMixin,UpdateView):
model = Task
form_class = TaskForm
template_name = 'partials/task_form.html'
def form_valid(self, form):
form_class = self.get_form_class()
form = self.get_form(form_class)
if form.is_valid():
task = form.save()
task.save()
return redirect("MyTasks:task_detail", pk=task.id)
else:
return render(request, "partials/task_form.html", {
"form":form
})

Get username or user as initial value on forms in django

I would like to get initial value on the following form but i get error : name 'user' is not defined. I don't know how to get user.username.
class InvoiceForm(ModelForm):
date = forms.DateField(widget=DateInput)
company = forms.CharField(initial={"company": user.username})
class Meta:
model = Invoice
fields = "__all__"
and the view to create the invoice is :
class InvoiceCreate(CreateView):
form_class = InvoiceForm
model = Invoice
template_name = "sales/invoice_form.html"
def get_success_url(self, request):
return reverse_lazy('invoice_details', kwargs={'pk' : self.object.pk})
def get(self, request, *args, **kwargs):
self.object = None
form_class = self.get_form_class()
form = self.get_form(form_class)
formset = InvoiceItemFormSet()
products = list(Product.objects.values())
return self.render_to_response(
self.get_context_data(form=form,formset=formset, products=products))
def post(self, request, *args, **kwargs):
self.object = None
form_class = self.get_form_class()
form = self.get_form(form_class)
formset = InvoiceItemFormSet(self.request.POST)
if (form.is_valid() and formset.is_valid()):
return self.form_valid(form, formset)
else:
return self.form_invalid(form, formset)
def form_valid(self, form, formset):
self.object = form.save()
formset.instance = self.object
formset.save()
try:
addmore = self.request.GET["addmore"]
if addmore == "True":
return redirect("update_invoice", pk=self.object.id)
except Exception as e:
pass
return HttpResponseRedirect(self.get_success_url())
def form_invalid(self, form, formset):
return self.render_to_response(self.get_context_data(form=form, formset=formset))
I would like to get initial value on the following form but i get error : name 'user' is not defined. I don't know how to get user.username.
You had that error because there is no user at that point in the class level definition:
company = forms.CharField(initial={"company": user.username})
change to:
company = forms.CharField()
then is views.py add this method to InvoiceCreate class:
def get_initial(self):
return {"company": self.request.user}

create help text for a field dynamically

I have my response form and view like this
class ResponseForm(ModelForm):
class Meta:
model = ResponseModel
exclude = ('author', 'title','submit_count')
# help_texts = {
# 'ans1': user.q1.value,
# }
#login_required
def ResponseFormView(request):
if request.method == "POST":
form = ResponseForm(request.POST)
if form.is_valid():
submission = form.save(commit=False)
submission.author = request.user
submission.save()
return render(request, 'thanks.html', {})
else:
form = ResponseForm()
return render(request, 'response_tem.html', {'form': form})
I want the help text for 'ans1' field to be the value of q1 field of request.user. How do I do it?
You can do it like this:
class ResponseForm(ModelForm):
def __init__(self, *args, **kwargs):
user = kwargs.pop('user', None) # popping user from known arguments
super(ResponseForm, self).__init__(*args, **kwargs)
if user:
self.fields['ans1'].help_text = "Help Text for {}".format(user.username)
class Meta:
model = ResponseModel
exclude = ('author', 'title','submit_count')
#login_required
def ResponseFormView(request):
if request.method == "POST":
form = ResponseForm(request.POST)
if form.is_valid():
submission = form.save(commit=False)
submission.author = request.user
submission.save()
return render(request, 'thanks.html', {})
else:
form = ResponseForm(user=request.user) # passing user as known argument
return render(request, 'response_tem.html', {'form': form})
Here, in the view I am passing the request.user as known argument when I am initiating Form Class's Object (marked with comment). Then in the Form, I am catching the user sent from view and updating the field's help text.

UpdateView gives blank form in django inline formset

MY CreateView worked fine but when I try to update this form data, it gives blank form. No data was shown. Here is my views.py:
#require_authenticated_permission(
'member.add_person')
class PersonCreate( FormsetMixin, CreateView):
template_name = 'member/person_form.html'
model = Person
form_class = MemberForm
formset_class = PersonFormSet
#require_authenticated_permission(
'member.change_person')
class PersonUpdate( FormsetMixin, UpdateView):
template_name = 'member/person_form.html'
model = Person
form_class = MemberForm
formset_class = PersonFormSet
Here is my formset:
class MemberForm(ModelForm):
class Meta:
model = Person
exclude = ('user',)
def __init__(self, *args, **kwargs):
super(MemberForm, self).__init__(*args, **kwargs)
self.fields['name'].widget.attrs['placeholder'] = 'Your full name'
self.fields['tele_land'].label = 'Land phone'
self.fields['tele_cell'].label = 'Cell phone'
self.fields['passing_year'].label = 'Passing year'
self.fields['passing_year'].help_text = 'According to your session year'
def save(self, request, commit=True):
person = super().save(commit=False)
if not person.pk:
person.user = get_user(request)
if commit:
person.save()
self.save_m2m()
return person
class ChildrenForm(ModelForm):
class Meta:
model = Children
fields = '__all__'
PersonFormSet = inlineformset_factory(Person, Children, extra=0, min_num=1, fields=('child_name', 'child_birth_date','blood_group' ))
Url:
url(r'^person/create/$', views.PersonCreate.as_view(), name='person-create'),
url(r'^person/(?P<slug>[\w\-]+)/update/$', views.PersonUpdate.as_view(), name='person-update'),
My formset mixin:
class FormsetMixin(object):
object = None
def get(self, request, *args, **kwargs):
if getattr(self, 'is_update_view', False):
self.object = self.get_object()
form_class = self.get_form_class()
form = self.get_form(form_class)
formset_class = self.get_formset_class()
formset = self.get_formset(formset_class)
return self.render_to_response(self.get_context_data(form=form, formset=formset))
def post(self, request, *args, **kwargs):
if getattr(self, 'is_update_view', False):
self.object = self.get_object()
form_class = self.get_form_class()
form = self.get_form(form_class)
formset_class = self.get_formset_class()
formset = self.get_formset(formset_class)
if form.is_valid() and formset.is_valid():
return self.form_valid(form, formset)
else:
return self.form_invalid(form, formset)
def get_formset_class(self):
return self.formset_class
def get_formset(self, formset_class):
return formset_class(**self.get_formset_kwargs())
def get_formset_kwargs(self):
kwargs = {
'instance': self.object
}
if self.request.method in ('POST', 'PUT'):
kwargs.update({
'data': self.request.POST,
'files': self.request.FILES,
})
return kwargs
def form_valid(self, form, formset):
self.object = form.save(self.request)
formset.instance = self.object
formset.save()
return redirect(self.object.get_absolute_url())
def form_invalid(self, form, formset):
return self.render_to_response(self.get_context_data(form=form, formset=formset))
Why my UpdateView gives blank form?
Proably because getattr(self, 'is_update_view', False) always is false so you're not loading any self.object.
I have for similar situations used ModelFormSetView from django-extra-views. It's easy to use if you already understand Django class based views and will save you a lot of code to write and maintain yourself.
BTW you should implement get_queryset and prefetch the Children.
Use in UpdateView: is_update_view = True. It will be like
class PersonUpdate( FormsetMixin, UpdateView):
template_name = 'member/person_form.html'
model = Person
is_update_view = True
form_class = MemberForm
formset_class = PersonFormSet

Django class based UpdateView with inline formsets

I have a model PSG which has a relation to another model SubPSG. PSGs can have several SubPSGs. I'm using inline formsets to create SubPSGs as I create the PSGs. The CreateView works okay but the UpdateView is not working as expected. The UpdateView is as follows:
class PSGUpdate(GroupRequiredMixin, UpdateView):
model = PSG
form_class = PSGForm
template_name = "management/psg_update_form.html"
success_url = reverse_lazy('dashboard')
group_required = [u"admin", "manager"]
def get_context_data(self, **kwargs):
context = super(PSGUpdate, self).get_context_data(**kwargs)
subpsgs = SubPSG.objects.filter(psg=self.object).values()
sub_formset = inlineformset_factory(PSG, SubPSG, fields=('name',), can_delete=True,
extra=len(subpsgs), formset=BaseSubPSGFormset,)
context['formset'] = sub_formset(instance=self.object, initial=subpsgs, prefix='psg')
return context
def post(self, request, *args, **kwargs):
self.object = self.get_object()
subpsgs = SubPSG.objects.filter(psg=self.object).values()
psg_form = PSGForm(request.POST, instance=self.object)
sub_formset = inlineformset_factory(PSG, SubPSG, fields=('name',), can_delete=True, extra=len(subpsgs), formset=BaseSubPSGFormset)
formset = sub_formset(self.request.POST, instance=self.object, prefix='psg')
if all([psg_form.is_valid(), formset.is_valid()]):
return self.form_valid(psg_form, formset)
else:
return self.form_invalid(psg_form, formset)
def form_valid(self, form, formset):
if all([formset.is_valid() and form.is_valid()]):
self.object = form.save()
instances = formset.save(commit=False)
for form in instances:
form.psg = self.object
form.save()
return HttpResponseRedirect(self.get_success_url())
else:
return super(PSGUpdate, self).form_valid(form)
When I try updating a SubPSG formset, a new object is created instead of the edit taking place. Moreover, duplicates of the other formsets are also created.
What I'm I doing wrong??