Django: Transmit GET-param after form-submit - django

I call my page with http://localhost:63314/user/mieter/?wohnungseinheit=1 as a(GET)-parameter.
I would like to use the transmitted parameter as an assignment for the "wohnungseinheit". After I filled in and sent my "form", the GET-parameter is missing.
How can I assign the "wohnungseinheit"?
def mieter(request,id):
if request.method == 'POST':
form = MieterForm(request.POST)
if form.is_valid():
tmp = request.GET.get('wohnungseinheit')
mieter = form.save()#wohnungseinheit=tmp
print(tmp) #result: None
Wohnungseinheit = Wohnungseinheiten.objects.get(id=tmp)
Wohnungseinheit.mieter.add(mieter)
return render(request,'Immo/user/mieter.html',{'form':form}) # i think i also could use render_to_response
else:
if not str == None and str(id).isdigit():
#unimportant code here
if blnAllowedAccess:
form = MieterForm(request.POST)
return render(request,'Immo/user/mieter.html',{'form':form})
else:
#NOTALLOWEDTOACCESS! TODO
pass
else:
tmp = request.GET.get('wohnungseinheit')
if tmp is not None:
form = MieterForm(request.POST or None)
return render(request,'Immo/user/mieter.html',{'form':form})
else:
pass #TODO: 404-error
EDIT:
models.py:
class MieterForm(forms.ModelForm):
nameL = forms.CharField(required=True,max_length=100)
class Meta:
model=Mieter
fields = ("nameL",)
class Wohnungseinheiten(models.Model):
mieter = models.ManyToManyField(Mieter,blank=True,null=True)
urls.py:
re_path(r'user/mieter/(?:(?P<id>\w+)/)?$', views.mieter,name="mieter"),
user/mieter.html:
<form class="form-signin" action="{% url 'mieter' %}" method="post">{% csrf_token %}
<input class="form-control" id="{{ form.nameL.auto_id }}" name="nameL" value="{{ form.nameL.value }} "type="text">
<button type="submit" class="btn btn-primary mb-2">Submit</button>
</form>

The solution was: <a href="{% url 'mieter' %}?wohnungseinheit=1">
The param could be dynamically assembled by an "if" or "for".

Related

Cannot pull the value from the key of a session dictionary in django

I have a session variable for the name of a company saved in my django view from a user input form. When I try and use this in a later view, no matter what I try it pulls the {key: value} pair rather than just the value
Views:
def start(request):
if request.method == 'POST':
# create a form instance and populate it with data from the request:
form = QuizTakerForm(request.POST )
# check whether it's valid:
if form.is_valid():
# process the data in form.cleaned_data as required
post = form.save(commit=False)
post.user = request.user
post.save()
request.session['obj_id'] = post.id
request.session['company_name'] = form.cleaned_data
# redirect to a new URL:
return HttpResponseRedirect('industry/')
....
def Gov_q1(request):
company_name = request.session.get('company_name')
print(company_name)
question = Question.objects.get(pk=24)
context = {'question': question, 'company_name': company_name}
return render(request, 'ImpactCheck/detail.html', context)
html:
<h1> Hi my name is {{ company_name }} </h1>
<h1>{{ question.text }}</h1>
<form action="." method="post">
{% for answer in question.answer_set.all %}
<input type="radio" name="answer" id="answer" value="{{ answer.id }}">
<label for="answer">{{ answer.answer_text }}</label><br>
{% endfor %}
<input type="submit" value="Submit">
</form>
Ive also tried company_name=request.session['company_name'], but both then render as {'company_name': 'test_company'} rather than test_company.
FYI If anyone has a similar issue I've circumvented using
def Gov_q1(request):
id=request.session.get('obj_id')
company_name= QuizTakers.objects.get(pk=id)
question = Question.objects.get(pk=24)
context = {'question': question, 'company_name': company_name, 'cn': cn}
return render(request, 'ImpactCheck/detail.html', context)

My django form returns empty cleaned_data

