django for loop in a .html template page (newbie) - django

The thing I really hate when learning a new language / framework is how ignorant I feel when I get stuck on a seemingly easy to solve issue.
I have a django for loop inside a html page but for some reason it is not working. I have missed something and cannot fix the issue on my own, so I turn to StackOverflow to help me.
This is my model I am running my query on models.py:
class RIAchievement(models.Model):
riAchievementID = models.AutoField(primary_key=True, db_column="RIAchievementID")
userLanguageVersionID = models.ForeignKey(UserLanguageVersion, db_column="UserLanguageVersionID")
typeAchievementID = models.ForeignKey(TypeAchievement, db_column="TypeAchievementID")
riAchievementTypeUserDescription = models.CharField(max_length=255, blank=True, null=True, db_column="RIAchievementTypeUserDescription")
riAchievementDescription = models.TextField(max_length=2000, db_column="RIAchievementDescription")
auth_user_id = models.ForeignKey(auth_user, db_column="auth_user_id")
class Meta:
db_table="RIAchievement"
This is where my models.py file is located in my project: GlobalXpy\app_data\models.py
This is the code within my views.py file:
from django.shortcuts import render_to_response
from GlobalXpy.app_data.models import RIAchievement
def index(request):
ri_achievement = RIAchievement.objects.all()
get_template = loader.get_template('ri_achievement.html')
return render_to_response(get_template)
This is the for loop that is inside my template file (ri_achievement.html):
{% for e in ri_achievement %}
<td> Preview Edit Duplicate Delete </td>
<td> FlagPath </td>
<td> AchievementType / RIAchievementTypeUserDescription </td>
<td> {{ e.riAchievementDescription }} </td>
{% endfor %}
Any assistance would be appreciated.

from django.shortcuts import render
from GlobalXpy.app_data.models import RIAchievement
def index(request):
ri_achievement = RIAchievement.objects.all()
return render(request, 'ri_achievement.html',{'ri_achievement': ri_achievement})
In your template:
{% if ri_achievement %}
There are {{ ri_achievement|length }} records:
{% for e in ri_achievement %}
<td> Preview Edit Duplicate Delete </td>
<td> FlagPath </td>
<td> AchievementType / RIAchievementTypeUserDescription </td>
<td> {{ e.riAchievementDescription }} </td>
{% endfor %}
{% else %}
There are no records in the system
{% endif %}

You forgot to pass the variable.
return render_to_response(get_template, {'ri_achievement': ri_achievement})

Related

Django templates - how to run a method on a variable?

