Django-- Get model fields in template only for current user - django

First of all, I know there are lot of questions about accessing model in template but let me explain why this is different.
I want profile page where User can see their details. I am able to do that but with one little bug. If there are 3 Users(say A, B,C) and User A want to see his profile he sees it three time. Like this:
How do I stop the loop after one iteration so that the User only get's his profile information once.
This is my URL:
url(r'^profile/$', views.IndexView.as_view(), name='profile'),
Views.py:
class IndexView(generic.ListView):
template_name = 'profile.html'
def get_queryset(self):
return Profile.objects.all()
and profile.html:
{% if user.is_authenticated %}
{% for profile in object_list %}
<h1>{{ request.user }}'s Profile</h1>
<table>
<tr>
<td>Username:</td>
<td>{{ user.username }}</td>
</tr>
<tr>
<td>First Name:</td>
<td>{{ user.first_name }}</td>
</tr>
<tr>
<td>Last Name:</td>
<td>{{ user.last_name }}</td>
</tr>
<tr>
<td>Email:</td>
<td>{{ user.email }}</td>
</tr>
<tr>
<td>Personal Info:</td>
<td>{{ user.profile.personal_info }}</td>
</tr>
<tr>
<td>Job Title:</td>
<td>{{ user.profile.job_title }}</td>
</tr>
<tr>
<td>Department:</td>
<td>{{ user.profile.department }}</td>
</tr>
<tr>
<td>Location:</td>
<td>{{ user.profile.location }}</td>
</tr>
<tr>
<td>Expertise:</td>
<td>{{ user.profile.expertise }}</td>
</tr>
<tr>
<td>Phone Number:</td>
<td>{{ user.profile.phone_number }}</td>
</tr>
<tr>
<td>Contact Skype:</td>
<td>{{ user.contact_skype }}</td>
</tr>
<tr>
<td>Contact Facebook:</td>
<td>{{ user.contact_facebook }}</td>
</tr>
<tr>
<td>Contact Linkedin:</td>
<td>{{ user.profile.contact_linkedin }}</td>
</tr>
</table>
<form class="form-horizontal" action="" method="post" enctype="multipart/form-data">
{% csrf_token %}
{% include 'form-template.html' %}
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<a href={% url 'profile_edit' %}><input type="button" class = " col-sm-offset-2 btn bk-bs-btn-warning " name="cancel" value="Edit" /></a>
</div>
</div>
</form>
{% endfor %}
{% else %}
<h2>Please login to see your Profile</h2>
{% endif %}
I am a newbie to django, thanks is advance.

You're looping over all Profile's but not actually using this data in the loop, instead you're using user.profile.
This means that you likely have 3 Profile objects in the database, then for each you display the details of the current user, which isn't desirable.
So you can remove the loop entirely, and just keep its contents that refer to all the user.profile attributes to achieve the desired result.
edit
Looks like user is passed into your template by default, and points to the currently logged in user. So user.profile will return the profile, and this works without doing anything else. So user.profile.personal_info is valid and should work. When you tried to use profile directly, that is not the same thing, and wasn't defined, so profile.personal_info didn't work. Then in your loop you used profile to loop over Profile objects, but this wasn't necessary or was used. Hope this makes sense.

Related

How to ADD for loop result in templates

views.html
{% for products in product %}
<tr>
<td>{{ products.quantity_deliver1 }}</td>
<td>{{ products.quantity_deliver2 }}</td>
<td>{{ Code Here }}</td>
</tr>
{% empty %}
<tr>
<td colspan="3" class="text-center bg-warning">No Products</td>
</tr>
{% endfor %}
How do I add products.quantity_deliver1 + products.quantity_deliver2 and output the sum in the 3rd data cell.
You can use builtin django template tag add for adding two.
{{products.quantity_deliver1|add:products.quantity_deliver2}}
Ref - https://docs.djangoproject.com/en/dev/ref/templates/builtins/#add

How to filter data displayed in a table in django?

