Django multiple forms, one form resets other form - python

Got some forms in my view...
I want that only what I have submitted is changed in the database. So that no forms overwrite each other. How can I do this with my view?
I even noticed that the order in which each '..._form.is_valid()' is, makes a difference in what gets overwritten
views.py
#login_required
def DashboardView(request):
browser = str(request.user_agent.browser.family)
user = str(request.user)
short_user = user[0:7] + "..."
try:
radius = request.user.fieldradius
except FieldRadius.DoesNotExist:
radius = FieldRadius(user=request.user)
try:
font_size = request.user.fontsize
except FontSize.DoesNotExist:
font_size = FontSize(user=request.user)
try:
change_color = request.user.colors
except Colors.DoesNotExist:
change_color = Colors(user=request.user)
try:
toggle_settings = request.user.togglesettings
except ToggleSettings.DoesNotExist:
toggle_settings = ToggleSettings(user=request.user)
try:
page_details = request.user.pagedetails
except PageDetails.DoesNotExist:
page_details = PageDetails(user=request.user)
if request.method == 'POST':
form = FieldForm(request.POST, instance=Field(user=request.user))
togglesettings_form = ToggleSettingsForm(
request.POST, instance=toggle_settings)
radius_form = FieldRadiusForm(request.POST, instance=radius)
change_color_form = ColorsForm(request.POST, instance=change_color)
fontsize_form = FontSizeForm(request.POST, instance=font_size)
pagedetails_form = PageDetailsForm(
request.POST, request.FILES, instance=page_details)
if togglesettings_form.is_valid():
togglesettings_form.save()
return redirect('/dashboard/#panel1')
if form.is_valid():
time.sleep(1.5)
obj = form.save(commit=False)
obj.creator_adress = get_client_ip(request)
obj.save()
return redirect('/dashboard')
if radius_form.is_valid():
radius_form.save()
return redirect('/dashboard')
if fontsize_form.is_valid():
fontsize_form.save()
return redirect('/dashboard')
if change_color_form.is_valid():
change_color_form.save()
return redirect('/dashboard')
if pagedetails_form.is_valid():
pagedetails_form.save()
return redirect('/dashboard')
else:
form = FieldForm()
radius_form = FieldRadiusForm(instance=radius)
fontsize_form = FontSizeForm(instance=font_size)
change_color_form = ColorsForm(instance=change_color)
pagedetails_form = PageDetailsForm(instance=page_details)
togglesettings_form = ToggleSettingsForm()
return render(request, 'dashboard.html', {'form': form, 'togglesettings_form': togglesettings_form, 'fontsize_form': fontsize_form, 'change_color_form': change_color_form, 'browser': browser, 'short_user': short_user, 'radius_form': radius_form, 'radius': radius, 'pagedetails_form': pagedetails_form})
If I submit a form, for example the togglesettings_form, it looks like this in the database:
After that, I submit another form, for example the fontsize_form. The fontsize_form will be saved but then the togglesettings_form will be resetted:
Forms and models, if you want to see them:
https://pastebin.com/PhaFCdBP
I have read something like
if ...form in request.POST:
do this
But I dont know how to implement that in my view

Usually I name the submit button on the form something like "my-form"
Then you can just go:
if "my-form" in request.POST:
then do what you need to do
View example:
if 'load_doc' in request.POST:
file = request.FILES['document_file']
doc = documents(client=current_client,document_name=request.POST['document_name'],document_file=file)
doc.save()
html example:
<form method="post" action="" enctype="multipart/form-data">
{% csrf_token %}
<div class="panel-body">{{ single_load_form|crispy }}</div>
<div class="panel-footer"><button class="btn btn-primary" name="load_doc">Submit</button></form></div>

Related

Django - 'This field is required on form' load

