How to preserve form fields in django after unsuccessful submit? - python

Code from views.py:
def feedback(request):
if request.method == "POST":
form = CommentForm(request.POST)
if form.is_valid():
form.save()
else:
print("form.errors:", form.errors)
else:
form = CommentForm()
articles = Comment.objects.all()
ResponseDict = {"articles": articles, "form": form}
return render_to_response("feedback.html", ResponseDict,
context_instance = RequestContext(request))
I've tried this and several modifications from answers to similar questions, but nothing works. When I press submit button, all form fields in html become empty.
EDIT: code from feedback.html:
{% extends "base.html" %}
{% block main %}
<table>
<form action="/feedback/" method="POST">
{% csrf_token %}
<div class="article">
<label for="name">
Ваше имя:
</label>
<br />
<input type="text" name="name" id="name" size="40" class="inputbox" value="" />
<br />
<!-- class="inputbox required" -->
<textarea class="WithoutTinymce" cols="50" rows="10" name="text" id="text"></textarea>
<br />
<input type="submit" name="submit" value="Отправить">
</div> <!-- /article -->
</form>
</table>
{% include "articles.html" %}
{% endblock %}
I can also paste code from base.html if needed.
EDIT2: minimized code from base.html:
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="cs" lang="cs">
...
<body id="body-id" onload="loaded()">
<!-- Main -->
<div id="main" class="box">
<div id="page" class="box">
<div id="page-in" class="box">
<!-- Content -->
<div id="content">
{% block main %}
{% endblock %}
<hr class="noscreen" />
</div> <!-- /content -->
</div> <!-- /page-in -->
</div> <!-- /page -->
</div> <!-- /Main -->
</body>
</html>