I have a project where when a user enters a vehicle no, the database is filtered and a table containing that vehicle no and the information corresponding to is displayed. I further want to filter this displayed table, eg: if the user chooses to see quantity greater than 18kl, then the matching vehicle number with quantity greater than 18 is displayed. Also I want to hide the columns selected by the users as there are many columns. Can someone tell me how to do this in django, or suggest some better ways. (I am providing only the related code snippet.)
forms.py
class VehicleSearch(forms.Form):
vehicl[![enter image description here][1]][1]e_no = forms.CharField(widget=forms.TextInput(attrs={'class': 'special'}), required=False)
#filter form
class Filter(forms.Form):
capacity_grp = forms.ChoiceField(label='Show only', widget=forms.RadioSelect,
choices=[('abv', '>18 kl'), ('blw', '<18 kl')], required=False)
views.py
def search(request):
form_1 = forms.VehicleSearch()
if request.method == 'POST' and 'btnform1' in request.POST:
form_1 = forms.VehicleSearch(request.POST)
if form_1.is_valid():
vehicle_no = form_1.cleaned_data['vehicle_no']
transport = models.Transport.objects.filter(vehicle=vehicle_no)
my_dict.update({'transport': transport})
return render(request, 'search.html', my_dict)
search.html
/Vehicle form/
<form id="f1" method="POST">
{% csrf_token %}
{{form_1.as_p}}
<p style="padding: 10px;"><button class="myButton" name="btnform1">Search</button></p>
</form>
/*Table display*/
<div class="submain">
{% if transport %}
<table id="transportation">
<thead>
<th>Vehicle</th>
<th>Carrier</th>
<th>Location No</th>
<th>MCMU</th>
<th>Location</th>
<th>Customer Code</th>
<th>Zone</th>
<th>Quantity</th>
<th>RTKM</th>
<th>KL* KM</th>
<th>Amount</th>
<th>Load</th>
<th>Capacity</th>
<th>Rate</th>
<th>Cost</th>
</thead>
{% for i in transport %}
<tr class="item">
<td>{{ i.vehicle }}</td>
<td>{{ i.carrier }}</td>
<td>{{ i.location_no }}</td>
<td>{{ i.mcmu }}</td>
<td>{{ i.location }}</td>
<td>{{ i.customer_code }}</td>
<td>{{ i.zone }}</td>
<td>{{ i.quantity }}</td>
<td>{{ i.rtkm }}</td>
<td>{{ i.klkm }}</td>
<td>{{ i.amount }}</td>
<td>{{ i.load }}</td>
<td>{{ i.capacity }}</td>
<td>{{ i.rate }}</td>
<td>{{ i.cost }}</td>
</tr>
{% endfor %}
</table>
</div>
In the table display you can add a loop with the name's field, something like that:
View:
def search(request):
form_1 = forms.VehicleSearch()
if request.method == 'POST' and 'btnform1' in request.POST:
form_1 = forms.VehicleSearch(request.POST)
columns = request.POST.getlist('filter_hide_columns')
if form_1.is_valid():
vehicle_no = form_1.cleaned_data['vehicle_no']
transport = models.Transport.objects.filter(vehicle=vehicle_no)
my_dict.update({'transport': transport}, {'columns': columns})
return render(request, 'search.html', my_dict)
TemplateTag
def lookup(model, attr):
if hasattr(model, attr):
return getattr(model, attr)
else:
return None
refer https://docs.djangoproject.com/en/2.2/howto/custom-template-tags/
Template:
{% if transport %}
<table id="transportation">
<thead>
<tr>
{% for field in columns %}
<th>{{ field.name }}</th>
{% endfor %}
</tr>
</thead>
<tbody>
{% for t in transport %}
<tr>
{% for field in columns %}
<td>{{ t|lookup:field.name }}</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
Please refer https://docs.djangoproject.com/en/2.2/topics/forms/#looping-over-the-form-s-fields

How to generate PDF in Django Generic Views?

