at the moment, I try to make a search form for a small database.
This is a part of my models.py file:
from django.db import models
from django import forms
#...
class searchForm(forms.Form):
searchField = forms.CharField(max_length = 100)
#...
This is a part of my views.py file:
from django.shortcuts import render
from django.http import HttpResponse
from django.http import HttpResponseRedirect
#...
def index(request):
template = loader.get_template('index.html')
context = Context({})
return HttpResponse(template.render(context))
def search(request):
if request.method == 'POST': # If the form has been submitted...
form = searchForm(request.POST)# A form bound to the POST data
if form.is_valid():
searchData = form.cleaned_data['searchField']
return HttpResponseRedirect('search.html') # Redirect after POST #???
else:
searchData = searchForm() # an unbound form
return render(request, 'search.html', {'form': form,}) #???
#...
This is a part of my index.html, where I want to implement that form:
<label for="Search">Search:</label>
<form action = "/search/" method = "post">
{% csrf_token %} {{ form.as_p }}
<input type = "submit" value = "Go" />
</form>
What I'm trying to do:
When I submit the form I would like to redirect to the result file called search.html, where for the beginning, is the input from the search textfield showing up. The link struktur should be something like that:
Landing-Page is: http://127.0.0.1:8000/
after a submitted form: http://127.0.0.1:8000/search.html
I think there might be an error in the search method, where I marked the lines with the '???'. The next problem is, that my search textfield isn't showing up.
Would be great, if someone could give me some advice.
thanks,
eljobso
First: The form isn't showing up because as you say, you want it to appear in index.html but the index view isn't passing any form to the template. Is in search view where you pass the form the template.
If you want the behavior described you should reorganize the code like this:
from django.shortcuts import render
from django.shortcuts import render_to_response
from django.http import HttpResponse
from django.http import HttpResponseRedirect
from django.template.context import RequestContext
#...
def index(request):
# this will only render the template with the form
searchData = searchForm() # an unbound form
return render_to_response(
'index.html',
context_instance=RequestContext(
request,{'form':searchData,}
)
)
def search(request):
if request.method == 'POST': # If the form has been submitted...
form = searchForm(request.POST)# A form bound to the POST data
if form.is_valid():
searchData = form.cleaned_data['searchField']
# do whatever you want to process the search with
# searchada, maybe populate some variable
return render_to_response(
'search.html',
context_instance=RequestContext(
request,{'form':searchData,} # maybe add here the populated variable with the search
)
)
else:
# request.GET, just show the unbound form
searchData = searchForm() # an unbound form
return render_to_response(
'search.html',
context_instance=RequestContext(
request,{'form':searchData,}
)
)
Then your templates should be:
index.html
<!-- is not good to have a label outside form -->
<label for="Search">Search:</label>
<form action = "/search/" method = "post">
{% csrf_token %} {{ form.as_p }}
<input type = "submit" value = "Go" />
</form>
And also that text included inside search.html template because there you render the form as well.
I hope this may bring some light!
With django FormView you can do that:
class Index(FormView):
form_class = SearchForm
template_name = 'index.html'
success_template = 'search.html' # I've added this attr
def form_valid(self, form): #That return a your form, validated
# Here you can do something with you VALID form.
searchData = form.cleaned_data['searchField']
context = dict(
searchData=searchData,
)
return render_to_response(self.success_template, {}, RequestContext(self.request, context))
Related
Condition: I have a model, created an empty table in the database, and I'm trying to create an html form that will fill in the fields of the corresponding columns of the table.
And here's what my app looks like:
models.py
from django.db import models
class Cities(models.Model):
city = models.CharField(max_length=100)
def __str__(self):
return self.state
class Routes(models.Model):
route_name = models.CharField(max_length=50, default='Route')
lvl = models.IntegerField(default=0)
about = models.TextField(max_length=1500)
total_distance = models.IntegerField(default=0)
city = models.ForeignKey(Cities, on_delete=models.CASCADE)
forms.py
from django.forms import ModelForm
from .models import Routes
class RouteForm(ModelForm):
class Meta:
model = Routes
fields = '__all__'
views.py
from django.shortcuts import get_object_or_404, render
from django.http import HttpResponse
from routes_form.forms import RouteForm
def getAbout(request):
if request.method == 'POST':
form = RouteForm(request.POST)
if form.is_valid():
form.save()
return render(request, 'routes_form/form_page.html', {'form': form})
form.html
<form method="post">
{% csrf_token %}
<legend>
<h2>About</h2>
</legend>
{{ form }}
<input type="text" placeholder="Write more about the route: about waypoints, points of interest and warnings.">
<input type="submit" value="Send route">
</form>
I have already tried to do everything as indicated in the Django Forms documentation. But still something is wrong. Even at the moment of starting the server, it writes an error:
cannot access local variable 'form' where it is not associated with a value
It is because you haven't defined form for GET method so:
def getAbout(request):
if request.method == 'POST':
form = RouteForm(request.POST)
if form.is_valid():
form.save()
return redirect('some_view_name_to_redirect')
else:
form=RouteForm()
return render(request, 'routes_form/form_page.html', {'form': form})
Note: Models in Django are written in singular form, as Django itself add s as the suffix, so it is better to name the models as City and Route.
Here you passed form = RouteForm(request.POST) object for POST request you need to pass for GET request so, when def getAbout(request) function called with GET request then renders it like this ...
def getAbout(request):
form=RouteForm() # <---- called at GET request
if request.method == 'POST':
form = RouteForm(request.POST) # <---- called at POST request
if form.is_valid():
form.save()
return redirect("/")
return render(request, 'routes_form/form_page.html', {'form': form})
my views.py file i just try to update form data form dashboard so i'm not getting what's going wrong to the code can someone please help me to solve
def addpost(request):
if request.user.is_authenticated:
if request.method == 'POST':
forms = addpostForm(request.POST)
if is_valid():
forms.save()
forms = addpostForm()
else:
forms = addpostForm()
return render(request, 'addpost.html', {'form': forms})
else:
return HttpResponseRedirect('login')
addpost.html file
<form action ='' method='POST'>
{% csrf_token %}
{{form.as_p}}
<input type='submit' class='btn btn-success btn-sm' value ='Add' >
<input type='submit' class='btn btn-danger btn-sm' value ='Cancel' >
</form>
my forms.py
class addpostForm(forms.ModelForm):
class Meta:
model = post
fields = ['title','desc']
labels ={'title':'Title','desc':'Description'}
widgets = {'title':forms.TextInput(attrs={"class":'form-control'}),'desc':forms.Textarea(attrs={"class":'form-control'}),}
Your method did not return a HTTP response in case of a GET request. You should unindent the else and thus construct a new form in case of a GET request and render the page.
For a successful POST request, you normally redirect to a view (that can be the same view), to implement the Post/Redirect/Get architectural pattern [wiki].
from django.contrib.auth.decorators import login_required
from django.shortcuts import redirect
#login_required
def addpost(request):
if request.method == 'POST':
forms = addpostForm(request.POST, request.FILES)
if is_valid():
forms.save()
return redirect('name-of-some-view')
else:
forms = addpostForm()
return render(request, 'addpost.html', {'form':forms})
Note: You can limit views to a view to authenticated users with the
#login_required decorator [Django-doc].
I am trying to print the POST data from django form on my webpage, right under my form. I am able to print it by HttpResponse on a different page, but I want it on the same page when the user presses submit button.
Views.py
from django.views.generic import TemplateView
from django.shortcuts import render
from django import forms
from django.http import HttpResponseRedirect, HttpResponse
from home.forms import HomeForm
def home(request):
def get(request):
form = HomeForm()
return render(request, 'home/home.html', {'form':form})
if request.method=='GET':
response=get(request)
return response
elif request.method == 'POST':
form = HomeForm(request.POST)
if form.is_valid():
text = HomeForm('post')
return HttpResponse('post')
else:
form = HomeForm()
return render(request, 'home/home.html', {'form':form})
Forms.py
from django import forms
class HomeForm(forms.Form):
post = forms.CharField( widget= forms.TextInput() )
Html template
<div class="container">
<form method='post'>
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="submit" class="btn btn-danger">
</form>
<h2>{{ text }}</h2>
</div>
I want the post field input to be displayed in the 'text' mentioned in the h2 tag of the webpage as soon as the user presses the submit button, and not on a separate page like HttpResponse does.
You have three options to get this thing done :
First is, you redirect the form on submit to the same page and pass the request.POST.DATA in context and then you can easily display it.
Like :
def home(request):
def get(request):
form = HomeForm()
return render(request, 'home/home.html', {'form':form})
if request.method=='GET':
response=get(request)
return response
elif request.method == 'POST':
form = HomeForm(request.POST)
if form.is_valid():
text = HomeForm('post')
# return HttpResponse('post')
context = {'text' : text, 'form' : form,}
return render(request, 'home/home.html', context)
else:
form = HomeForm()
return render(request, 'home/home.html', {'form':form})
Second Option is To display itself in the form the initial values from the Model :
form = HomeForm(initial = {'text' : modelsFile.Model.object}) # models.ModelName.text
Third Option is to use JavaScript and JQuery for realtime display of data.
That would be complex but good to do, you can search for how to display form data realtime in JS on google.
Thank you.
I'm new to django and trying to create my first app and I think I might need some little help :)
I have a ModelForm on a site to submit and want to show the data on the same page. I'm having trouble to set up two functions on the same page, I think i might have to use a class and set it in urls.py but I'm not able to make it work :( the code looks like this:
forms.py:
from django import forms
from .models import Eintrag
class NameForm(forms.ModelForm):
class Meta:
model = Eintrag
fields = ['Anmeldung', 'Essen']
urls.py
from django.urls import path
from . import views
app_name = 'form'
urlpatterns = [
path('', views.get_name, name='form'),
]
views.py
from django.shortcuts import render
from django.utils import timezone
from django.contrib.auth.decorators import login_required
from .forms import NameForm
from .models import Eintrag
#login_required()
def get_name(request):
# if this is a POST request we need to process the form data
if request.method == 'POST':
# create a form instance and populate it with data from the request:
form = NameForm(request.POST)
# check whether it's valid:
if form.is_valid():
eintrag = form.save(commit=False)
# process the data in form.cleaned_data as required
# ...
# redirect to a new URL:
eintrag.Name = request.user # Set the user object here
eintrag.pub_date = timezone.now() # Set the user object here
eintrag.save()
return render(request, 'form/name.html', {'form': form})
# if a GET (or any other method) we'll create a blank form
else:
form = NameForm()
return render(request, 'form/name.html', {'form': form})
def post_list(request):
posts = Eintrag.objects.all()
return render('form/post_list.html', {'posts': posts})
name.html
...
{% include "form/post_list.html" %}
<form action="/form/" method="post">
{% csrf_token %}
{{ form }}
<input type="submit" value="Submit" />
</form>
...
post_list.html
{% for post in posts %}
{{ post }}
{% endfor %}
So the problem is in urls.py only get_name is handled and I'm clueless how I should include post_list. I rather not want to use different url's, do I have to?
Thanks for any help and advice!
You don't need a separate URL or view for the list. Just include the queryset in the context of your get_name view.
posts = Eintrag.objects.all()
return render(request, 'form/name.html', {'form': form, 'posts': posts})
with [Class Based View] it would be better.
But with your view, you can send multiple data via context.
#login_required()
def get_name(request):
# if this is a POST request we need to process the form data
if request.method == 'POST':
# create a form instance and populate it with data from the request:
''' codes '''
eintrag.save()
return HttpResponseRedirect(request.path) # generate an empty form
# if a GET (or any other method) we'll create a blank form
else:
form = NameForm()
posts = Eintrag.objects.all() # the queryset is here, and sent via context
return render(request, 'form/name.html', {'form': form,'posts':posts})
I your html remain the same, but keep your form action='' empty
{% include "form/post_list.html" %}
<form action="" method="post">
{% csrf_token %}
{{ form }}
<input type="submit" value="Submit" />
</form>
I have two views and I want to render those views to a single HTML page. I know how to render a single view to an HTML page but don't know how to render two views to a single HTML page.
views.py file
from django.shortcuts import render
from django.http import HttpResponse
from app.models import *
# Create your views here.
def collegeview(request):
if request.method == 'POST':
form = collegeform(requst.POST)
if form.is_valid():
form.save()
return HttpResponse('its done here')
else:
form = collegeform()
return render(request, 'about.html', {'form':form})
def schoolview(request):
if request.method == 'POST':
f = schoolform(requst.POST)
if f.is_valid():
f.save()
return HttpResponse('its done here')
else:
f = schoolform()
return render(request, 'about.html', {'f':f})
about.html
<html>
<body>
<h1>its working </h1>
first view <br>
<form action ='' method = 'POST'> {% csrf_token %}
{{form.as_p}}
<input type='submit' name='submit'>
</form>
2nd view<br>
<form action='' method='POST'> {% csrf_token %}
{{f.as_p}}
<input type='submit' name='submit'>
</form>
</body
</html>
single view working corresponding to the URL.
Not possible to render two different views to the same template, but you can add both the logics in a single view and then render both forms in that:
from django.shortcuts import render
from django.http import HttpResponse
from app.models import *
def institute_view(request):
f = schoolform(requst.POST or None)
form = collegeform(requst.POST or None)
if request.method == 'POST':
if form.is_valid():
form.save()
return HttpResponse('its done here')
elif f.is_valid():
f.save()
return HttpResponse('its done here')
else:
f = schoolform()
form = collegeform()
return render(request, 'about.html', {'f':f,'form':form})
By this method, both of your forms can be handled and whenever anyone of them gets posted the values will be saved accordingly.