I have a Django view that shows two create forms.
Whenever the page loads all of the input fields display - 'This field is required".
enter image description here
Template code
{% block content %}
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ listing_create_form.as_p }}
{{ listing_media_form.as_p }}
<button type="submit">Submit Form</button>
</form>
{% endblock %}
views.py
#login_required
def createListing(request):
listing_create_form = ListingCreateForm(request.POST or None, request.FILES)
listing_media_form = ListingMediaForm(request.POST or None, request.FILES)
if request.method == 'POST':
if listing_create_form.is_valid() and listing_media_form.is_valid():
listing_create_form.instance.created_by = request.user
form = listing_create_form.save()
form.save()
new_listing_id = form.pk
# loop over images to upload multiple
for image_uploaded in request.FILES.getlist('image'):
image_instance = ListingMedia.objects.create(listing=form, image=image_uploaded)
image_instance.save()
return redirect('boat_listings')
context = {'listing_create_form': listing_create_form, 'listing_media_form': listing_media_form}
return render(request, 'listings/listing_create_form.html', context)
forms.py
class ListingCreateForm(forms.ModelForm):
class Meta:
model = Listings
widgets = {
"featured_image": forms.FileInput(
attrs={
"enctype": "multipart/form-data"
}
),
}
fields = "__all__"
exclude = ("created_by", "created_on", "last_modified",)
class ListingMediaForm(forms.ModelForm):
class Meta:
# image = forms.FileField(widget=forms.ClearableFileInput(attrs={'multiple': True}))
widgets = {
"image": forms.ClearableFileInput(
attrs={
"multiple": True
}
),
}
model = ListingMedia
fields = ['image']
Django template should render without field required message before user has inputted invalid inputs.
it looks like when you initialise form instances, it gets data and tries to validate so that's what you are receiving error messages.
change your view:
#login_required
def createListing(request):
if request.method == 'POST':
listing_create_form = ListingCreateForm(request.POST, request.FILES)
listing_media_form = ListingMediaForm(request.POST, request.FILES)
if listing_create_form.is_valid() and listing_media_form.is_valid():
listing_create_form.instance.created_by = request.user
form = listing_create_form.save()
form.save()
new_listing_id = form.pk
# loop over images to upload multiple
for image_uploaded in request.FILES.getlist('image'):
image_instance = ListingMedia.objects.create(listing=form, image=image_uploaded)
image_instance.save()
return redirect('boat_listings')
else:
listing_create_form = ListingCreateForm()
listing_media_form = ListingMediaForm()
context = {'listing_create_form': listing_create_form, 'listing_media_form': listing_media_form}
return render(request, 'listings/listing_create_form.html', context)

Why is my form not being saved to the database? [duplicate]

This question already exists:
Why is my form not being saved to my Django database? [duplicate]
Closed 2 years ago.
I'm trying to develop an e-commerce website using Django. I want to use Ajax to handle the view of my checkout form after it has been submitted. After the form is submitted, I want it to go to :
return HttpResponseRedirect(reverse(str(next_page))+"?address_added=True") , i.e http://127.0.0.1:8000/checkout/?address_added=True
But for some reason, it is not going there. Rather it's being redirected to http://127.0.0.1:8000/checkout/?csrfmiddlewaretoken=W4iXFaxwpdtbZLyVI0ov8Uw7KWOM8Ix5GcOQ4k3Ve65KPkJwPUKyBVcE1IjL3GHa&address=123+Main+Street&address2=&state=MA&country=USA&zipcode=55525&phone=%28877%29+314-0742&billing=on
As a result, the form data is also not getting saved. I was thinking if it were because of the new version of Django.
What I want to do is that after they submit the place order button, the form is going to be None, i.e disappear and then I would add a credit card form there for payment. But it is not happening. What is wrong here? How can I do this or is there a better way to do this?
My forms.py:
class UserAddressForm(forms.ModelForm):
class Meta:
model = UserAddress
fields = ["address", "address", "address2", "state", "country", "zipcode", "phone", "billing"]
My accounts.views.py:
def add_user_address(request):
try:
next_page = request.GET.get("next")
except:
next_page = None
if request.method == "POST":
form = UserAddressForm(request.POST)
if form.is_valid():
new_address = form.save(commit=False)
new_address.user = request.user
new_address.save()
if next_page is not None:
return HttpResponseRedirect(reverse(str(next_page))+"?address_added=True")
else:
raise Http404
else:
raise Http404
My orders.views.py:
#login_required()
def checkout(request):
try:
the_id = request.session['cart_id']
cart = Cart.objects.get(id=the_id)
except:
the_id = None
return redirect(reverse("myshop-home"))
try:
new_order = Order.objects.get(cart=cart)
except Order.DoesNotExist:
new_order = Order(cart=cart)
new_order.cart = cart
new_order.user = request.user
new_order.order_id = id_generator()
new_order.save()
except:
return redirect(reverse("cart"))
try:
address_added = request.GET.get("address_added")
except:
address_added = None
if address_added is None:
address_form = UserAddressForm()
else:
address_form = None
if new_order.status == "Finished":
#cart.delete()
del request.session['cart_id']
del request.session['items_total']
return redirect(reverse("cart"))
context = {"address_form": address_form, "cart": cart}
template = "orders/checkout.html"
return render(request, template, context)
My urls.py:
path('ajax/add_user_address', accounts_views.add_user_address, name='ajax_add_user_address'),
My checkout.html:
<form method="POST" action="{% url 'ajax_add_user_address' %}?redirect=checkout">
{% csrf_token %}
<fieldset class="form-group">
{{ address_form|crispy }}
</fieldset>
<div class="form-group">
<button class="btn btn-outline-dark" type="submit">Place Order</button>
</div>
</form>