I have a simple Form, view and a html that renders the form. but the problem is that the form always returns form.is_valid == False.
So I have checked the cleaned data but I noticed that self.cleaned_data returns an empty list.
Here is the relevant code:
class GraphForm(forms.Form):
from_month = forms.DateField(widget=forms.Select(choices=MONTHS))
from_year = forms.DateField(widget=forms.Select(choices=YEARS))
to_month = forms.DateField(widget=forms.Select(choices=MONTHS))
to_year = forms.DateField(widget=forms.Select(choices=YEARS))
def clean(self):
return self.cleaned_data <<< will always stay be empty
def showgraph(request):
if request.method == 'POST':
form = GraphForm(request.POST)
if form.is_valid():
>>> will never happen <<<
...
...
...
else:
form = GraphForm()
return render(request, 'graph.html', {"form": form})
<form method="post">
{% csrf_token %}
{{ form.from_month }}
{{ form.from_year }}
<br>
{{ form.to_month }}
{{ form.to_year }}
<br>
<p align="center">
<button type="submit" class="btn btn-primary">send</button>
</p>
</form>
Can anyone help with this peculiar problem?
The <form> tag should have action besides method so that the submit button can work, like this.
<form action="{% url 'name_of_the_view' %}" method="post">
...
</form>
If the code doesn't reach inside form.is_valid(), then it means the form is not valid, add an else to if and print the form.errors() and return the same form to template also add form error in the template to see the errors.
def showgraph(request):
if request.method == 'POST':
form = GraphForm(request.POST)
if form.is_valid():
>>> will never happen <<<
else:
print(form.errors())
else:
form = GraphForm()
return render(request, 'graph.html', {"form": form})
Add error for each field:
<span class="text-danger">{{field.errors.as_text|cut:'* '}}</span>

Django add form on every page

In my application i need to add a form in base.html, which I've done. For this i used context_processors, now my problem is everytime i'm trying to post, i'm getting a blank page and this error: Method Not Allowed (POST)
In this form i want just to add a button where it will mark all current users notifications as read.
I know that you can use context_processors like this:
def my_context(request):
data = dict()
if request.user.is_authenticated:
data['notifications'] = Notification.objects.filter(user=request.user, read=False)
data['form'] = NotificationForm()
return data
But instead of adding the form i need these lines:
def my_context(request):
data = dict()
if request.user.is_authenticated:
data['notifications'] = Notification.objects.filter(user=request.user, read=False)
if request.method == 'POST':
if 'read-notifications' in request.POST:
for notification in data['notifications']:
notification.read = True
notification.save()
next = request.POST.get('next', '/')
return redirect(next)
return data
The form in base.html:
<form action="" method="POST">{% csrf_token %}
<input type="hidden" name="next" value="{{ request.path }}">
<button type="submit" class="btn m-btn--square btn-primary" name="read-notifications">Mark as read</button>
</form>
urls.py
url(r'^orders/create/$', views.admin_order_document, name='create_order'),
url(r'^orders/waiting/$', views.OrdersWaitingListView.as_view(), name='order_waiting_list'),
url(r'^orders/unallocated/$', views.OrdersUnallocatedListView.as_view(), name='order_unallocated_list'),
url(r'^orders/working/$', views.OrdersWorkingListView.as_view(), name='order_working_list'),
How can i show this form on every page without getting the above error?
So, I chose a different approach and i ended up with this solution:
base.html
<form action="{% url 'mark_read' %}" method="POST">{% csrf_token %}
<input type="hidden" name="next" value="{{ request.path }}">
<button type="submit" class="btn m-btn--square btn-primary" name="action" value="mark_read">Marchează ca citite</button>
</form>
views.py
#login_required()
def read_notifications(request):
if request.method == 'POST':
if 'action' in request.POST:
notifications = Notification.objects.filter(user=request.user, read=False)
for notification in notifications:
notification.read = True
notification.save()
next = request.POST.get('next', '/')
return redirect(next)
urls.py
url(r'^mark-read/$', views.read_notifications, name='mark_read'),
Basically, the form action will redirect me to the view function, it will do what it has to do and it will redirect me back on the same page.

