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()
Related
I have a few forms in my forms variable, which I took from my DB.
views.py:
def settings(request):
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})
MY HTML:
<h3>{{ error }}</h3>
{% for form in forms %}
<form method="POST" id="{{form.name.name}}">{% csrf_token %}</form>
{% endfor %}
<form method="POST" id="new-form"> {% csrf_token %}</form>
{% for form in forms %}
<tr>
<td>{{ form.name }}</td>
<td>{{ form.token }}</td>
<td><button class="btn btn-lg btn-success w-100">Save</button></td>
</tr>
{% endfor %}
<tr>
<td><input class="form-control" placeholder="Name" form="new-form"></td>
<td><input class="form-control" placeholder="API-token" form="new-form"></td>
<td><button class="btn btn-lg btn-success w-100" form="new-form">Add</button></td>
</tr>
I am making a kind of editable grid and using a table for my layout ( so I cannot put a form direct to a row). So I am making the forms separately with the new HTML 5 form tag.
But I cannot take out the name(HTML attr on my inputs) which == the name field in the DB. So I could make different forms for every single row in my database. Can you help me?
I was thinking about setting the id of the form from my forms object but it makes the same forms for every row.
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
I am working on a Supplier Management System. I have a page where users could view all suppliers on the application. on the same page, users can upvote and downvote suppliers, is there a way that i could make the supplier not able to upvote or downvote his self.
I am thinking if there is a way i can pass the supplier.user into the context which identifies the supplier, perhaps doing something like this but it doesn't seem to work. I could then pass this into the template {% if supplier.user == request.user %}content...{% endif %}
Presently, supplier.user return nothing.
views.py
def Viewsupplier(request):
title = "All Suppliers"
suppliers = User.objects.filter(user_type__is_supplier=True)
# Get the updated count:
suppliers_votes_count = {}
for supplier in suppliers:
upvote_count = supplier.upvotes
downvote_count = supplier.downvotes
supplier_count = {supplier: {'upvote': upvote_count, 'downvote': downvote_count } }
suppliers_votes_count.update(supplier_count)
context = {"suppliers":suppliers, "title":title, "suppliers_votes_count": suppliers_votes_count}
return render(request, 'core/view-suppliers.html', context)
view-supplier.html
<thead>
<tr>
<th>No</th>
<th>Email</th>
<th>Votes</th>
</tr>
</thead>
<tbody>
{% for supplier in suppliers %}
<tr>
<td>{{forloop.counter}}</td>
<td>{{supplier.email}}</td>
<td>
<div class="table-data-feature">
{% if supplier.user == request.user %}<a href="{% url 'upvote' supplier.id %}">{% endif %}
<button class="item" data-toggle="tooltip" data-placement="top" title="Like">
<i class="zmdi zmdi-thumb-up"></i></button>
{% if supplier.user == request.user %}</a>{% endif %}
<button>{{supplier.upvotes}}</button>
{% if supplier.user == request.user %}<a href="{% url 'downvote' supplier.id %}">{% endif %}
<button class="item" data-toggle="tooltip" data-placement="top" title="Dislike">
<i class="zmdi zmdi-thumb-down"></i></button>
{% if supplier.user == request.user %}</a>{% endif %}
<button>{{supplier.downvotes}}</button>
</div>
</td>
</tr>
{% empty %}
<tr><td class="text-center p-5" colspan="7"><h4>No supplier available</h4></td></tr>
{% endfor %}
</tbody>
I was able to solve the issue by using this templatetag in my templates:
{% if supplier.email != request.user.email %}content...{% endif %}
This worked easily because i already had the supplier info from the views already.
Whenever I press my submit button for my file to go to that file page I get a method not allowed, I thought it was an issue with not has POST and GET but I do. Essentially this line isn't working in my code
if request.method == 'POST':
return redirect(url_for('files()'))
views.py
class HView(BaseView):
route_base = "/home"
#expose('/test')
#appbuilder.app.route('/test', methods=['GET', 'POST'])
def test(self):
if request.method == 'POST':
return redirect(url_for('files()'))
else:
return render_template(blah)
index.html
{% extends "appbuilder/base.html" %}
{% block title %}Title{% endblock %}
{% block content %}
<div class="container">
<div class="col-12-xs">
<h3>Bucket List</h3>
<table class="table table-striped">
<tr>
<th>Bucket Name</th>
<th>Created</th>
<th></th>
</tr>
{% for bucket in buckets %}
<tr>
<td>{{ bucket['Name'] }}</td>
<td>{{ bucket['CreationDate'] | datetimeformat }}</td>
<td>
<form class="select-bucket" action="{{ url_for('HView.test')}}" method="post">
<input type="hidden" name="bucket" value="{{ bucket['Name'] }}"/>
<button type="submit" class="btn btn-primary btn-sm">
<i class="fas fa-archive"></i>
</button>
</form>
</td>
</tr>
{% endfor %}
</table>
</div>
</div>
{% endblock %}
Try specifying the method in #expose
Ex:
class HView(BaseView):
route_base = "/home"
#expose('/test', methods=['GET', 'POST'])
def test(self):
if request.method == 'POST':
return redirect(url_for('files()'))
else:
return render_template(blah)
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})