I'm new to Django, so maybe my attempts are pure heresy ;)
I'm trying to make a view which lists disponible conference rooms with its attributs, availability included.
I have 2 models: Room and Reservation. I'd like in the view to have a column saying if the room is available the day the page is displayed.
My models.py:
from django.utils import timezone
from django.db import models
class Room(models.Model):
name = models.CharField(max_length=255, unique=True)
capacity = models.IntegerField()
projector = models.BooleanField()
class Reservation(models.Model):
room = models.ForeignKey(Room, on_delete=models.CASCADE)
date = models.DateField()
comment = models.CharField(max_length=255)
class Meta:
unique_together = ('room', 'date',)
my views.py:
class ShowRoom(View):
def get(self, request):
rooms = Room.objects.all()
time_now = timezone.now().date()
context = {
'rooms': rooms,
'time_now': time_now
}
return render(request, 'rooms/list_rooms.html', context)
My template:
{% extends 'rooms/base.html' %}
{% block block_title %} Home {% endblock %}
{% block block_content %}
{% if rooms %}
<table class="table">
<thead>
<td> Name </td>
<td> Capacity </td>
<td> Available </td>
<td> Projector </td>
</thead>
<tbody>
{% for room in rooms|dictsort:'capacity' %}
<tr>
<td> {{ room.name }} </td>
<td> {{ room.capacity }} </td>
<td> Available? </td>
<td> {{ room.projector|yesno:'yes,no' }} </td>
</tbody>
{% endfor %}
</table>
{% else %}
<h1> You have no registered rooms yet. </h1>
{% endif %}
{% endblock %}
Everything works fine, I need just to replace this <td> Available? </td> line with a code, which would display "free" or "occupied" according to existing room reservations.
I've found out that maybe I should write a custom filter.
Here is my filter:
from django import template
from rooms.models import Room, Reservation
register = template.Library()
#register.filter
def check_reservation(queryset, now):
return queryset.filter(date=now)
(I wanted first to make it working, and after make it display this "free" or "occupied".)
I've added to the template {% load my_extras %} and replaced the line I want to change with
<td> {{ room.reservation_set.all|check_reservation:'time_now' }} </td>
The output is:
ValidationError at /room/ ["'time_now' value has an invalid date
format. It must be in YYYY-MM-DD format."]
Before adding the filter, I was trying this solution in the shell and it was working.
I don't know if there is something wrong with the filter, or I try to approach the issue from wrong side.
Thanks in advance for any tips.
Try adding another field to the the Room class:
occupied = model.BooleanField(default=False)
In the views you can check the date associated with the reservation and today's date.
if reservation.date == time_now:
room.occupied = true
You can then filter with rooms that are available and which are not.
rooms_occupied = room.objects.filter(occupied=True)
rooms_available = room.object.filter(occupied=False)
In the template:
{% if rooms_occupied %}
Available
{% endif %}

Display Django model data to table in HTML

I have two Django models that record time. Model one records time during the morning and Model two records time during the evening. I want to present both of these times along with the difference between the times within an HTML table but am confused about how to do it. I am new to Django and would really appreciate some advice.
This is what I have so far:
models.py:
class Alltime(models.Model):
id= models.ForeignKey(User, on_delete = models.CASCADE)
mtime = models.DateTimeField()
etime = models.DateTimeField()
views.py:
def panel(request):
time_data = User.objects.filter(pk__gt=1) #I need all data except for the default Super User account
get_time = Alltime.objects.all()
return render(request, 'users/interface.html', {'data': time_data, "get_time": get_time})
panel.html:
<form>
{% csrf_token %}
<table>
<tr>
<th>Name</th>
<th>Morning timeE</th>
<th>Evening time</th>
<th>Difference in hours</th>
</tr>
{% for data in data %}
<tr>
<td>{{data.username}}</td>
{% endfor %}
{% if get_time %}
{% for m in get_time %}
<td>{{m.mtime}}</td>
<td>{{m.etime}}</td>
{% endfor %}
{% else %}
<td> Not available </td>
{% endif %}
</tr>
</table>
</form>
How can I get the difference between the times and place them within the HTML table?
If I understand correctly what you want to do, then you can/need to structure your data differently. An easy way is to prepare the data in your view:
def panel(request):
time_data = User.objects.filter(pk__gt=1)
time_table=[]
for user in time_data:
morning_time = Morning.objects.filter(user=user)
evening_time = Evening.objects.filter(user=user)
diff = morning_time - evening_time
time_table.append((user.name, morning_time, evening_time, diff))
return render(request, 'users/interface.html', {'data': time_table})
And in the template:
<table>
<tr>
<th>Name</th>
<th>Morning timeE</th>
<th>Evening time</th>
<th>Difference in hours</th>
</tr>
{% for line in data %}
<tr>
<td>{{line.0}}</td>
<td>{{line.1}}</td>
<td>{{line.2}}</td>
<td>{{line.3}}</td>
</tr>
{% endfor %}
</table>
You need to add the handling of not existing data in the view code.
Some remarks:
The whole thing does not really make sense to me. I guess you will need to filter for dates too. But you should get the idea from this. And why is it in a form?
You can add a property to the Alltime model that returns the difference between the morning and evening time
#property
def diff(self):
return self.etime - self.mtime
Then in your template you can use this property
{% for m in get_time %}
<td>{{m.mtime}}</td>
<td>{{m.etime}}</td>
<td>{{m.diff}}</td>
{% endfor %}

Django - How to delete a object directly from a button in a table

(sorry for my bad english)
I need to delete an object, but directly from a list of the objects that y have in my template.
I have a work orders, that have spare parts but i don't know how to create the deleteview for the spare parts using only a buton in the detailview of the work order. The idea is that the user make click in the Delete button.
This is the model of the Spare Parts
class OrderSparePart(models.Model):
# Relations
workorder = models.ForeignKey(
WorkOrder,
verbose_name=_('order'),
)
# Attributes - Mandatory
spare_part = models.CharField(
max_length=80,
verbose_name=_('spare part'),
)
# Attributes - Optional
price = models.DecimalField(
max_digits=6,
decimal_places=2,
null=True,
blank=True,
verbose_name=_('price'),
)
# Object Manager
# Custom Properties
# Methods
def get_absolute_url(self):
return reverse('work_orders:detail', kwargs={'order_id': self.workorder.id})
# Meta and String
class Meta:
verbose_name = _("order spare part")
verbose_name_plural = _("order spare parts")
This is where is showed in the template
{% if spare_parts %}
<table class="table">
<thead>
<tr>
<th>{% trans "Spare Part" %}</th>
<th>{% trans "Price" %}</th>
<th>{% trans "Delete" %}</th>
</tr>
</thead>
<tbody>
{% for part in spare_parts %}
<tr>
<td><i class="fa fa-gear"></i> {{ part.spare_part }}</td>
{% if part.price %}
<td>$ {{ part.price }}</td>
{% else %}
<td></td>
{% endif %}
<td><i class="fa fa-trash"></i></td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<p>NO HAY REPUESTOS ASENTADOS AÚN</p>
{% endif %}
The the idea is use the to delete the spare part.
how i have to make the deleteview and the link to this???
Thanks!
here in fa fa-thrash pass the id and the URL as I did it:-
{% if spare_parts %}
<table class="table">
<thead>
<tr>
<th>{% trans "Spare Part" %}</th>
<th>{% trans "Price" %}</th>
<th>{% trans "Delete" %}</th>
</tr>
</thead>
<tbody>
{% for part in spare_parts %}
<tr>
<td><i class="fa fa-gear"></i> {{ part.spare_part }}</td>
{% if part.price %}
<td>$ {{ part.price }}</td>
{% else %}
<td></td>
{% endif %}
<td></i></td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<p>NO HAY REPUESTOS ASENTADOS AÚN</p>
{% endif %}
ur url would be sonething like that:
url(r'^delete/(?P<part_id>[0-9]+)/$', view.function, name='delete_view'),
in ur view:
def function(request,part_id =None):
object = YourModel.objects.get(id=part_id)
object.delete()
return render(request,'ur template where you want to redirect')
In your html template inside for loop use the form tag inside <td> to create delete button as below (css class will work if you are using bootstrap3):
<form action="{% url 'delete_view' pk=part.pk %}" method="POST">
{% csrf_token %}
<input class="btn btn-default btn-danger" type="submit" value="Delete"/>
</form>
add urlpattern in urls.py
url(r'^delete-entry/(?P<pk>\d+)/$', views.DeleteView.as_view(), name='delete_view'),
delete view will be like below in views.py
class DeleteView(SuccessMessageMixin, DeleteView):
model = OrderSparePart
success_url = '/'
success_message = "deleted..."
def delete(self, request, *args, **kwargs):
self.object = self.get_object()
name = self.object.name
request.session['name'] = name # name will be change according to your need
message = request.session['name'] + ' deleted successfully'
messages.success(self.request, message)
return super(DeleteView, self).delete(request, *args, **kwargs)
Note: import necessary imports shown in links or you need not to worry if you are using IDE such as pyCharm it will prompt you which import to make.
My solutions works best for django 4.0.3 and is the combination of gahan and Abi waqas answers. Use this one if you are using django 3 or above
Add the following to views.py
def delete_object_function(request, id):
# OrderSparePart is the Model of which the object is present
ob = OrderSparePart.objects.get(id=id)
ob.delete()
return redirect('page-delete.html') # for best results, redirect to the same page from where delete function is called
Add the following to urls.py
path('page-delete/<int:id>', views.delete_object_function, name='delete_object'),
Add the following code to the django template from where the delete function is to be called.
Let's say page-delete.html
<form action="{% url 'delete_object' id=part.id %}" method="post">
{% csrf_token %}
<button class="btn btn-danger" type="submit" ><i class="fa fa-trash"></i></button>
</form>
This works as I've used this solution in my own code.

Form to display checkbox with title without the ability to edit title

I've been playing around with Django forms and it's a bit of a headache. I came to a point where I can display my form properly but I only want to edit part of it's data, not all of them.
Specifically: I have a Product model that has a title and a featured bool field. I want a form that displays all the products names with a tickbox next to it. The user is able to edit the featured property of each Product on the same form, but only that! My problem is that with the current setup, the displayed title is also an input field, not a simple text. If I change the template to display {{ productForm.title.value }} instead of {{ productForm.title }} it displays it as a text but the form failes the validation (It requires the title to have a value, since it cannot be null).
Model is plain simple, title and featured fields with CharField and BooleanField types. Validation branch is also not taken care of in the sample but "is_valid()" returns false.
views.py
def featured_product(request):
FeaturedProductFormSet = modelformset_factory(Product, fields=('title', 'featured'))
if request.method == "POST":
productForms = FeaturedProductFormSet(request.POST)
if productForms.is_valid():
productForms.save()
return redirect('/admin/')
else:
productForms = FeaturedProductFormSet()
return render_to_response(
'vetco_app/featured_products.html',
{
'productForms': productForms,
},
context_instance=RequestContext(request)
)
featured_products.html
<form action="" method="post">
<table>
<thead>
<th>
Termék neve
</th>
<th>
Kiemelt
</th>
</thead>
<tbody>
{% for productForm in productForms %}
{% if not forloop.last %}
<tr>
<td>
{{ productForm.id }}
{{ productForm.title }}
</td>
<td>
{{ productForm.featured }}
</td>
</tr>
{% endif %}
{% endfor %}
</tbody>
</table>
<p>
{{ productForms.management_form }}
{% csrf_token %}
<button type="submit" name="action" value="Save">Save</button>
</p>
How to make it display only the text of the title without the need to validate it?
Simply provide context:
from django.template import RequestContext
context = RequestContext(request, {"your_model":your_model")
now in templates just write:
{{ your_model.some_attribute }}

accessing foreignKey inside the template

well it's quiet simple.
2 models with ManyToMany relation:
class Artist(models.Model):
name = models.CharField(max_length=100, unique=True)
slug = models.SlugField(max_length=100, unique=True,
help_text='Uniq value for artist page URL, created from name')
birth_name = models.CharField(max_length=100, blank=True)
class Song(models.Model):
title = models.CharField(max_length=255)
slug = models.SlugField(max_length=255, unique=True,
help_text='Unique value for product page URL, create from name.')
youtube_link = models.URLField(blank=False)
artists = models.ManyToManyField(Artist)
my view suppose to display latest 5 songs:
def songs(request, template_name="artists/songs.html"):
song_list = Song.objects.all().order_by('-created_at')[:5]
return render_to_response(template_name, locals(),
context_instance=RequestContext(request))
and the problem is in the template... i want to display the artist name
but just dont realy know how to do it, i tried:
{% for song in song_list %}
{{ artists__name }} - {{ song.title }}
{% endfor %}
would appreciate any help !
Try changing your template code to:
{% for song in song_list %}
{% for artist in song.artists.all %}
{{ artist.name }} - {{ song.title }}
{% endfor %}
{% endfor %}
artists is another type of manager, so you have to iterate through artists.all and print the name attribute of each element.
Well, I worked on above solution of Mr #Dominic Rodger, but because am using Django version 3.2 it did not worked for me. Therefore, the problem may remain the same but according to how Django version changes, the way to solve them sometimes become different. If you're using Django 3.x use below solution.
In views.py
def songs(request):
song_list = Song.objects.all().order_by('-created_at')[:5]
song_list = {'song_list':song_list}
return render(request, 'artists/songs.html', song_list)
In your HTML Template use code below
<div class="table-responsive">
<table class="table table-bordered" id="dataTable" width="100%" cellspacing="0">
<thead>
<tr>
<th>Artist - Song Title</th>
</tr>
</thead>
<tbody>
{% for song in song_list %}
</tr>
<td>{{ song.artist.name }} - {{ song.title }}</td>
<tr>
{% endfor %}
</tbody>
</table>
In urls.py
path('songs/', views.songs, name='songs'),
If you're running source code from localhost, then type on your browser http://127.0.0.1:8000/songs/
Thank you ....