I have a template that is rendered by generic List View. I want to give a download link in front of each row of data in table. The download link will create a PDF file of respective rows data. Please tell me how to write a code for that?
Views.py
class BookingConfirmationListView(LoginRequiredMixin, generic.ListView):
model = container_booking
template_name = 'home/booking_confirmation_detail.html'
context_object_name = 'all_container'
def get_queryset(self):
return container_booking.objects.all()
Templates look like
<table class="table-striped table-hover table-bordered" width="100%">
<tr>
<th>Date</th>
<th>Source</th>
<th>Destination</th>
<th>Container</th>
<th>Commodity</th>
<th>Agreed Rate</th>
<th>Edit</th>
<th>Delete</th>
<th>Status</th>
</tr>
{% for item in all_container %}
<tr>
<td>{{ item.date }} </td>
<td>{{ item.place_of_reciept }} </td>
<td>{{ item.final_place_of_destination }} </td>
<td>{{ item.equipment_type }}{{ item.quantity }} </td>
<td>{{ item.commodity }} </td>
<td>{{ item.agreed_rate }} </td>
<td><a href="{% url 'home:cont_bk-update' item.id %}" ><i class="fas
fa-edit"></i></a></td>
<td><a href="{% url 'home:cont_bk-delete' item.id %}" ><i class="fas
fa-trash"></i></a></td>
<td>{{ item.approved }}</td>
</tr>
{% endfor %}
</table>
urls.py
url(r'^cont_bkdetail$', views.BookingConfirmationListView.as_view(),
name='cont_bk-detail'),
url(r'^cont_bk/(?P<pk>[0-9]+)/$',
views.BookingConfirmationUpdate.as_view(), name='cont_bk-update'),
url(r'^cont_bk/(?P<pk>[0-9]+)/delete/$',
views.BookingConfirmationDelete.as_view(), name='cont_bk-delete'),
I want that whenever I click download, the PDF file of that row is generated.

PyCharm says Expected }} after |default in a template

<div class="person_roles_div">
<table>
<thead></thead>
<tbody>
{% for position in person.positions %}
<tr>
<td>{{ position.provider|default:"" }} {{ position.role }}</td>
<td>{{ position.facility|default:"" }}</td>
<td>{{ position.startdate|default:"" }}</td>
<td>{{ position.enddate|default:"" }}</td>
<td>
<button id="remove_position_sk_{{ position.position_sk }}" class="position_remove_button">Remove</button>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
In the first four td tags that output a context variable and specify a default, PyCharm is highlighting the : and blank space right before and after each ""
The hovertip message is (( or {% expected. The page runs fine.
Any idea what setting I should looking at?
it's "Python template languages". See the screenshot:
Make sure it's set to "Django"

Django Template - Need to use filter()

I am kinda stuck.
Here is the situation. I have 2 for loops. One that loops through categories and the other one that loops through a match set. Here is the problem:
I need to get all the matches from that category...
Here is what I have:
{% for category in tournament.get_categories %}
<div class="line" style="margin-top: 25px; margin-bottom: 40px;"></div>
<div class="container">
<h3 class="margin-reset" id="{{ category.slug }}">{% trans "Matches schedule" %}<span> | {{ category.name }}</span></h3>
<table class="standard-table table">
<thead>
<tr>
<th>Match</th>
<th>Heure</th>
<th>Plateau</th>
<th>Équipe bleu</th>
<th>Équipe gris</th>
<th>Équipe noir</th>
<th>Résultat</th>
</tr>
</thead>
<tbody>
{% for match in tournament.match_set.filter(category=category) %}
<tr>
<td>{{ match.match_num }}</td>
<td>{{ match.time }}</td>
<td>{{ match.plateau }}</td>
<td>{{ match.blue_team.name }}</td>
<td>{{ match.grey_team.name }}</td>
<td>{{ match.black_team.name }}</td>
<td>{{ match.get_url_string }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endfor %}
As you guys probably guessed it, I get this error:
Could not parse the remainder: '(category=category)' from 'tournament.match_set.filter(category=category)'
What can I do?
Thanks,
Ara
EDIT:
Here is the solution:
The custom tag:
#register.filter
def get_matches_by_category(value, category):
return value.match_set.filter(category=category)
And the use:
{{ tournament|get_matches_by_category:category }}
I created a custom templatetag and used that filter.
It's kinda an overkill but...oh well.
What I have done in a very similar case is pass the list of categories to the template, adding them a new attribute with the matches, like:
for category in categories:
category.matches = Match.objects.filter(tournament=tournament, category=category)
It's kinda slow, but you can work it and reduce the number of queries
I would pass the categories list to the template after this