My django version is 1.11.4, and I'm on a simple exercise in my book which I need to make a web page that people can submit their comments for a selected restaurant.
But it shows the message Forbidden (CSRF token missing or incorrect.).
views.py :
def comments(request, id):
if id != 0:
r = Restaurant.objects.get(id = id)
else:
return HttpResponseRedirect('/restaurantsList/')
if request.POST:
dateTime = timezone.localtime(timezone.now())
Comment.objects.create(
content = request.POST['content'],
visitor = request.POST['visitor'],
email = request.POST['email'],
dateTime = dateTime,
restaurant = r
)
return render_to_response('comments.html', locals(), RequestContext(request))
comments.html :
<!doctype html>
<html>
<head>
<title>Comments</title>
<meta charset='utf-8'>
</head>
<body>
<h2>Comments for {{ r.name }}</h2>
{% if r.comment_set.all %}
<p>We have {{ r.comment_set.all | length }} comments</p>
<table>
<tr>
<th>Visitor</th>
<th>Time</th>
<th>Comment</th>
</tr>
{% for c in r.comment_set.all %}
<tr>
<td>{{ c.visitor }}</td>
<td>{{ c.dateTime | date:'F j, Y' }}</td>
<td>{{ c.content }}</td>
</tr>
{% endfor %}
</table>
{% else %}
<p>No comment</p>
{% endif %}
<br /><br />
<form action='' method='post'> {% csrf_token %}
<table>
<tr>
<td><label for='visitor'>Visitor: </label></td>
<td><input id='visitor' type='text' name='visitor'></td>
</tr>
<tr>
<td><label for='email'>E-mail: </label></td>
<td><input id='email' type='text' name='email'></td>
</tr>
<tr>
<td><label for='content'>Comment: </label></td>
<td>
<textarea id='content' rows='10' cols='48'
name='content'></textarea></td>
</td>
</tr>
</table>
<input type='submit' value='Submit'>
</form>
</body>
I've added {% csrf_token %} in .html, used RequestContext(request) in view function and tried several ways I searched from the Internet. But it still doesn't work.
Can somebody give me a help? Thanks!
You should use a book that is more up to date. render_to_response is deprecated and RequestContext should not be used here. Also, passing locals is a horrible anti-pattern, although not the cause of your problem.
return render(request, 'comments.html', {'r': r})
Related
I am trying to save my form in my data base. But my code adds a new row instead of save changes to the existing one. where is my mistake?
view.py
def settings(request):
error = ''
if request.method == 'POST':
new_form = TrafficSourcesForm(request.POST)
if new_form.is_valid():
new_form.save()
else:
error = 'Something went wrong!'
new_form = TrafficSourcesForm()
forms = [TrafficSourcesForm(instance=x) for x in TrafficSources.objects.all()]
return render(request, 'mainpage/dashboard.html', {'new_form': new_form, 'forms': forms, 'error': error})
template
<div class="table table-striped table-hover">
<div class="table-row">
<th style="width: 42%">Name</th>
<th style="width: 43%">Token</th>
<th style="width: 15%">Action</th>
</div>
{% for form in forms %}
<div class="table-row">
<form method="POST">
{% csrf_token %}
<div class="table-cell">{{ form.name }}</div>
<div class="table-cell">{{ form.token }}</div>
<div class="table-cell"><button class="btn btn-lg btn-success w-100"">Save</button></div>
</form>
</div>
</div>
If its not clear: I am showing all the table from my databese on the page. I want to edit them and save again to the database.
Because you are using POST data and form to create a new instance on every request:
...
if request.method == 'POST':
new_form = TrafficSourcesForm(request.POST)
if new_form.is_valid():
new_form.save()
...
To edit an object, you first need to retrieve the instance, which is normally done using its unique identifier (pk). Although normally you would send this ID using the url dispatcher captured value. I am using a hidden field in this case:
mainpage/dashboard.html
<body>
{% if forms %}
<table class="table table-striped table-hover">
<thead>
<tr>
<th style="width: 42%">Name</th>
<th style="width: 43%">Token</th>
<th style="width: 15%">Action</th>
</tr>
</thead>
<tbody>
{% for form in forms %}
<form method="POST">
{% csrf_token %}
<tr>
<td>{{ form.name }}</td>
<td>{{ form.token }}</td>
<input type="hidden" value="{{ form.instance.pk }}" name="id">
<td class="table-cell"><button class="btn btn-lg btn-success w-100">Save</button></td>
</tr>
</form>
{% endfor %}
</tbody>
</table>
{% endif %}
<form method="POST">
{% csrf_token %}
{{new_form.as_p}}
<div class="table-cell"><button class="btn btn-lg btn-success w-100">Create</button></div>
</form>
</body>
views.py
def settings(request):
error = ''
if request.method == 'POST':
new_form = TrafficSourceForm(request.POST)
pk = request.POST.get('id')
if new_form.is_valid():
if pk:
TrafficSource.objects.filter(id=pk).update(**new_form.cleaned_data)
else:
TrafficSource.objects.create(**new_form.cleaned_data)
else:
error = 'Something went wrong!'
new_form = TrafficSourceForm()
forms = [TrafficSourceForm(instance=x) for x in TrafficSource.objects.all()]
return render(request, 'mainpage/dashboard.html', {'new_form': new_form, 'forms': forms, 'error': error})
Id recommend getting the specific object you want to modify. Ex. traffic_source = TrafficSources.objects.get(id=<id_here>)
I have an update view which displays a form (based on some criteria). I can update my model successfully, but if I enter bad data (like a bad time field), I do not get any errors back, I simply get a refresh of the update form.
My view looks like this:
class Cd_MixedView(UpdateView):
model = Track
template_name = 'cd_mixed_view.html'
form_class = TrackForm
context_object_name = 'cd_edit'
def get_context_data(self, **kwargs):
context = super(Cd_MixedView,self).get_context_data(**kwargs)
cur_track = Track.objects.get(id=self.kwargs['pk'])
context['form'] = TrackForm(instance=cur_track)
context['cd_info'] = Cd.objects.get(id=cur_track.cd_id.pk)
return context
def post(self, request, *args, **kwargs):
self.object = self.get_object()
form = self.get_form()
if form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)
def form_valid(self,form):
form.save()
return super(Cd_MixedView, self).form_valid(form)
def form_invalid(self,form):
print("Form Invalid")
return super(Cd_MixedView,self).form_invalid(form)
My template is the following:
<!-- templates/cd_mixed_view.html -->
{% extends 'base.html' %}
{% load static %}
{% block title %} CD Details{% endblock title %}
{% block content %}
<h1>CD Update Track </h1>
{% if cd_info %}
<p>Artist Name: {{ cd_info.artist_name}}
<p>Cd Title: {{ cd_info.cd_title }}
<p>Cd Total Time: {{ cd_info.cd_total_time|time:"H:i:s" }}
<p>Cd Run Time: {{ cd_info.cd_run_time|time:"H:i:s" }}
<p>Cd Remaining Time:
{% if cd_info.cd_run_time_delta > cd_info.cd_total_time_delta %}
(-{{ cd_info.cd_remaining_time|time:"H:i:s" }})
{% else %}
{{ cd_info.cd_remaining_time|time:"H:i:s" }}
{% endif %}
<TABLE BORDER="0" TABLE_LAYOUT="fixed" WIDTH="100%">
<TR BGCOLOR="#B0B0FF">
<TD ALIGN="Center"> Track #</TD>
<TD ALIGN="Center"> Cut Title</TD>
<TD ALIGN="Center">Track Length</TD>
<TD ALIGN="Center" BGCOLOR="#CC99CC">Run Time</TD>
<TD ALIGN="Center" BGCOLOR="#CC99CC">Time Remaining</TD>
</TR>
{% for tracks in cd_info.cd_tracks.all %}
{% if tracks.id != cd_edit.pk %}
<TR>
<TD ALIGN="Left" VALIGN="Top" WIDTH="10"> {{ tracks.track_number }}</TD>
<TD ALIGN="Left" VALIGN="Top"> {{ tracks.track_title }}</TD>
<TD ALIGN="Left" VALIGN="Top">{{ tracks.trk_length_time|time:"H:i:s" }}</TD>
<TD ALIGN="Left" VALIGN="Top">{{ tracks.trk_run_time|time:"H:i:s" }}</TD>
{% if tracks.trk_run_time_delta > cd_info.cd_total_time_delta %}
<TD BGCOLOR="#8DF1BF" ALIGN="Left"> (-{{ tracks.trk_remaining_time|time:"H:i:s" }})</TD>
{% else %}
<TD BGCOLOR="#8DF1BF" ALIGN="Left"> {{ tracks.trk_remaining_time|time:"H:i:s" }}</TD>
{% endif %}
</TR>
{% else %}
<form action="" method="post">
{% csrf_token %}
{{ form }}
<tr>
<td> </td>
<td><input type="submit" value="Update Track Values"></td>
</tr>
</form>
{% if form.errors %}
<p>There were some errors in the information you entered. Please correct the following:</p>
<ul>
{% for field in form %}
{% if field.errors %}
<li>{{ field.label }}:
{{ field.errors|striptags }}</li>
{% endif %}
{% endfor %}
</ul>
{% endif %}
{% endif %}
{% endfor %}
</TABLE>
{% endif %}
{% endblock content %}
The form itself is the following:
class TrackForm(forms.ModelForm):
class Meta:
model = Track
exclude = ('trk_length_time_delta',
'trk_run_time',
'trk_run_time_delta' ,
'trk_remaining_time',
'trk_remaining_time_delta',
)
widgets = {
'cd_id': forms.HiddenInput()
}
I even put a print in the invalid_form function - so it seems to know the form is invalid,
but it just redisplays my form with the previous data.
Any ideas what I am missing here?
Thanks
You use UpdateView yet for some reason you go and redefine most of it's useful methods while not even making any useful or new changes. The main problem is that you override get_context_data and overwrite the form while manually defining it even though the super method has already added the form properly to the context.
Let UpdateView do it's job most of the code you write is not needed as UpdateView already does that:
class Cd_MixedView(UpdateView):
model = Track
template_name = 'cd_mixed_view.html'
form_class = TrackForm
context_object_name = 'cd_edit'
def get_context_data(self, **kwargs):
context = super(Cd_MixedView,self).get_context_data(**kwargs)
cur_track = self.object # no need to get the object again it is already present in `self.object`
# form is already added to context by super method
context['cd_info'] = Cd.objects.get(id=cur_track.cd_id.pk)
return context
# `post`, `form_valid` and `form_invalid` methods were same as super so no need to write yourself
TypeError at /dashboard
'post' object is not iterable i am just try to get data from db table and show on dashboard in dabel form
my dashboard.html page
{% if posts %}
<table class="table table-dark table-hover">
<thead>
<tr>
<th scope="col" style="width:3%">ID</th>
<th scope="col" style="width:30%">Title</th>
<th scope="col" style="width:55%">Description</th>
<th scope="col" style="width:15%">Action</th>
</tr>
</thead>
<tbody>
{% for post in posts %}
<tr>
<td>{{posts.id}} </td>
<td>{{posts.title}}</td>
<td>{{posts.desc}}</td>
<td><a class="btn btn-primary" type="submit" value="Submit">Edit</a>
<form action ='' , method ='POST' class='d-inline'>
{% csrf_token %}
<input type='submit' class='btn btn-danger btn-sm' value ='Delete' >
</form>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<h4 class =' text-center alert alert-warning'>No Records </h4>
{% endif %}
</div>
</div>
{% endblock content %}
my views.py
def dashboard(request):
if request.user.is_authenticated:
posts= post.objects.all()
return render(request,'dashboard.html',{'posts':post})
else:
return HttpResponseRedirect('login')
urls.py
path('dashboard',views.dashboard,name='dashboard'),
You have a typo in your views.py file. Try change this:
return render(request,'dashboard.html',{'posts':post})
to this:
return render(request,'dashboard.html',{'posts':posts})
I assume in template dashboard.html you have to change this :
{% for post in posts %}
<tr>
<td>{{posts.id}} </td>
<td>{{posts.title}}</td>
<td>{{posts.desc}}</td>
to this :
{% for post in posts %}
<tr>
<td>{{post.id}} </td>
<td>{{post.title}}</td>
<td>{{post.desc}}</td>
It should be like this:
{% for post in posts %}
<tr>
<td>{{post.id}} </td>
<td>{{post.title}}</td>
<td>{{post.desc}}</td>
i am developing a web app in python using flask and a sqlite3 database. It is a web app for anonymous bullyng reports in schools.
In a route called tablatestigos i want to display a table with the information of the database. The headers of the table are "Escuela", "Curso", "Victima" and "Descripcion del hecho" but i want to make that "Curso" header to be a dropdown menu (like a Filter By header) and if you select for example the course 5A, it should display ONLY the table rows of that course.
I managed to create the table correctly and add that dropdown menu with all the courses in the header in html but i don't know how to connect it properly to the database so when i click in a certain "curso" it shows me only the rows for it.
I don't want the webpage to refresh everytime a course is selected, i want it to happen dinamically.
This is my python and flask code:
#app.route("/tablatestigos", methods=["GET", "POST"])
#login_required
def tablatestigos():
escuela = session["user_id"]
hechos = db.execute("SELECT * FROM testigos WHERE escuela = :escuela", escuela=session["user_id"])
if not hechos:
return apology("No se han recibido reportes aún.")
return render_template("tablatestigos.html", hechos=hechos)
Here is my html:
{% extends "layout.html" %}
{% block title %}
Reportes de Testigos
{% endblock %}
{% block main %}
<form action="/" method="post">
<table class="table table-striped">
<thead>
<tr>
<th>Escuela</th>
<th>Curso</th>
<th>Victima</th>
<th>Descripción del hecho</th>
<th>
<div class="dropdown">
<button class="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown">Todos
<span class="caret"></span></button>
<ul class="dropdown-menu" name="curso">
{% for hecho in hechos %}
<li>{{ hecho.curso }}</li>
{% endfor %}
</ul>
</div>
</th>
</tr>
</thead>
<tbody>
{% for hecho in hechos %}
<tr>
<td>{{ hecho.escuela }}</td>
<td>{{ hecho.curso }}</td>
<td>{{ hecho.victima }}</td>
<td>{{ hecho.hecho }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</form>
{% endblock %}
Sorry if this is a very noob question but i am new to coding and this is my first web app project i am developing.
Thanks in advance :)
I'm a django newbie, I'm making a little app to record work calls received during nighttime.
At the moment the app works fine. I have made a form to fill call data, which is then presented as a table using a generic ListView.
class IndexView(LoginRequiredMixin, generic.ListView):
login_url = '/login/'
redirect_field_name = 'redirect_to'
template_name = 'chiamate/list_full.html'
context_name = 'lista_chiamate'
def get_queryset(self):
return Chiamata.objects.all
Here is the code for the template:
{% extends 'chiamate/base.html' %}
{% block content %}
{% if user.is_authenticated %}
<i class="fa fa-plus-square-o fa-lg" aria-hidden="true"></i> Nuova Chiamata
<p></p>
{% else %}
<p>Welcome, Guest please [login]</p>
{% endif %}
<div class="table-responsive">
<table class="table table-striped">
<form action="{{ action }}" method="post">
{% csrf_token %}
{% for chiamata in object_list %}
{% if chiamata.data_chiusura.weekday == 4 or chiamata.data_chiusura.weekday == 5 or chiamata.data_chiusura.weekday == 6 %}
<tr class="info">
{% elif chiamata.data_chiusura == None %}
<tr class="danger">
{% else %}
<tr>
{% endif %}
<td><input class="checkbox" name="chiamata_mail" type="checkbox" id="checkbox_{{ chiamata.id }}"value="{{ chiamata.id }}"></td>
<td class="txtdata">{{ chiamata.utente.get_full_name|wordwrap:5 }}</td>
<td class="txtdata">{{ chiamata.data_chiamata|date:"l d M Y H:i" }}</td>
<td>{{ chiamata.interlocutore }}</td>
<td>{{ chiamata.testo_chiamata|truncatechars:200 }}</td>
<td class="txtdata">{{ chiamata.reperibile|wordwrap:5 }}</td>
<td>{{ chiamata.data_chiusura|date:"H:i" }}</td>
<td></i> Edit</td>
<td><i class="fa fa-trash-o fa-lg" aria-hidden="true"></i> Delete</td>
</tr>
{% endfor %}
<input id="send_selected" type="submit" value="Send" />
</form>
</table>
</dv>
{% endblock %}
I've already tried to add the checkboxes here. When I do, they show on the page but then when I press the send button (currently implemented as a form send, but I want to use a bootstrap button) I don't know how to pass the objects to the email function, or at least show them in a new page.
You should define the post method of your view:
class IndexView(LoginRequiredMixin, generic.ListView):
def post(self, request, *args, **kwargs):
return ChiamataUpdateView.as_view()(request)
And handle the post data on the other view.
Also, you get_queryset isn't returning a queryset since you're not calling all(). It should be:
return Chiamata.objects.all()