Including the template doesn't return form field

Here is my form
Class SearchForm(forms.Form):
pub_from = forms.CharField(max_length=20)
pub_to = forms.CharField(max_length=20)
and my SearchView is
def SearchView(request):
if request.method == 'POST':
form = SearchForm(request.POST)
if form.is_valid():
pub_date_from = form.cleaned_data['pub_date_from']
pub_date_to = form.cleaned_data['pub_date_to']
#form.save()
return HttpResponseRedirect("/admin/")
else:
return render_to_response("search_form.html", {"form":form}, context_instance=RequestContext(request))
else:
form = SearchForm()
context = {"form":form}
return render_to_response("search_form.html", context, context_instance=RequestContext(request))
and my search_form.html is
<form action="" method="get">{% csrf_token %}
{{ form }}
<input type="submit" value="submit">
When I render the form singly it shows the form field and now when I inherit it to another template in category.html doing {% include "search_form.html" %} it only displays the submit button not the form field.
I dont know what am I doing wrong.
What is this???? <form action="" method="get">
the form method is a POST!
This was used by our throwing-stones ancestors:
<input type="submit" value="submit">
We now use button instead of input

Django CSRF verification failed. Request aborted

I have a model:
class Tour(models.Model):
owner_id = models.ForeignKey(User)
name = models.CharField(max_length=50)
location = models.ManyToManyField(Location)
subscribers = models.ManyToManyField(User, related_name="sub")
tour_date = models.DateField(null=True)
description = models.CharField(max_length=300, null=True)
And a template that includes this form:
<form method="post" action="/mytours/">
{% csrf_token %}
<input name="name" value="{{ name }}" class="pull-left" type="text" placeholder="Type the tour name... "></br>
<input name="tour_date" value="{{ tour_date }}" type="text" id="datepicker" placeholder="Pick a tour date..."/>
<button class="btn" data-dismiss="modal" aria-hidden="true">Cancel</button>
<button type="submit" class="btn btn-primary">Save</button>
</form>
And in my views I am trying to add to my database what is filled in the form:
if request.method == 'POST':
location = Location.objects.get(id=1)
name = request.POST.get('name', '')
tour_date = request.POST.get('tour_date', '')
tour = Tour()
tour.owner_id = user.pk
tour.name = name
tour.tour_date = tour_date
tour.location = location
tour.save()
c = {'name':name, 'tour_date':tour_date, 'tour':tour}
c.update(csrf(request))
return render_to_response("myTours.html", c)
I am new in django and I don't know where is the problem.
You're misunderstanding what to do with the CSRF token. You're creating it on POST, but the point is to create it for the original display of the form on the GET request. It is checked by the middleware on POST, so you don't need to add it there.
You should use the render call as recommended by surfeurX, but on the call that displays the form in the first place.
What I do when I implement forms in django is writing a form class and creating an instance of it in the view. Then pass the instance to the template.
# form class eg. in models.py
from django import forms
class TourForm(forms.Form):
name = forms.CharField(max_length=50)
# in the view
if request.method == 'POST':
form = TourForm(request.POST)
if form.is_valid():
# do your stuff here with form data
else:
form = TourForm() # An unbound form
return render(request, 'myTours.html', {
'form': form,
})
in your template you can display the generated form like this:
<form action="/mytours/" method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Save" class="btn btn-primary" />
</form>
for further information just look inside the official django forms documentation
You probably need to add django.middleware.csrf.CsrfViewMiddleware to MIDDLEWARE_CLASSES and add a RequestContext to your response:
return render_to_response("myTours.html", c, context_instance=RequestContext(request))
https://docs.djangoproject.com/en/1.3/ref/contrib/csrf/
How do you render your template ??? I think your csrf_token doesn't print any hidden input, add "request" in your template context like:
return render(request, "template.html", {"var": var})
https://docs.djangoproject.com/en/dev/topics/http/shortcuts/#render