How to connect multiple chained dropdown with django-forms-dynamic - python

I have a form with counterparty, object and sections i connected them to each other with django-forms-dynamic package but object not connected to sections
Counterparty connected to object form but sections are not connected to object how can i fix that?
I guess that im wrong with 2 functions in forms.py: section_choices and initial_sections and they`re not connected to objects but dont know how to fix that
forms.py
class WorkLogForm(DynamicFormMixin, forms.ModelForm):
def object_choices(form):
contractor_counter = form['contractor_counter'].value()
object_query = ObjectList.objects.filter(contractor_guid__in=[contractor_counter])
return object_query
def initial_object(form):
contractor_counter = form['contractor_counter'].value()
object_query = ObjectList.objects.filter(contractor_guid__in=[contractor_counter])
return object_query.first()
def section_choices(form):
contractor_object = form['contractor_object'].value()
section_query = SectionList.objects.filter(object=contractor_object)
return section_query
def initial_sections(form):
contractor_object = form['contractor_object'].value()
section_query = SectionList.objects.filter(object=contractor_object)
return section_query.first()
contractor_counter = forms.ModelChoiceField(
label='Контрагент',
queryset=CounterParty.objects.none(),
initial=CounterParty.objects.first(),
empty_label='',
)
contractor_object = DynamicField(
forms.ModelChoiceField,
label='Объект',
queryset=object_choices,
initial=initial_object,
)
contractor_section = DynamicField(
forms.ModelMultipleChoiceField,
label='Раздел',
queryset=section_choices,
initial=initial_sections,
)
views.py
#login_required
def create_work_log(request):
if request.method == 'POST':
form = WorkLogForm(request.POST, user=request.user)
if form.is_valid():
work_log = form.save(commit=False)
work_log.author = request.user
work_log = form.save()
messages.success(request, 'Данные занесены успешно', {'work_log': work_log})
return redirect('create_worklog')
else:
messages.error(request, 'Ошибка валидации')
return redirect('create_worklog')
form = WorkLogForm(user=request.user, initial=initial)
return render(request, 'contractor/create_work_log.html', {'form': form})
def contractor_object(request):
form = WorkLogForm(request.GET, user=request.user)
return HttpResponse(form['contractor_object'])
def contractor_section(request):
form = WorkLogForm(request.GET, user=request.user)
return HttpResponse(form['contractor_section'])

This may not be an answer you want but I use HTMX for these things. Here is a link to their example for this.
https://htmx.org/examples/value-select/
There is also a package plugin called Django-htmx.
You may need to learn HTMX but it is a mature technology, rather simple and reliable. I am unfamiliar with Django-forms-dynamic

Related

How would I receive multiple items from a model form thro' Select2MultipleWidget and ModelChoiceField?

I have a view and a model form as shown below. I initially could get a single item ID to use inn the view. Now I need multiple items selected from a Select2MultipleWidget. How would I do this? I already tried as shown in my code. I can understand that the data from the form to the view is not correct.
def new_issue(request,pk):
borrowed = request.session.get('teacher_borrowings')
if request.method == 'POST':
form = IssueForm(request.POST,pk=pk)
if form.is_valid():
try:
book = form.cleaned_data['book_id'].id
form.save(commit=True)
books = Books.objects.filter.get(id=book)
Books.Claimbook(books)
return redirect('all_borrowed_teacher', borrowed=borrowed)
except Exception as e:
return redirect('/')
else:
pass
return render(request, 'item.html)
def new_issue(request,pk):
borrowed = request.session.get('teacher_borrowings')
if request.method == 'POST':
form = IssueForm(request.POST,pk=pk)
if form.is_valid():
try:
book = form.cleaned_data['book_id'].id
form.save(commit=True)
books = Books.objects.filter.get(id=book)
Books.Claimbook(books)
return redirect('all_borrowed_teacher', borrowed=borrowed)
except Exception as e:
return redirect('/')
else:
pass
return render(request, 'item.html)
The error
Select a valid choice. That choice is not one of the available choices.

NOT NULL constraint failed: mainsite_customer.user_id

I just wanna get profile with full form or empty form.
def local_cabinet(request):
user_id = request.user.id
caruser = Checkout.objects.filter(user=request.user)
# form = CheckoutForms()
orders = request.user.orderitem_set.all()
total_orders = orders.count()
ready_order = request.user.order_set.all()
customer = Customer.objects.filter(user=request.user)
customer_form = CustomerForm()
Maybe here's problem I don't know:
if request.method == 'POST':
if customer.exists():
form = CustomerForm(request.POST, request.FILES, instance=customer)
else:
form = CustomerForm(request.POST)
if form.is_valid():
form.save()
context = {
'caruser': caruser,
'orders': orders,
'total_orders': total_orders,
'ready_order': ready_order,
'cat_selected': 0,
'customer_form': customer_form,
'customer': customer,
}
return render(request, 'localcabinet.html', context=context)
I don't know why I get this, maybe because I'm not right at saving the form.
You are missing User instance in form, that you probably need to pass it after form creation and before saving it.
You didn't provide model nor forms, but I guess it will look like this:
if request.method == 'POST':
...
else:
form = CustomerForm(request.POST)
form.user = request.user
if form.is_valid():
form.save()
...
Another thing is that you assign queryset instead of single object with filter method:
customer = Customer.objects.filter(user=request.user) # gives queryset with probably one object
customer = Customer.objects.get(user=request.user) # gives an object - but gives Error if there is None or more than one
Probably the best approach to get single object is with try and except:
try:
customer = Customer.objects.get(user=request.user)
except Customer.DoesNotExists:
customer = None
then later instead of if customer.exists() you can use simple if customer.

UnboundLocalError when submitting form in Django App

I am trying to submit a form but receiving an error:
UnboundLocalError at /create/
local variable 'spr' referenced before assignment
Below is the section of my views.py file that is highlighted in the error, specifically:
return HttpResponseRedirect("/%i" %spr.id)
def create(response):
if response.method == "POST":
form = CreateNewSprint(response.POST)
if form.is_valid():
n = form.cleaned_data["name"]
spr = Sprint(name=n)
spr.save()
response.user.sprint.add(spr)
return HttpResponseRedirect("/%i" %spr.id)
else:
form = CreateNewSprint()
return render(response, "main/create.html", {"form": form})
I am unsure of why this is happening, any pointers in the right direction would be greatly appreciated. If any other code/information is needed please let me know.
If the form.is_valid() returns False, then it will aim to evaluate return HttpResponseRedirect("/%i" %spr.id), but spr is never set in that case. You thus should in that case rerender the invalid form:
def create(response):
if response.method == 'POST':
form = CreateNewSprint(response.POST)
if form.is_valid():
n = form.cleaned_data['name']
spr = Sprint(name=n)
spr.save()
response.user.sprint.add(spr)
return HttpResponseRedirect('/%i' %spr.id)
else:
form = CreateNewSprint()
return render(response, 'main/create.html', {'form': form})
Note: You can make use of redirect(…) [Django-doc] and
determine the url based on the view name and the parameters. This is more safe and elegant than performing string formatting and
then wrap it in a HttpResponseRedirect object [Django-doc].

2 forms, 1 view, 2 SQL tables in Django

I'm struggling to understand how to submit data from two django forms into two separate database tables from the same view. I only want one submit button. While this question got me closer to the solution, I'm getting errors and the data is not writing to the database. I think this code actually checks the two forms against each other instead of submitting both forms in one go. Any ideas?
Here's what I've tried:
For one form --> one table. This works, so it's a start.
# views.py
def BookFormView(request):
if request.method == 'POST':
form = BookForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect("/books/")
else:
form = BookForm()
return render(request, 'books/createbooks.html',
{'form' : form})
However, when I add this form in from forms.py to get the subsequent views.py I get local variable 'book_form' referenced before assignment. That's usually an easy global-vs-local variable issue to fix, but I don't know what it means in this case.
def BookFormView(request):
if request.method == 'POST':
if 'book' in request.POST:
book_form = BookForm(request.POST, prefix='book')
if book_form.is_valid():
book_form.save()
return HttpResponseRedirect("/books/")
bookdetailsform = BookDetailsForm(prefix='bookdetails')
elif 'bookdetails' in request.POST:
bookdetailsform = BookDetailsForm(request.POST, prefix='bookdetails')
if bookdetailsform.is_valid():
bookdetailsform.save()
return HttpResponseRedirect("/books/")
book_form = BookForm(prefix='book')
else:
book_form = BookForm(prefix='book')
bookdetailsform = BookDetailsForm(prefix='bookdetails')
return render(request, 'books/createbook.html',
{'book_form' : book_form,
'bookdetailsform': bookdetailsform})
Based on the question's comments:
def BookFormView(request):
if request.method == 'POST':
book_form = BookForm(request.POST, prefix='book')
bookdetailsform = BookDetailsForm(request.POST, prefix='bookdetails')
if book_form.is_valid() and bookdetailsform.is_valid():
book_form.save()
bookdetailsform.save()
return HttpResponseRedirect("/books/")
else:
book_form = BookForm(prefix='book')
bookdetailsform = BookDetailsForm(prefix='bookdetails')
return render(request, 'books/createbook.html',
{'book_form': book_form, 'bookdetailsform': bookdetailsform})
I think the problem is that when a user submits a bookdetails post request,
it will be handled under if 'book' in request.POST: condition. Why?
because string bookdetails contains string book, no matter the type of request they do, it will be handled with if book in request.POST: condition.
I believe fixing that if condition problem is the first step.

BaseModelFormSet __init__() got an unexpected keyword argument

I am getting the above error when I have tried to convert my inline_formset to have at least the first row required. (please see here for the StackOverflow question)
My existing code is below:
#views.py
def application(request, job_id):
job = get_object_or_404(Job, pk=job_id)
#return 404 if job isn't yet published
if (job.pub_date>timezone.now() or job.close_date<timezone.now()):
return HttpResponseNotFound('<h1>Job not found</h1>')
#create all the inlineformsets (can_delete) set to false as will always be empty upon population
EducationInlineFormSet = inlineformset_factory(Applicant, Education, extra=1, can_delete=False)
QualificationInlineFormSet = inlineformset_factory(Applicant, Qualification, extra=1, can_delete=False)
EmploymentInlineFormSet = inlineformset_factory(Applicant, Employment, extra=1, can_delete=False)
if request.method == 'POST':
applicant = Applicant(job=job)
form = ApplicantForm(request.POST, instance=applicant)
bottom_form = ApplicantFormBottom(request.POST, instance=applicant)
education_formset = EducationInlineFormSet(request.POST, instance=applicant)
qualification_formset = QualificationInlineFormSet(request.POST, instance=applicant)
employment_formset = EmploymentInlineFormSet(request.POST, instance=applicant)
#check all of the forms and formsets are valid
if form.is_valid() and bottom_form.is_valid() and education_formset.is_valid() and qualification_formset.is_valid() and employment_formset.is_valid():
# save the model to database, directly from the form:
form.save()
bottom_form.save()
education_formset.save()
qualification_formset.save()
employment_formset.save()
return render(request, 'jobs/success.html')
else:
applicant = Applicant(job=job)
form = ApplicantForm(instance=applicant)
bottom_form = ApplicantFormBottom(instance=applicant)
education_formset = EducationInlineFormSet(instance=applicant)
qualification_formset = QualificationInlineFormSet(instance=applicant)
employment_formset = EmploymentInlineFormSet(instance=applicant)
c = {
'job' : job,
'form' : form ,
'bottom_form' : bottom_form,
'education_formset' : education_formset,
'qualification_formset' : qualification_formset,
'employment_formset' : employment_formset,
}
return render(request, 'jobs/application.html', c)
In order to customise the formset I defined the following:
class BaseFormSet(BaseModelFormSet):
def __init__(self, *args, **kwargs):
super(BaseFormSet, self).__init__(*args, **kwargs)
for form in self.forms:
form.empty_permitted = False
and pass use it as follows:
EducationInlineFormSet = inlineformset_factory(Applicant, Education, extra=1, can_delete=False, formset=BaseFormSet)
This returns the above error and having read around a lot I'm still none the wiser how I can keep passing an instance to the formset.
Any help would be greatly appreciated.
Regards,
Chris.
I had a similar issue - the problem was the customised formset.
Try subclassing from BaseInlineFormSet (not BaseModelFormSet).
Here is the relevant section of the docs.

Categories

Resources