How to pre-populate form with data received from a previous HTML form submission in Django?

I'm trying to populate my ModelForm with some of data that I have submitted to previous HTML page which is also ModelForm.
I just want to pass it to another form so it doesn't have to be written twice.
I've tried couple solutions from stackoverflow but they are 6+ years old, kinda outdated and also couldnt come up with solution from django docs https://docs.djangoproject.com/en/2.2/topics/forms/
I have two models, which have same fields which are name and boxid
I need to pass it from first input to second(to populate it).
forms.py
class NewCashierForm(forms.ModelForm):
class Meta:
model = Cashier
fields = ("cashier_company", "cashier_dealer", "cashier_name", "cashier_boxid", "cashier_type", "cashier_package", "cashier_otheritem", "cashier_otheritemserial", "cashier_length", "cashier_promotion", "cashier_amount", "cashier_paymenttype")
labels = {"cashier_company":('Firma'), "cashier_dealer": ('Diler'), "cashier_name":('Ime i prezime'), "cashier_boxid":('Box ID'), "cashier_type":('Tip'), "cashier_package":('Paket'), "cashier_otheritem":('Drugi uredjaj'), "cashier_otheritemserial":('SBU'), "cashier_length":('Dužina'), "cashier_promotion":('Promocija'), "cashier_amount":('Iznos'), "cashier_paymenttype":('Nacin uplate')}
exclude = ['cashier_published']
def save(self, commit=True):
cashier = super(NewCashierForm, self).save(commit=False)
if commit:
cashier.save()
return cashier
class NewPersonForm(forms.ModelForm):
class Meta:
model = Person
fields = {"person_name", "person_adress", "person_phone", "person_boxid"}
labels = {"person_name":('Ime i prezime'), "person_adress":('Adresa'), "person_phone":('Telefon'), "person_boxid":('Box ID')}
def save(self, commit=True):
person = super(NewPersonForm, self).save(commit=False)
if commit:
person.save()
return person
views.py
def addcashier(request):
if request.method == 'GET':
form = NewCashierForm()
else:
form = NewCashierForm(request.POST)
if form.is_valid():
fs = form.save(commit=False)
fs.user = request.user
fs.save()
return redirect('/byauthor')
return render (request, 'main/addcashier.html', {'form':form})
def addperson(request):
if request.method == 'GET':
form = NewPersonForm()
else:
form = NewPersonForm(request.POST)
if form.is_valid():
fs = form.save(commit=False)
fs.user = request.user
fs.save()
return redirect('/addcashier')
return render (request, 'main/addperson.html', {'form':form})
addperson.html and addcashier.html
{% extends "main/base.html" %}
{% block content %}
<form method="POST">
{% csrf_token %}
{{form.as_p}}
<button class="btn" type="submit">Unos i dodavanje pretplate</button>
</form>
<input type="button" value="Otkazi unos" onclick="window.history.back()" />
{% endblock %}
Any help and/or hint is appreciated.
To prepopulate the form, you need to pass an argument initial={} when initializing your form for the GET call. Since you are passing data from one view to another, you should use sessions.
def addperson(request):
if request.method == 'GET':
form = NewPersonForm()
else:
form = NewPersonForm(request.POST)
if form.is_valid():
fs = form.save(commit=False)
fs.user = request.user
fs.save()
request.session["person_form"] = request.POST.dict() #save the form as a dict in request.sessions
return redirect('/addcashier')
return render (request, 'main/addperson.html', {'form':form})
Then in your second view, use this data from sessions to initialize the form.
def addcashier(request):
if request.method == 'GET':
# get the form data from the request.session
form_data = request.session.pop('person_form', {})
box_id = form_data.get("person_boxid")
name = form_data.get("person_name")
form = NewCashierForm(initial={"cashier_name":name, "cashier_boxid":box_id}) # initialize the form with the data
else:
form = NewCashierForm(request.POST)
if form.is_valid():
fs = form.save(commit=False)
fs.user = request.user
fs.save()
return redirect('/byauthor')
return render (request, 'main/addcashier.html', {'form':form})

invalid block of form is rendered