In your template you are not making use of form passed by the view.
You can update part of your template as (assuming your field names in the form are first_field and second_field.
<form action="/feedback/" method="POST">
{% csrf_token %}
<div class="article">
<label for="name">
Ваше имя:
</label>
<br />
{{ form.first_field.errors }}
{{ form.first_field.label_tag }}: {{ form.first_field }}
<br />
<!-- class="inputbox required" -->
{{ form.second_field.errors }}
{{ form.second_field.label_tag }}: {{ form.second_field }}
<br />
<input type="submit" name="submit" value="Отправить">
</div> <!-- /article -->
</form>
For more reference - Displaying form using template

You need to pass the form back to the template; and you need to render the form in the template as per jpic's link.
The following should render your form errors:
from django.shortcuts import render, redirect
def feedback(request):
ctx = {}
ctx['articles'] = Comment.objects.all()
if request.method == "POST":
form = CommentForm(request.POST)
if form.is_valid():
form.save()
return redirect('/thanks')
else:
ctx['form'] = form
return render(request, 'feedback.html', ctx)
else:
ctx['form'] = CommentForm()
return render(request, "feedback.html", ctx)
In your template:
{% extends "base.html" %}
{% block main %}
<table>
<form action="/feedback/" method="POST">
{% csrf_token %}
<div class="article">
{{ form }}
<br />
<input type="submit" name="submit" value="Отправить">
</div> <!-- /article -->
</form>
</table>
{% include "articles.html" %}
{% endblock %}

Easy, your template has this:
<input type="text" name="name" id="name" size="40" class="inputbox" value="" />
So value attribute of the input tag is always empty.
Same goes for the textarea, which should always render empty:
<textarea class="WithoutTinymce" cols="50" rows="10" name="text" id="text"></textarea>
Check out the documentation about rendering a form in a template

Related

Why the html custom form is not working django

I have a contact page with a simple form.
Here is views.py:
def contact_view(request):
if request.method == 'GET':
form = ContactForm()
else:
form = ContactForm(request.POST)
if form.is_valid():
subject = form.cleaned_data['subject']
from_email = form.cleaned_data['from_email']
message = form.cleaned_data['message']
try:
send_mail(subject, message, from_email, settings.ADMIN_EMAILS)
except BadHeaderError:
return HttpResponse('Invalid header found.')
return redirect('success')
return render(request, "base/contact.html", {'form': form})
def success_view(request):
return HttpResponse('Success! Thank you for your message.')
this is contact.html:
{% block content%}
<main class="page contact-page">
<section class="portfolio-block contact">
<div class="container">
<div class="heading">
<h2>Contact me</h2>
</div>
<form method="post">
{% csrf_token %}
<div class="mb-3"><label class="form-label" for="name">Your Name</label><input class="form-control item" type="text" id="name"></div>
<div class="mb-3"><label class="form-label" for="subject">Subject</label><input class="form-control item" type="text" id="subject"></div>
<div class="mb-3"><label class="form-label" for="email">Email</label><input class="form-control item" type="email" id="email"></div>
<div class="mb-3"><label class="form-label" for="message">Message</label><textarea class="form-control item" id="message"></textarea></div>
<div class="mb-3"><button class="btn btn-primary btn-lg d-block w-100" type="submit" value="submit">Submit Form</button></div>
</form>
</div>
</section>
</main>
{% endblock %}
When I use form.as_p it works very well but when I use this template it is not working
it only shows in the terminal that a post request was made.
The html looping syntax of form is following, where we have access to specific field, field.label ,non_field_errors as well as particular field errors.
In your case you can use in this way:
contact.html
{% block content%}
<main class="page contact-page">
<section class="portfolio-block contact">
<div class="container">
<div class="heading">
<h2>Contact me</h2>
</div>
<form method="POST" novalidate>
{% csrf_token %}
{% if form.non_field_errors %}
{% for error in form.non_field_errors %}
<div>
{{error}}
</div>
{% endfor %}
{% endif %}
{% for field in form %}
<p>{{field.label_tag}} {{field}}</p>
<br>
{% for error in field.errors %}
<span>{{error}}</span>
{% endfor %}
{% endfor %}
<input type="submit" value="Save">
</form>
</div>
</section>
</main>
{% endblock %}
You can use it as above it will work perfectly with your existing views, as you said it is working with form.as_p.
If you give only form.as_p, it will render form fields in <p> tag of html, you can see through Ctrl+U of view page source,there we cannot have more control over form.
Your question -- How can i use bootstrap's classes in django's form?
Answer - You can set through widget in your form's fileds. for example:
class MyForm(forms.Form):
name=forms.CharField(widget=forms.TextInput(attrs={'class':'form-control'}))
In the above way, you can set it to every field.

Passing value along with form in POST data in Django

When I render the form in HTML, I use this view. the patient_id is used to denote what patient the check in is for and for name display and such.
def Checkin(request, patient_id):
patient = get_object_or_404(PatientInfo, pk=patient_id)
form = forms.PatientCheckinForm()
return render(request, 'patientRecords/checkin.html', {'patient': patient, 'form':form})
When I submit the patient form filled out as a POST method, I still need access to the patient_id. Currently this is the view that accepts the filled form:
def CheckinSubmit(request):
if request.method == 'POST':
form = forms.PatientCheckinForm(request.POST, request.FILES)
if form.is_valid():
instance = form.save(commit=False)
instance.date_time_of_checkin = dt.now()
instance.patient = patient.patient_id
instance.save()
return redirect('patientRecords/index.html')
I want to set the instance.patient to the patient_id that was part of patient from the Checkin view. Is there a way to pass the patient data back along with the POST method or is there another way this can be done?
For reference, here is my template and I am using ModelForm not form.
{% block content %}
<div class="container">
<h1>Patient Checkin</h1>
<h2>{{patient.first_name}} {{patient.last_name}}</h2>
</div>
<div class="container">
<form action="{% url 'patientRecords:checkinsubmit' %}" method="POST" class="form">
{% csrf_token %}
{% bootstrap_form form %}
{% buttons %}
<button type="submit" class="btn btn-primary">Submit</button>
{% endbuttons %}
</form>
</div>
{% endblock %}
Thanks in advance!
You should be able to simply add a hidden input to your form to capture the patient ID:
{% block content %}
<div class="container">
<h1>Patient Checkin</h1>
<h2>{{patient.first_name}} {{patient.last_name}}</h2>
</div>
<div class="container">
<form action="{% url 'patientRecords:checkinsubmit' %}" method="POST" class="form">
<input type="hidden" name="patient_id" value="{{patient.patient_id}}" />
{% csrf_token %}
{% bootstrap_form form %}
{% buttons %}
<button type="submit" class="btn btn-primary">Submit</button>
{% endbuttons %}
</form>
</div>
{% endblock %}
(Note this assumes that the patient ID is accessible from the patient_id property of the patient object.)
Then, in your CheckinSubmit method, you can access this value via request.POST.get('patient_id')
Alternatively, it appears that your check in form loads with the patient ID in the URL. In your CheckinSubmit method, you should be able to access this URL through the request.META.HTTP_REFERER property. You could then parse the URL (e.g., using request.META.HTTP_REFERER.split('/')[len(request.META.HTTP_REFERER.split('/')) - 1] to pull out the patient ID.
Example
<form method="post" action = "{% url 'user_search_from_group' %}">
<div class="module-option clearfix">
<div class="input-append pull-left">
<input type="hidden" name="groupname" value="{{ gpname }}" />
{% csrf_token %}
<input type="text" class="span3" placeholder="Filter by name" id="username3" name="username3" required>
<button type="submit" class="btn" name="submit">
<i class="icon-search"></i>
</button>
</div>
</div>
</form>
Here a hidden field is used to pass a value along form.
def user_search_from_group(request):
if request.method == 'POST':
username3 = request.POST.get('username3')
gname = request.POST.get('groupname')
Using request we are use the value inside view

Django : get data and edit in the same form, edit in one place

I've been working to make an edit form where shows data saved in db and user can edit it like jsp model and view. When user click button it shows add form but all the relevant information in db is already filled up in the form, so user can modifying old data and once they click submit button it redirect to main.
I succeeded to display a form when user click edit button but failed to get data.
this is views.py
#login_required
def update_article(request, article_no):
article = get_object_or_404(Article, no=article_no)
if request.method == "POST":
form = ArticleForm(request.POST, instance=article)
if form.is_valid():
post = form.save(commit=False)
post.save()
return redirect('blog.views.detail', no=article.no)
else:
form = ArticleForm(instance=article)
return render(request, 'blog/update_article.html', {'form': form})
urls.py
url(r'^update_article/(?P<article_no>[0-9]+)/$', views.update_article, name='update_article'),
update_article.html
{% extends 'blog/base.html' %}
{% block body %}
<form class="form-horizontal" role="form" action="create_article.html" method="post" enctype="multipart/form-data">
{% csrf_token %}
{% include 'blog/form_template.html' %}
<button type="submit" class="button-primary">submit</button>
</form>
list
{% endblock %}
detail.html
This is part of the page send users to update_article.html
<form action="{% url 'blog:update_article' item.no %}" method="post" style="display: inline;">
{% csrf_token %}
<input type="hidden" name="no" value="{{ item.no }}" />
<button type="submit" class="button-primary">edit</button>
</form>
form_template.html
{% for field in form %}
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<span class="text-danger small">{{ field.errors }}</span>
</div>
<label class="control-label col-sm-2" for="title">{{ field.label_tag }</label>
<div class="col-sm-10">{{ field }}</div>
</div>
{% endfor %}
In update_article views
pass article object with form
return render(request, 'blog/update_article.html', {'form': form, 'article': article})
and then form in html page
<form class="form-horizontal" role="form" action="create_article.html" method="post" enctype="multipart/form-data">
{% csrf_token %}
{% include 'blog/form_template.html' %}
<input class="u-full-width" type="text" name="title" value="{{article.title}}"/>
<textarea class="u-full-width" name="content" value="{{article.content}}"></textarea>
<button type="submit" class="button-primary">등록</button>
</form>
I think this would help your problem
also I guess your action link is not valid

How do I render form ChoiceField images next to choices without breaking the form?

I am trying to render the images of the choices next to their respective choice. Attempting to do so will not save the form as valid so I have become lost at what to do. I've tried both methods below and I have no idea why one works and the other doesn't, could I get some tips?
#Form:
class ServerGroupForm(forms.Form):
OPTIONS = (
("pic1", "https://i.imgur.com/tMahp6U.png"),
("pic2", "https://i.imgur.com/b76nwsj.gif"),
("pic3", "https://i.imgur.com/qzEcfyX.png Lover"),
("pic4", "https://i.imgur.com/kdc7UF7.png"),
("pic5", "https://i.imgur.com/ynWJ13W.gif"),
("pic6!", "https://i.imgur.com/goHFWsp.png"),
("pic7", "https://i.imgur.com/b76nwsj.gif"),
("pic8", "https://i.imgur.com/KPgKm79.png"),
("pic9", "https://i.imgur.com/7KtEV1i.png"),
("pic10", "https://i.imgur.com/7KtEV1i.png"),
("pic11", "https://i.imgur.com/FXfo773.png")
)
servergroups = forms.MultipleChoiceField(widget=forms.CheckboxSelectMultiple, choices=OPTIONS)
#View:
def sendmessage(msg):
#Other code sends msg to user, not includes so this isn't long
def select_server_group(request):
form = ServerGroupForm(request.POST)
if form.is_valid():
servergroups = form.cleaned_data['servergroups']
sendmessage(msg=servergroups)
return redirect('/')
return render_to_response('webts3/selcectsgroup.html', {'form':form },
context_instance=RequestContext(request))
#HTML: Works but no icons
<section class="login">
<div class="titulo">Create a channel</div>
<form method="post" action="." enctype="multipart/form-data">{% csrf_token %}
<table border="0">
{{ form.as_table }}
</table>
<input type="submit" class="btn btn-block btn-danger" value="Submit" style="margin-top: 10px;">
</form>
</section>
#HTML: Icons but not working
<form method='post' action="." enctype="multipart/form-data">{% csrf_token %}>
<table>
{% for x,y in form.fields.servergroups.choices %}
<tr>
<td><input type="checkbox" name="{{ x }}" value="{{ x }}"><img src={{ y }}</img></td>
</tr>
{% endfor %}
</table>
<input type='submit' value='submit'>
</form>
The name attribute of the field should not be {{ x }}. It should be "servergroups".
Note you'd also need to have some logic that determines if the field is already selected, for when for example the form is being redisplayed after validation errors.

Global Variable Django

I have two template in django:
first, i give name index.html
<html>
<head>
<title>Django</title>
</head>
<body>
<div id="formulir">
<form action="" method="POST" enctype="multipart/form-data">
{% csrf_token %}
<div class="label">Username</div><div class="input"><input type="text" name="username"/></div>
<div class="label">Email</div><div class="input"><input type="text" name="email"/></div>
<input type="submit" name="tambah" value="Add"/>
</form>
</div>
<div id="data">
{% block data %}{% endblock %}
</div>
</body>
</html>
Second, i give name data.html
{% extends 'index.html' %}
{% block data %}
<table border="1">
<tr>
<th>Username</th>
<th>Email</th>
</tr>
{% for i in data %}
<tr>{{ i.username }}</tr>
<tr>{{ i.email }}</tr>
{% endfor %}
</table>
{% endblock %}
I want to do when form in index.html submitted, the data show in data.html and when I submitted for the second time the data.html show 2 data, so the first data still exist. I don't want to save the data to database.
This is my views.py
from django.shortcuts import render_to_response
from django.template import RequestContext
global data
data = []
def home(request):
if request.POST:
data = data.append(request.POST)
return render_to_response('data.html', locals(), context_instance=RequestContext(request))
return render_to_response('index.html', locals(), context_instance=RequestContext(request))
anybody can help me?
Using global variables is bad practice overall but you may use it if your application run with one system process: Python Django Global Variables. You can save data in session or you need to put all posted data to form and repost it in hidden inputs for example if you need to get it without saving anywhere:
...
<div id="formulir">
<form action="" method="POST" enctype="multipart/form-data">
{% csrf_token %}
<div class="label">Username</div><div class="input"><input type="text" name="username"/></div>
<div class="label">Email</div><div class="input"><input type="text" name="email"/></div>
<input type="submit" name="tambah" value="Add"/>
{% for i in data %}
<input type="hidden" name="username" value="{{ i.username }}"/>
<input type="hidden" name="email" value="{{ i.email }}"/>
{% endfor %}
</form>
</div>
....
To create data variable and access to it in templates with code like that {{ i.username }} you need some logic in view:
def home(request):
data = []
if request.POST:
username = request.POST.getlist('username')
email = request.POST.getlist('email')
data = [{'username': u, 'email': e} for u, e in zip(username, email)]
return render_to_response('data.html', locals(),
context_instance=RequestContext(request))
return render_to_response('index.html', locals(),
context_instance=RequestContext(request))

Categories

Resources