Django ModelForm error message not showing in template - python

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})

Related

multiple form handling Django python 3.x

i wanted to make simple page with two input forms
first one for posting data into file
second for taking index and deleting data from file
and both of them working independent
but so far i can only use first form like the second one its not even reached not a single method from second form is completed
here goes the code:
###############
#Views.py
class HomeView(TemplateView):
template_name = 'index/num.html'
def get(self, request):
form = AddForm()
form2 = DeleteForm()
result = printResult()
return render(request, self.template_name, {'form': form, 'form2': form2,'result': result})
def post(self, request):
result = "result"
####____add option###################
if request.method == 'POST':
form = AddForm(request.POST)
form2 = DeleteForm(request.POST)
if form.is_valid():
text = form.cleaned_data['post']
if (re.match("[0-9]+", str(text))):
text = text
else:
text= None
result = addToFile(text)
args = {'form': form, 'form2': form2, 'text': text, 'result': result }
return render(request, self.template_name, args)
##########
###____Delete option#######
if form2.is_valid():
index = form2.cleaned_data['dell']
result = DeleteIndexFromFile(index)
args2 = {'form': form, 'form2': form2, 'text': index, 'result': result }
return render(request, self.template_name, args2)
##########
#forms.py
from django import forms
class AddForm(forms.Form):
post = forms.CharField(required = False)
class DeleteForm(forms.Form):
delete = forms.IntegerField(required = False)
#num.html
<div class="container">
<p>
<form method="post">
{% csrf_token %}
{{ form }}
<button type="submit">Submit</button>
</form>
<form method="delete" >
{% csrf_token %}
{{ form2 }}
<button type="submit">Delete</button>
</form>
</p>
<p>
<h4>Data: {{ text }}</h4>
<h4>{{ result }}</h4>
</p>
</div>
there's a package called django-shapeshifter for doing this:
https://github.com/kennethlove/django-shapeshifter
In the interest of full disclosure, I am a contributor to the project.

Problem setting initial Django ModelForm field value

I’m trying to set the default value in the form (the field is the date for publishing the article “public”), but when loading the form on the page, the field is empty. I tried to set the default value in the "header" field (any value, not necessarily today's date) - also does not appear.
form:
from main.models import Article
from datetime import datetime
class AddArticleForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(AddArticleForm, self).__init__(*args, **kwargs)
self.fields['publish'].initial = datetime.now()
class Meta:
model = Article
fields = ('title', 'author', 'body', 'publish', 'status')
labels = {
'body': 'Text'
}
widgets = {
'title': forms.TextInput(attrs={'class': 'md-form'}),
'author': forms.TextInput(attrs={'class': 'md-form'}),
'body': forms.Textarea(attrs={'class': 'md-textarea', 'rows': 3}),
'publish': forms.DateTimeInput(attrs={'class': 'md-form'}),
'status': forms.Select(attrs={'class': 'custom-select'})
}
views:
def add_article(request):
form = AddArticleForm(request.POST)
if form.is_valid():
form.save()
return redirect('/articles/')
args = {
'form': form
}
return render(request, 'html/add_article.html', args)
html:
...
<form action="." method="post" class="add-article">
{% csrf_token %}
{% for field in form %}
<div class="md-form">
{% if field.name != 'status' and field.name != 'publish' %}
<label for="{{ field.name }}">{{ field.label }}</label> {{ field }}
{% else %}
<label for="{{ field.name }}"></label> {{ field }}
{% endif %}
</div>
{% endfor %}
<button type="submit" class="btn btn-pink btn-block">Share</button>
</form>
...
Probably the issue is you are sending request.POST as argument to the form class even if it is a GET request.
form = AddArticleForm(request.POST)
^^^^^^^^^^^^^
So I suggest to update the view like this:
def add_article(request):
form = AddArticleForm(request.POST or None)
if request.method == "POST":
if form.is_valid():
form.save()
return redirect('/articles/')
context = {
'form': form
}
return render(request, 'html/add_article.html', context)
So that, it will handle POST requests explicitly, and send request.POST as argument only if there is request.POST.
I think you should add initial argument in your field form.
For example:
name = forms.CharField(initial='Your name')
Here is documentation on this:
https://docs.djangoproject.com/en/3.0/ref/forms/fields/#initial

django form not rendering in template. Input fields doesn't shows up

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))

FormSet saves the data of only one 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.

Django Form Errors not showing

I have a form validator and when it fails, the error message doesn't show. Any idea what I'm missing?
views.py:
def setup_onesheet(request):
# if the form has been submitted
if request.method == 'POST':
if 'unverified_username' in request.POST:
form = OnesheetURL(request.POST)
if form.is_valid():
...
form = OnesheetURL()
variables = RequestContext(request, {
'error_message': error_message,
'form' : form,
});
return render_to_response('onesheet_setup/setup_new_onesheet.html', variables)
forms.py:
class OnesheetURL(forms.Form):
unverified_username = forms.CharField(label='http://onesheet.com/', max_length=75, validators=[validate_slug])
template:
<form method="post" action="/setup/new/" id="verify-identity" class="full">
{% csrf_token %}
<ul>
<li>
{{ form.unverified_username.errors }}
{{ form.unverified_username.label_tag }}
{{ form.unverified_username }}
<p>Onesheet URL can only contain letters, numbers, underscores ( _ ) or hyphens ( - ).</p>
</li>
</ul>
<input type="submit">
</form>
Try:
def setup_onesheet(request):
# if the form has been submitted
if request.method == 'POST':
if 'unverified_username' in request.POST:
form = OnesheetURL(request.POST)
if form.is_valid():
...
else:
form = OnesheetURL()
variables = RequestContext(request, {
'error_message': error_message,
'form' : form,
});
return render_to_response('onesheet_setup/setup_new_onesheet.html', variables)

Categories