I want to show a form for invitation. I have created a form but when i go to the url /invitations/request, the invalid block is shown not the template with form. What might be the reason?
url(r'^request/$', requestInvitation, name='request-invitation'),
#csrf_exempt
def requestInvitation(request):
form = InviteForm(request.POST or None)
response_data = {}
if form.is_valid():
join = form.save(commit=False)
email = form.cleaned_data.get('email')
already_join, created = Invitation.objects.get_or_create(email=email)
if created:
already_join.invite_code = get_invite_code()
already_join.save()
response_data['result'] = "Thank you for your interest"
response_data['email'] = email
print ('response_data', response_data)
return HttpResponse(json.dumps(response_data),content_type="application/json")
else:
return HttpResponse(json.dumps({'result': 'Error message'}))
# return HttpResponseRedirect('/')
context = {"form": form}
return render(request, 'invitation/invitation.html', context)
<form method="POST" class="invitation-form vcenter" action=".">
{% csrf_token %}
<div class="ui action input">
<input type="email" class="requested_email" name="email" placeholder="Email address">
<button class="ui button primary">Request Invite</button>
</div>
</form>
I think, you need to separate out the POST call. I mean, you need to check if the request method is POST or not. Something like this:
if request.method == 'POST': # If the form has been submitted...
response_data = {}
if form.is_valid():
join = form.save(commit=False)
email = form.cleaned_data.get('email')
already_join, created = Invitation.objects.get_or_create(email=email)
if created:
already_join.invite_code = get_invite_code()
already_join.save()
response_data['result'] = "Thank you for your interest"
response_data['email'] = email
print ('response_data', response_data)
return HttpResponse(json.dumps(response_data),content_type="application/json")
else:
return HttpResponse(json.dumps({'result': 'Error message'}))
# return HttpResponseRedirect('/')
else:
# An unbound form
Here's the workflow for your request:
A GET request is made (you're just visiting /invitations/request. So request.POST is an empty {}.
form = InviteForm(request.POST or None). Thus, the InviteForm is not valid.
if form.is_valid(): is False.
else: return HttpResponse(json.dumps({'result': 'Error message'})). So, the else clause is executed, which returns a JSON response, which you're showing in your template.
Now, for the solution:
#csrf_exempt
def requestInvitation(request):
form = InviteForm()
response_data = {}
if request.method == 'POST':
# This is a POST request, so request.POST will not be {}
form = InviteForm(request.POST)
if form.is_valid():
join = form.save(commit=False)
email = form.cleaned_data.get('email')
already_join, created = Invitation.objects.get_or_create(email=email)
if created:
already_join.invite_code = get_invite_code()
already_join.save()
response_data['result'] = "Thank you for your interest"
response_data['email'] = email
print ('response_data', response_data)
return HttpResponse(json.dumps(response_data),content_type="application/json")
else:
return HttpResponse(json.dumps({'result': 'Error message'}))
context = {'form': form}
return render(request, 'invitation/invitation.html', context)

How to access user input (POST) in different Django views

I have a view called "search" which stores POST input as "search_id" but "search_id" is only available in the scope of the view "search". I want to be able to access the variable "search_id" in my view "dispTable".
Disclaimer- if this part of my question makes no sense, plz ignore: I understand that I could add an additional parameter to dispTable which would allow me to pass the search_id into dispTable in a return statement but what if I wanted to be able to access search_id in multiple views.
def search(request):
if request.method == 'POST' :
search_id = request.POST.get('textfield', None)
try:
return dispTable(request)
except Person.DoesNotExist:
return HttpResponse("no such user")
except Person.MultipleObjectsReturned :
#return dispTable(request, search_id)
return showResults(request)
else :
return render(request, 'People/search.html')
def dispTable(request) :
table = authTable(Person.objects.filter(MAIN_AUTHOR = 'search_id'))
RequestConfig(request).configure(table)
#return render(request, 'People/tableTemp.html', {'table':table})
return render(request, 'People/tableTemp.html', {"table" : Person.objects.filter(MAIN_AUTHOR = search_id)})
I also tried using a form, but I still did not know how to access the input variable in additional views, like dispTable
from django import forms
class SearchForm(forms.Form) :
search_id = forms.CharField(max_length=100)
def process(self) :
search_id = self.cleaned_data['search_id']
def search(request) :
if request.method == 'POST' :
form = SearchForm(request.POST)
if form.is_valid() :
form.process()
return dispTable(request)
else :
form = SearchForm()
return render (request, 'People/search.html')
And here is my html file:
<form method="POST" action="send/">
{% csrf_token %}
<input type="text" name="textfield">
<button type="submit">Upload text</button>
</form>

Categories