django template form render with local variable - python

The example in https://docs.djangoproject.com/en/1.6/topics/forms/ demonstrates usage of form and has the following code:
def contact(request):
if request.method == 'POST': # If the form has been submitted...
form = ContactForm(request.POST) # A form bound to the POST data
if form.is_valid(): # All validation rules pass
return HttpResponseRedirect('/thanks/') # Redirect after POST
else:
form = ContactForm() # An unbound form
return render(request, 'contact.html', {'form': form,})
and contact.html template is
<form action="/contact/" method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit" />
</form>
I am wondering if it's possible in render(request,...,{'form':form,}) instead of specifying template file contact.html to pass variable with the contents of template, something like this:
html = """
<html>
<head> bla bla bla</head>
<body>
<form action="/contact/" method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit" />
</form>
</body>
"""
return render(request, html, {'form': form,})
If it's possible what could be the drawbacks and risks associated with such approach?
Thanks in advance!

Not with render, which is a shortcut for loading a template, rendering it and returning a response. But you can do it with separate calls:
from django.template import RequestContext, Template
tpl = Template(html)
rendered = tpl.render(RequestContext(request, {'form': form}))
return HttpResponse(rendered)
The main drawback is that you're mixing the HTML in the python file, which makes it hard to read. Buy you could use this technique to load templates from the database or an api, for example.

Related

Django; Can't display on main page notes from admin page

I'm creating my first Django notes app and I'm trying to insert and display notes on the main page. Unfortunately I managed only how to insert them in data base, but I can't display them on the main page.
Here is my views.py file:
from django.shortcuts import render, render_to_response
from django.template import RequestContext, loader
from django.http import HttpResponse
from .models import Note
from .forms import NoteForm
def home(request):
notes = Note.objects
template = loader.get_template('note.html')
form = NoteForm(request.POST or None)
if form.is_valid():
save_it = form.save(commit=False)
save_it.save()
context = {'notes': notes, 'form': form}
return render(request, 'note.html', context)
And here is my html file:
<link href="http://codepen.io/edbond88/pen/CcgvA.css" media="screen" rel="stylesheet" type="text/css">
<style>
body {<br />
background: rgba(222,222,222,1);<br />
margin: 20px;<br />
}<br />
</style>
<h1>Notes App</h1>
<form method="POST" action="">
{% csrf_token %}
{{ form.as_p }}
<td> </td>
<input type="submit" value="Add note">
</form>
I'm trying to make the app from this tutorial: https://pythonspot.com/django-tutorial-building-a-note-taking-app/
You need Note.objects.all() instead of Note.objects in views.py:
def home(request):
notes = Note.objects.all()
template = loader.get_template('note.html')
form = NoteForm(request.POST or None)
if form.is_valid():
save_it = form.save(commit=False)
save_it.save()
context = {'notes': notes, 'form': form}
return render(request, 'note.html', context)
and also, you need to iterate over them to show them in the template:
<h1>Notes App</h1>
{% for note in notes %}
<p>{{ note }}</p>
{% endfor %}
try this :
return render(request, 'note.html', context=context)
instead of this :
return render(request, 'note.html', context)
and this :
notes = Note.objects.all()
instead of this :
notes = Note.objects
The first problem I see is that you didn't add any action into your form. The action attribute should be the view where you want to submit the form to.
So this is what you should do first:
<h1>Notes App</h1>
<form method="POST" action="whatever_your_url_for_this_page_is">
{% csrf_token %}
{{ form.as_p }}
<td> </td>
<input type="submit" value="Add note">
</form>

Can't display the data entered in form in database

