I have a view like:
def some_view(request, page_url):
form = UserTicketForm(request.POST)
if request.method == 'POST':
if form.is_valid():
first_name = request.POST.get('first_name')
ticket_text = request.POST.get('ticket_text')
data = dict(
form=UserTicketForm,
)
return render(request, 'front/some_page.html', data)
and in HTML page it has:
{% csrf_token %}
{% bootstrap_form form %}
{% block submit %}
<div class="button_holder">
<button type="submit" name="register-submit" class="btn btn-primary" value="send">
submit
</button>
</div>
{% endblock %}
each time I refresh the page, it resubmits the last submitted form. how can fix this issue?
You need to redirect to a different url after the form is submitted and saved
if form.is_valid():
first_name = request.POST.get('first_name')
ticket_text = request.POST.get('ticket_text')
return HttpResponseRedirect(reverse('some_url'))
Write Like this
def some_view(request, page_url):
if request.method == 'POST':
form = UserTicketForm(request.POST)
if form.is_valid():
first_name = request.POST.get('first_name')
ticket_text = request.POST.get('ticket_text')
data = dict(
form=UserTicketForm,
)
return render(request, 'front/some_page.html', data)
Related
I have a django form, but it's not showing the "upload file" field when I render it on my website. What am I doing wrong? Ideally, the form has a question ID associated with it that's submitted automatically (e.g. it doesn't have to be manually put in by the user when uploading the file)
models.py
class Choice(models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE)
response_file = models.FileField(upload_to='audio_responses')
forms.py
class PostAudio(forms.ModelForm):
class Meta:
model = Choice
fields = ('response_file',)
views.py
def QuestionRecordSubmitView(request, pk):
model = Question
if request.method == 'POST':
form = PostAudio(request.POST, request.FILES)
if form.is_valid():
form.instance.question_id = pk
form.save()
# get survey pk
question_instance = Question.objects.get(pk=pk)
survey_pk = question_instance.survey.pk
return redirect('survey-share',pk=survey_pk)
else:
form = PostAudio()
return render(request, 'survey/question_audio_submit.html')
html
{% extends "landing/base.html" %}
{% block content %}
<h2>New Submission</h2>
<form method="POST" class="post-form" enctype="multipart/form-data">{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="save btn btn-default">Save</button>
</form>
{% endblock content %}
def QuestionRecordSubmitView(request, pk):
model = Question
if request.method == 'POST':
form = PostAudio(request.POST, request.FILES)
if form.is_valid():
form.instance.question_id = pk
form.save()
# get survey pk
question_instance = Question.objects.get(pk=pk)
survey_pk = question_instance.survey.pk
return redirect('survey-share',pk=survey_pk)
else:
form = PostAudio()
return render(request, 'survey/question_audio_submit.html', {'form':form})```
I have created some custom error message following the documentation (as best as I can find) but I'm not getting any errors, let alone my custom errors. Here's my code:
forms.py
class UploadFileForm(forms.ModelForm):
class Meta:
model = Job
fields = ['jobID','original_file']
labels = {
'jobID': _('Job ID'),
'original_file': _('File'),
}
error_messages = {
'jobID': {
'max_length': _("Job ID is limited to 50 characters."),
'required': _("Please provide a Job ID."),
'invalid': _("Job ID must be a combination of letters, numbers, - and _.")
},
'original_file': {
'required': _("Please provide a file."),
'validators': _("Please ensure you are selecting a zipped (.zip) GDB."),
},
}
help_texts = {
'original_file': _('Please provide a zipped (.zip) GDB.'),
}
upload.html
<form method = "POST" action="{% url 'precheck:upload' %}" enctype="multipart/form-data" name="uploadForm">
{% csrf_token %}
{% for field in form %}
<div>
<strong>{{ field.errors }}</strong>
{{ field.label_tag }} {{ field }}
{% if field.help_text %}
<p class ="help-text">{{ field.help_text }}</p>
{% endif %}
</div>
{% endfor %}
<br />
<button type="button" id="uploadButton" data-loading-text="Loading..." class="btn btn-primary" autocomplete="off" style="margin: auto 20%; ">Upload</button>
</form>
views.py
def upload(request):
if request.method == 'POST':
form = UploadFileForm(request.POST, request.FILES, user = request.user)
if form.is_valid():
form.save()
request.session['jobID'] = request.POST['jobID']
#job = Job.objects.filter(user_id = request.user.id).filter(jobID = request.POST['jobID']).latest()
# initialize(job)
return render(request,'precheck/run_precheck.html')
form = UploadFileForm()
historyList = Job.objects.filter(user_id = request.user.id)[:10]
return render(request, 'precheck/upload.html',{'form': form, 'history': historyList})
I've included everything I think is relevant, let me know if you need anything more.
The problem is that if the form is not valid, you're resetting the form to the initial form:
form = UploadFileForm()
historyList = Job.objects.filter(user_id = request.user.id)[:10]
return render(request, 'precheck/upload.html',{'form': form, 'history': historyList})
Your flow should render the bound form (with its errors) so it should be:
if request.method == 'POST':
form = UploadFileForm(request.POST, request.FILES, user = request.user)
if form.is_valid():
# do stuff for valid form
return redirect
elif request.method == 'GET':
form = UploadFileForm()
# flow common for GET and invalid form
return render(request, template, {'form': form})
I'm not able to see the django form in my template. it is not being rendered properly. I've tried working on this, but the form not shows up. Tried the same code in a new project to test-that worked fine but here it doesn't work. This {{ form.as_p }} not shows up anything i.e. no input fields for me to enter the details and check the other part. Thanks in advance.
# forms.py
class ContactForm(forms.Form):
contact_name = forms.CharField(required=True)
contact_email = forms.EmailField(required=True)
contact_subject = forms.CharField(required=True)
content = forms.CharField(
required=True,
widget=forms.Textarea
)`
and:
# views.py
def contact(request):
form_class = ContactForm
if request.method == 'POST':
form = form_class(data=request.POST)
if form.is_valid():
contact_name = request.POST.get(
'contact_name'
, '')
contact_email = request.POST.get(
'contact_email'
, '')
contact_subject = request.POST.get(
'contact_subject'
, '')
form_content = request.POST.get('content', '')
# Email the profile with the
# contact information
template = get_template('contact_template.txt')
context = Context({
'contact_name': contact_name,
'contact_email': contact_email,
'contact_subject' : contact_subject,
'form_content': form_content,
})
content = template.render(context)
email = EmailMessage(
"New contact form submission",
content,
"Your website" +'',
['youremail#gmail.com'],
headers = {'Reply-To': contact_email }
)
email.send()
return redirect('contact')
return render(request, 'contact.html', {
'form': form_class,
})
The template for the same looks like this.
template
<section id="contact">
<div class="container text-center">
<div class="row text-center">
<div class="bg-image">
<div class="col-md-6 col-md-offset-3 text-center share-text wow animated zoomInDown heading-text">
<p class="heading">
If you got any questions, please do not hesitate to send us a message.
</p>
</div>
</div>
</div>
{% block content %}
<h1>Contact</h1>
<form role="form" action="" method="post">{% csrf_token %}
{{ form.as_p }}
<button type="submit">Submit</button>
</form>
{% endblock %}
</div>
</section>
Add an else clause for generating a form on GET:
def contact(request):
form_class = ContactForm
if request.method == 'POST':
form = form_class(data=request.POST)
# ... more code from above ...
else:
form = form_class() # this is important
return render(request, 'contact.html', {
'form': form, # NOTE: instead of form_class!!!!
})
You are passing the form class to your template instead of a form instance.
You haven't handled the case when request.method is not POST.
Your view should look like this:
def contact(request):
if request.method == 'POST':
form = ContactForm(request.POST)
if form.is_valid():
# form handling logic here
# ...
# ...
return redirect('some-link')
else:
return render(request, 'template.html', dict(form=form))
else:
form = ContactForm()
return render(request, 'template.html', dict(form=form))
When I submitted forms (but on page I filled id more than 1 form) - my FormSet saves the data of only one form, the rest of the data just disappear...
My template:
<div id="data">
<form method="post" action="/lookup/" id="test_data">{% csrf_token %}
{{ formset.management_form }}
{% for form in formset %}
<section id="test_data_row">
{{ form }}
</section>
{% endfor %}
</form>
</div>
<div class="bt">
<button type="submit" class="btn btn-default" id="submit_form" form="test_data">Submit</button>
<button type="button" class="btn btn-default" id="add" value="Add row"/>Add row</button>
</div>
My forms.py:
class LookupForm(forms.ModelForm):
class Meta:
model = look
exclude = ()
LookupFormSet = formset_factory(LookupForm, can_delete=True)
My model
class look(models.Model):
class Meta():
db_table = 'lookup'
id_device = models.CharField(max_length=75)
phone_number = models.CharField(max_length=100)
phone_number_country = models.CharField(max_length=1000)
text = models.CharField(max_length=1000, default=None)
my views.py:
def manage_articles(request):
LookupFormSet = modelformset_factory(model=look, exclude=())
if request.method == "POST":
formset = LookupFormSet(
request.POST, request.FILES,
queryset=look.objects.none(),
)
if formset.is_valid():
for form in formset:
form.save()
return HttpResponseRedirect('/')
else:
formset = LookupFormSet(queryset=look.objects.none())
return render(request, 'req/lookup.html', {'formset': formset})
my JS (js for add new form):
document.getElementById('add').onclick = duplicate;
var i = 0;
var original = document.getElementById('test_data');
function duplicate() {
var clone = original.cloneNode(true); // "deep" clone
clone.id = "test_data" + ++i; // there can only be one element with an ID
original.parentNode.appendChild(clone);
}
You cannot save a formset as it contains multiple forms. So I would suggest you change your code to:
if formset.is_valid():
for form in formset:
form.save()
return HttpResponseRedirect('/')
See the docs.
I am creating a password reset form after a user is authenticated they are presented with the reset page where they can enter the username and new password. However once they have set this new data and click the submit button the data is shown in the url of the next page that is shown. How do I need to configure my application to not do this?
views.py
def index(request):
if request.method == 'POST':
form = login(request.POST)
if form.is_valid():
user = form.cleaned_data['username']
passw = form.cleaned_data['password']
if user and passw:
#try the post to login
r=validateUser(user,passw)
if r:
formReset = reset()
return render(request, 'loggedin.html',{'form' : formReset})
else:
return render(request, 'index.html',{'form' : form})
else:
form = login()
loggedin(request)
return render(request, 'index.html', {'form' : form})
def loggedin(request):
if request.method == 'GET':
form = reset(request.GET)
if form.is_valid():
user = form.cleaned_data['username']
newpassword = form.cleaned_data['newpassword']
confirmnewpassword = form.cleaned_data['confirmnewpassword']
if newpassword == confirmnewpassword:
#passwords match
val = resetpassword(user,newpassword)
else:
return render(request, 'loggedin.html', {"message" : 'Passwords do not match', 'form' : form})
else:
return render(request, 'loggedin.html',{'form' : form})
forms.py
from django import forms
class login(forms.Form):
#class used for the login prompt
username = forms.CharField(widget=forms.TextInput(attrs={'class' : 'btn btn-lg btn-default'}),label='')
password = forms.CharField(widget=forms.PasswordInput(attrs={'class' : 'btn btn-lg btn-default'}),label='')
class reset(forms.Form):
#class used for inputs to reset password
username = forms.CharField(widget=forms.TextInput(attrs={'class' : 'btn btn-default'}),label='User Name')
newpassword = forms.CharField(widget=forms.PasswordInput(attrs={'class' : 'btn btn-default'}),label='New Password')
confirmnewpassword = forms.CharField(widget=forms.PasswordInput(attrs={'class' : 'btn btn-default'}),label='Confirm Password')
loggedin.html
{% extends "base.html" %}
{% load staticfiles %}
{% block content %}
<form action="/" method="GET">
{% csrf_token %}
<div class="container">
<h1>You are logged in</h1>
{{ message }} </br>
{{ form.as_p }}
<input type="submit" class="btn btn-lg btn-default" action="submit" value="Reset">
</div></form>{% endblock %}
That's how a GET action works. You should be using POST for this anyway.