The user enters the data in the form. But the data entered in the form doesn't get displayed in the Database.
views.py
def add(request):
if request.method=='POST':
form=FilesCreate(request.POST)
if form.is_valid():
form.save()
return render(request,'plagiarism/page1.html',{'form':FilesCreate()})
def add2(request):
if request.method=='POST':
form2=FilesCreate2(request.POST)
if form2.is_valid():
form2.save()
return render(request,'plagiarism/page2.html',{'form':FilesCreate2})
models.py
from django.db import models
class File1(models.Model):
#user=models.ForeignKey(User)
firstfile=models.CharField(max_length=1000, default="")
#secondfile=models.CharField(max_length=1000)
def __str__(self):
return self.firstfile
plagiarism/page1.html
<h1>Enter your first file</h1>
<form action="file2/" method="post">
{% csrf_token %}
{% for field in form %}
{{field}}
<input type="submit" value="Submit file1"/>
{% endfor %}
</form>
plagiarism/page2.html (displays page after clicking submit in page 1)
<h1>Enter your second file</h1>
<form action="plagiarism/file2/result/" method="post">
{% csrf_token %}
{% for field in form %}
{{field}}
<input type="submit" value="Get Results"/>
{% endfor %}
</form>
{% block h1 %}
{% endblock %}
<body>
plagiarism/page3.html (displays page after clicking submit in page 2)
<h1> Here is your Result </h1>
<h2>
{{data}}
</h2>
</body>
forms.py
from django.forms import ModelForm
from django import forms
from plagiarism.models import File1,File2
class FilesCreate(ModelForm):
class Meta:
model=File1
exclude=()
widgets={'firstfile':forms.Textarea(attrs={'cols':50,'rows':100})}
example.py
from django.shortcuts import render
def getresult(request):
data=95.5
return render(request,'plagiarism/page3.html',{'data': data})
urls.py
from django.conf.urls import url
from . import views
from . import example3
urlpatterns=[
url(r'^$',views.add,name='add'),
url(r'file2/$',views.add2,name='add2'),
url(r'file2/result/$',example3.getresult,name='getresult')
]
You seem to want a kind of wizard, where you process a form and it redirects you to the next, but you're not doing the basics of form processing well. For simple form handling, you can do this:
urls.py
from django.conf.urls import url
from . import views
from . import example3
urlpatterns=[
url(r'^$',views.add,name='add'),
url(r'file2/result/$', example3.getresult, name='getresult')
]
In the template, you are calling file2 with the form's action, but you really want to call the same page, to process the form with the add view:
plagiarism/page1.html
<h1>Enter your first file</h1>
<form method="post">
{% csrf_token %}
{% for field in form %}
{{field}}
{% endfor %}
<input type="submit" value="Submit file1"/>
</form>
Note the missing action attribute in the <form> element.
When you visit the root of the website, the add view will be called with a GET request. When you submit the form, the same add view will be called, with a POST request, which will then be processed:
views.py
def add(request):
if request.method == 'POST':
form = FilesCreate(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect(reverse('getresult'))
else:
form = FilesCreate()
return render(request,'plagiarism/page1.html',{'form': form})
Note the HttpResponseRedirect, which redirects to a new page on success, and the else, which creates an empty form for the first time you visit the page (i.e. request.method is not POST, it is GET). This way, if the form isn't valid, the last line will render it bound to the data that was submitted and display the errors.
This should get you the data into the database, which was your first goal. If you want to go to another form upon submission, you can redirect there (instead of the result page) and do the same as above in the view add2.
There used to be a Django Form Wizard, but you can see this project to do multi-step forms.

Form is not shown in html correctly

Form is not shown in html correctly.I wrote in search.html,
{% load static %}
<form action='/search/' method='POST>
<table>
{{ form.as_table }}
</table>
<input name="submit" type="Search" />
{% csrf_token %}
</form>
in views.py
def search(request):
form = SearchForm()
if request.method == 'GET':
return render_to_response(
'search.html', {'form': form}, RequestContext(request))
elif request.method == 'POST':
form = SearchForm(request.POST)
search_result = POST.objects.all()
if form.is_valid():
result = search_result.filter(Q(title__contains=form.cleaned_data['keyword']))
return render_to_response('search.html',{'form':form, 'result':result})
When I access search method,search.html is shown as strings like
now search.html
It is not From,so I really cannot understand why such a thing happens.No error happens but UserWarning: A {% csrf_token %}was used in a template, but the context did not provide the value. This is usually caused by not using RequestContext.
"A {% csrf_token %} was used in a template, but the context " is shown in terminal.How should I fix this?What is wrong in my code?
This may not be the issue, but I think your input tag is wrong, it should be this:
<input name="submit" type="Search">
As here : https://www.w3schools.com/tags/tag_input.asp

Django form isn't rendering at all

I'm trying to make a non model form that just gets input text for a chat like interface.
views.py
def get_input(request):
if request.method == 'POST':
form = inputForm(request.POST)
if form.is_valid():
return HttpResponseRedirect('/thanks/')
else:
form = inputForm()
return render(request, 'index.html', {'form': form})
def shelley_test(request):
form = inputForm()
return render(request, 'shelley_test.html')
form.py
from django import forms
class inputForm(forms.Form):
input = forms.CharField(label='input field')
shelley_test.html
<form action="/get_input/" method="get">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit" />
</form>
please please help. I'm new at django and stumped :(
You're not sending the form to the context in your shelley_test method - see the difference in the render line compared with get_input.
Note though you don't need shelley_test at all: just go straight to /get_input/ to see the empty form.

Django redirects to different view when form action is set to "."

I am lost here. I am quite new to django and maybe this is a newbie question.
I have a very simple list view , which shows the records in the database and a create view to add these objects :
#login_required
def list_view(request):
objects = Foo.objects.all()
ctx = {'objects': objects}
return render_to_response('main/foos.html', ctx,
context_instance=RequestContext(request))
#login_required
def create_view(request):
if request.method == 'POST':
form = FooForm(request.POST)
if form.is_valid():
form.save()
return redirect('/foos/')
else:
form = FooForm()
ctx = {'form': form}
return render_to_response('main/foo_form.html', ctx,
context_instance=RequestContext(request))
The foo_form.html template looks like this:
<!DOCTYPE html>
<html>
<head>
<title>Club</title>
</head>
<body>
<form action="." method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Confirm/>
</form>
</body>
</html>
Url settings:
urlpatterns = patterns('',
url(r'^foos/$', 'list_view'),
url(r'^foos/new$', 'create_view'),
)
When I type the url "localhost:8000/foos/new", the create view gets the GET request as expected. The problem is, upon submitting the form, I am redirected to the list (using a debugger I found out the request is getting to the list_view), even when form action is set to "."
What am I doing wrong? The create_view view should receive the POST request .
Any help is appreciated! Again, I am sorry if this is a newbie question
You haven't finished the regex string in the second url
url(r'^foos/new$', 'create_view')
so "." will use the current url to POST the form. Django takes the url '/foos/new' and matches it against the regex. It matches the first regex, as it finds a match for 'foos', so goes to the 'list_view'. Just finish your regex correctly and it will work.
url(r'^foos/new/$', 'create_view')
Leave the form action as "" to post to the same url rather than having a .
So in this case
<form action="" method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Confirm/>
</form>

Categories