Django-filter: count data - python

Does anybody knows how can I use count based on selected value using django_filters
Error
'UserFilter' object has no attribute 'count'
My Reference link
views.py
def search(request):
user_list = Person.objects.all()
user_filter = UserFilter(request.GET, queryset=user_list)
count = user_filter.count() #this will return an error
print(count)
return render(request, 'user_list.html', {'filter': user_filter})
filters.py
from django.contrib.auth.models import User
from .models import Person
import django_filters
class UserFilter(django_filters.FilterSet):
class Meta:
model = Person
fields = ['category', 'firstname', 'lastname' ]
user_list.html
{% extends 'base.html' %}
{% block content %}
<form method="get">
{{filter.form.as_p}}
<button type="submit" >Search</button>
</form>
<table class="table table-bordered">
<thead>
<tr>
<th>Firstname</th>
<th> Lastname</th>
<th>Caegory</th>
</tr>
</thead>
<tbody>
{% for user in filter.qs %}
<tr>
<td>{{ user.firstname }}</td>
<td>{{ user.lastname }}</td>
<td>{{ user.category }}</td>
</tr>
{% empty %}
<tr>
<td colspan="5">No data</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}
I want to count all the list base from data I filtered

You'll want the count of the resulting queryset, which you can get from the filter's qs property (as you do in your template!).
Change
count = user_filter.count()
to
count = user_filter.qs.count()

You can work with the .qs attribute:
def search(request):
user_list = Person.objects.all()
user_filter = UserFilter(request.GET, queryset=user_list)
count = user_filter.qs.count()
return render(request, 'user_list.html', {'filter': user_filter})
.qs [GitHub] is a property that generates a QuerySet by filtering the original queryset by values in the fields of the FilterSet.

Related

Trying to add a form to a DetailView

I am writing a Detail View - and the form that is displayed is the particular Track that the user is adding/updating to the CD Entry (It's a CD Library application). The trick is I want to see everything else about the CD on the page as well as the form for the particular track. Having trouble figuring out how to get the form to be just the trac I am adding/updating.
Basically you can enter a CD Title,Artist, and total time of the CD into the CD model. Then the Tracks are stored in the Track Model, with their Foreign Key being the CD they are on.
While looking at a Detail View of the CD, the user can add or update a Particular track via a button. I'm trying to get the update part working.
Model Looks like this:
from django.db import models
from datetime import datetime, timedelta
class Cd(models.Model):
artist_name = models.CharField(max_length=155)
cd_title = models.CharField(max_length=155)
cd_total_time = models.TimeField(default="00:00:00")
cd_total_time_delta = models.DurationField(default=timedelta)
cd_run_time = models.TimeField(default="00:00:00",blank=True)
cd_run_time_delta = models.DurationField(default=timedelta)
cd_remaining_time = models.TimeField(default="00:00:00",blank=True)
cd_remaining_time_delta = models.DurationField(default=timedelta)
def save(self, *args, **kwargs):
super().save(*args,**kwargs)
def __str__(self):
return f"{self.artist_name} : {self.cd_title}"
class Track(models.Model):
cd_id = models.ForeignKey(Cd, on_delete=models.CASCADE,
related_name='cd_tracks',
)
track_title = models.CharField(max_length=50)
track_number = models.IntegerField()
trk_length_time = models.TimeField(null=True,default=None, blank=True)
trk_length_time_delta = models.DurationField(default=timedelta)
trk_run_time = models.TimeField(default="00:00:00",blank=True)
trk_run_time_delta = models.DurationField(default=timedelta)
trk_remaining_time = models.TimeField(default="00:00:00",blank=True)
trk_remaining_time_delta = models.DurationField(default=timedelta)
def save(self, *args, **kwargs):
super().save(*args,**kwargs)
self.cd_id.save()
def __str__(self):
return f"{self.track_title}"
The views.py snippet:
class Track_update(UpdateView):
model = Track
template_name = 'track_update.html'
fields = [ 'cd_id', 'track_title',
'track_number', 'trk_length_time'
]
success_url = "/"
class Cd_DetailView(DetailView):
model = Cd
template_name = 'cd_detail.html'
fields = ['artist_name','cd_title','cd_total_time',
'cd_run_time','cd_remaining_time'
]
class Cd_MixedView(FormMixin, DetailView):
model = Cd
template_name = 'cd_mixed_view.html'
form_class = TrackForm
def get_success_url(self):
return reverse('cd_detail {id}')
def get_context_data(self, **kwargs):
context = super(Cd_MixedView,self).get_context_data(**kwargs)
context['form'] = TrackForm(initial={
'cd_id':self.object
})
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)
The urls.py looks like
from django.urls import path
from django.contrib import admin
from .views import (
HomePageView,
Cd_Create,
Cd_Update,
Cd_DetailView,
List_Cds,
Track_Create,
Cd_MixedView,
)
urlpatterns = [
path('', HomePageView.as_view(), name = 'home'),
path('admin/', admin.site.urls),
path('cd/add/', Cd_Create.as_view(), name='cd_new'),
path('cd/update/<int:pk>', Cd_Update.as_view(), name='cd_update'),
path('cd/detail/<int:pk>', Cd_DetailView.as_view(), name='cd_detail'),
path('track/add/', Track_Create.as_view(), name='track_new'),
path('track/add/<int:pk>', Cd_MixedView.as_view(), name='cd_mixed_view'),
path('list/', List_Cds.as_view(), name='list_cds'),
]
The template looks like this:
<!-- templates/cd_mixed_view.html -->
{% extends 'base.html' %}
{% load static %}
{% block title %} CD Details{% endblock title %}
{% block content %}
<h1>CD Update Track </h1>
<p>Artist Name: {{ cd.artist_name}}
<p>Cd Title: {{ cd.cd_title }}
<p>Cd Total Time: {{ cd.cd_total_time|time:"H:i:s" }}
<p>Cd Run Time: {{ cd.cd_run_time|time:"H:i:s" }}
<p>Cd Remaining Time:
{% if cd.cd_run_time_delta > cd.cd_total_time_delta %}
(-{{ cd.cd_remaining_time|time:"H:i:s" }})
{% else %}
{{ cd.cd_remaining_time|time:"H:i:s" }}
{% endif %}
<TABLE BORDER="0" TABLE_LAYOUT="fixed" WIDTH="100%">
<TR BGCOLOR="#B0B0FF">
<TD></TD>
<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.cd_tracks.all %}
*** This is the part I am having trouble with ***
{% if tracks.id = track number that was clicked %}
{form_as_p}
{% else %}
<TR>
<TD ALIGN="Center" rowspan="1" height="33" width="33">
<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.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>
{% endfor %}
</TABLE>
</table>
{% endblock content %}
So, how do I pass the Track ID into the template, so that I can display the form for THAT track, otherwise
display the track information for all the other tracks.
Any information about how to approach this would be greatly appreciated.
Below is a picture of what the Detail Screen looks like before attempting to update the Track.
Thanks
Did you think about adding the tracking id as a slug, creating another function in views, to pass it? with an 'a' tag, and passing an href, with inside it the foreign key if the track referring to the CD. You could pass the values in the context of the view.

Django: retrieve table data in html page

I have a Django table with 3 fields.
I have a total of 4 entries and i want to visualize all of them inside a table which only displays 2 of these 3 fields.
How should i do that? i did manage to only display 1 row instead of 4, i'm struggling, someone could help?
This is the easy model to manage.
class Inc(models.Model):
id = models.AutoField(primary_key=True)
nr_sin = models.CharField(max_length=50, default=None)
nr_pol = models.CharField(max_length=50, default=None)
Have you already got the QuerySet being passed from your view to your templates?
Assuming you have, and it's in a variable called inc_list, then in your template you could do this to display the nr_sin and nr_pol fields:
{% if inc_list %}
<table>
<thead>
<tr>
<th>NR SIN</th>
<th>NR POL</th>
</tr>
</thead>
<tbody>
{% for inc in inc_list %}
<tr>
<td>{{ inc.nr_sin }}</td>
<td>{{ inc.nr_pol }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
In you view query your model to get all the entries you want to display in the table and pass them as a context variable to the templete. Later in the template you have to iterate over the list of elements and render one by one as follow:
# import your model
class SomeView(View):
def get(self, request):
elements = Inc.objects.all()
context = {'elements': elements}
return render(request, 'your_template.html', context)
render the table:
<table>
<thead>
<tr>
<th>ID</th>
<th>nr_sin</th>
</tr>
</thead>
<tbody>
{# you loop over the list and render one element at each iteration #}
{% for inc in elements %}
<tr>
<td>{{ inc.pk }}</td>
<td>{{ inc.nr_sin }}</td>
</tr>
{% endfor %}
</tbody>
</table>

How to display related objects through DetailView

I'm trying to display a product, and available brands(has product as ForeignKey) for that product through DetailView. Based on Django documentation and similar answers on stackoverflow, I tried below code but it doesn't work. Product details are rendering but names of brands are not. I've checked through django-admin, that the brands the products are present in the database.
Could someone please help.
Models.py
class Product(models.Model):
name = models.CharField(max_length=256)
price = models.IntegerField()
class Brand(models.Model):
name = models.CharField(max_length=256)
product = models.ForeignKey(Product,on_delete=models.PROTECT,related_name='Brands')
Views.py
class ProductDetailView(DetailView):
model = Product
Urls.py
path('detail/<int:pk>/',views.ProductDetailView.as_view(),name='product_detail'),
product_detail.html
<table class="table table-bordered table-hover table-secondary">
<tr>
<th class="bg-secondary th-customer-detail">Name</th>
<td>{{ product.name }}</td>
</tr>
<tr>
<th class="bg-secondary th-customer-detail">Price</th>
<td>{{ product.price }}</td>
</tr>
</table>
<br>
<ul>
{% for brand in product.brand_set.all %}
<li>{{ brand.name }}</li>
{% endfor %}
</ul>
You can do it this way
class ProductDetailView(DetailView):
model = Product
context_object_name = 'product'
def get_context_data(self,**kwargs):
context = super(ProductDetailView,self).get_context_data(**kwargs) #returns a dictionary of context
primary_key = self.kwargs.get('pk')
brands = Brand.objects.filter(product = primary_key)
new_context_objects = {'brands':brands}
context.update(new_context_objects)
return context
<table class="table table-bordered table-hover table-secondary">
<tr>
<th class="bg-secondary th-customer-detail">Name</th>
<td>{{ product.name }}</td>
</tr>
<tr>
<th class="bg-secondary th-customer-detail">Price</th>
<td>{{ product.price }}</td>
</tr>
</table>
<br>
<ul>
{% for brand in brands %}
<li>{{brand.name}}</li>
{% endfor %}
</ul>

how to sum elements of a model and return the total in a django template?

I'm new to Django and after spending a lot of time on this (and still being stuck) I thought to ask for some expert help!
In this small project, what I'm trying to achieve is a webpage that returns the total amount in GBP of a user's investments (only cash investments for now). I have created some python scripts to get the FX rates.
I'm trying to sum up all the amounts in GBP however I'm stuck! I don't know whether I should do this in the model (Cash) or in the view and how to then show it in the template(cash_list.html).
Your help would be really appreciated.
Workings below
models.py
from django.db import models
class fx_table(models.Model):
eur_to_gbp_pair = 'EUR/GBP'
aud_to_gbp_pair = 'AUD/GBP'
usd_to_gbp_pair = 'AUD/USD'
eur_to_gbp = models.FloatField(default=0)
aud_to_gbp = models.FloatField(default=0)
usd_to_gbp = models.FloatField(default=0)
date_time = models.CharField(max_length=264,unique=True,default='')
class Cash(models.Model):
reference = models.CharField(max_length=128)
amount = models.FloatField(default=0)
currency = models.CharField(max_length=128)
forms.py
from django import forms
from fx_rates_app.models import Cash
from fx_rates_app.models import Shares
class NewUserFormCash(forms.ModelForm):
class Meta():
model = Cash
fields = '__all__' #You want to be able to change all the fields
class NewUserFormShares(forms.ModelForm):
class Meta():
model = Shares
fields = '__all__'
Python script
import os
os.environ.setdefault('DJANGO_SETTINGS_MODULE','fx_rates_project.settings')
import django
django.setup()
from fx_rates_app.models import fx_table
import pandas_datareader.data as web
from datetime import datetime
os.environ["ALPHAVANTAGE_API_KEY"] = 'XXXXXXXXXX'
fx_gbp_to_eur = web.DataReader("GBP/EUR","av-forex")
eur = float(fx_gbp_to_eur[4:5].values[0][0])
fx_gbp_to_aud = web.DataReader("GBP/AUD","av-forex")
aud = float(fx_gbp_to_aud[4:5].values[0][0])
fx_gbp_to_usd = web.DataReader("GBP/USD","av-forex")
usd = float(fx_gbp_to_usd[4:5].values[0][0])
from datetime import datetime
now = datetime.now()
dt_string = now.strftime("%d/%m/%Y %H:%M:%S")
webpg1 = fx_table.objects.get_or_create(eur_to_gbp=eur,aud_to_gbp=aud,usd_to_gbp=usd,date_time=dt_string)[0]
views.py
from django.shortcuts import render
from fx_rates_app.models import fx_table
from fx_rates_app.forms import NewUserFormCash,NewUserFormShares
from django.views.generic import TemplateView,ListView
from django.urls import reverse
from fx_rates_app import forms
from fx_rates_app.models import Cash, Shares,fx_table
import datetime
class CashListView(ListView):
model = Cash
context_object_name = 'cash_details'
def get_context_data(self, **kwargs):
context = super(CashListView, self).get_context_data(**kwargs)
context.update({
'fx_list': fx_table.objects.all(),
'insert': datetime.datetime.now(),
})
return context
class SharesListView(ListView):
model = Shares
context_object_name = 'shares_details'
def get_context_data(self, **kwargs):
context = super(SharesListView, self).get_context_data(**kwargs)
context.update({
'fx_list': fx_table.objects.all(),
})
return context
def Cash(request):
form_cash = NewUserFormCash()
if request.method == "POST":
form_cash = NewUserFormCash(request.POST)
if form_cash.is_valid():
form_cash.save(commit=True)
return index(request)
else:
print('ERROR FORM INVALID')
return render(request,'fx_rates_app/cash_positions.html',{'form':form_cash})
urls.py
from django.urls import path
from fx_rates_app import views
from fx_rates_app.views import CashListView,SharesListView,FxListView
app_name = 'fx_rates_app'
urlpatterns = [
path('fx/',FxListView.as_view(), name='fx'),
path('cash_positions/',views.Cash,name='cash_positions'),
path('shares/',views.Shares,name='shares'),
path('cash_list/',CashListView.as_view(), name='cash_list'),
path('shares_list/',SharesListView.as_view(), name='shares_list'),
]
cash_list.html
{% extends 'fx_rates_app/base.html' %}
{% block body_block %}
{% load mathfilters %}
<div class="container">
<table class="table table-bordered">
<thead>
<th>Reference</th>
<th>Amount</th>
<th>Currency</th>
<th>Equivalent in GBP</th>
</thead>
{% for item in cash_details %}
{% for ele in fx_list %}
<tr>
<td> {{ item.reference }} </td>
<td> {{ item.amount|floatformat:0|intcomma }} </td>
<td> {{ item.currency }} </td>
{% if item.currency == "AUD" %}
<td>{{ item.amount|div:ele.aud_to_gbp|floatformat:0|intcomma }}</td>
{% elif item.currency == "EUR" %}
<td>{{ item.amount|div:ele.eur_to_gbp|floatformat:0|intcomma }}</td>
{% elif item.currency == "USD" %}
<td>{{ item.amount|div:ele.usd_to_gbp|floatformat:0|intcomma }}</td>
{% else %}
<td> {{ item.amount|floatformat:0|intcomma }} </td>
{% endif %}
</tr>
{% endfor %}
{% endfor %}
<tr>
<td> Total </td>
<td> </td>
<td> </td>
<td> Total in GBP here</td>
</tr>
{% endblock %}
</div>
Thanks in advance,
Alex
I think you can try like this in view:
from django.db.models import Sum, When, Case, FloatField, Value, F
class CashListView(ListView):
model = Cash
context_object_name = 'cash_details'
def get_context_data(self, **kwargs):
context = super(CashListView, self).get_context_data(**kwargs)
latest_fx = fx_table.objects.last()
queryset = context['cash_details'].annotate(amount_in_gbp=Case(
When(currency="AUD", then=F('amount')/latest_fx.aud_to_gbp),
When(currency="USD", then=F('amount')/latest_fx.usd_to_gbp),
When(currency="EUR", then=F('amount')/latest_fx.eur_to_gbp),
default=F('amount'),
output_field=FloatField()
)
)
context['cash_details'] = queryset
context['total_in_gbp'] = queryset.aggregate(sum=Sum('amount_in_gbp'))['sum']
return context
# template
{% for item in cash_details %}
<tr>
<td> {{ item.reference }} </td>
<td> {{ item.amount|floatformat:0|intcomma }} </td>
<td> {{ item.currency }} </td>
<td> {{ item.amount_in_gbp|floatformat:0|intcomma }} </td>
</tr>
{% endfor %}
Total: {{ total_in_gbp }}
I am using Conditional Expression to sum up all the values per currency.

Django: Trying to click on a link and remove an assigned client

Good morning. I am having an issue trying to remove a client from an assigned bed. I created a one-item form called "RoomUpdate" that will allow a user to add a client to a bed that is empty via a dropdown through a ModelChoiceField.
When the bed is full, it does not allow the access to the drop down, instead, I have a link that states "remove client." What I want to happen is when I click that button, it assigns the default value of None to that bed in that room.
What's tricky, at least to my new-ish to Django mind, is how I do this through multiple tables. Having looked for multiple answers and tried different things, I know I've lost track of what I'm doing so I definitely could use some help.
models.py
class Room(models.Model):
room_id = models.AutoField(primary_key=True)
room_number = models.CharField(max_length=5)
shelter_id = models.ForeignKey(Shelter)
max_occupancy = models.CharField(max_length=3)
floor_location = models.CharField(max_length=3)
def __str__(self):
return self.room_number
class Bed(models.Model):
bed_id = models.AutoField(primary_key=True)
room_id = models.ForeignKey(Room, related_name='beds')
bed_size = models.ForeignKey(BedSize)
client_assigned = models.ForeignKey(Clients, null=True, blank=True, default=None)
forms.py
class RoomUpdate(forms.ModelForm):
client_assigned = forms.ModelChoiceField(queryset=Clients.objects.all(), required=False)
#def __init__(self, *args, **kwargs):
#super(RoomUpdate, self).__init__(*args, **kwargs)
#self.fields['client_assigned'].choices.insert(0, ('','---------' ) )
class Meta:
model = Room
fields = ( 'client_assigned', )
views.py
def room_update(request, pk, template_name='shelter/room_edit.html'):
rooms = get_object_or_404(Room, pk=pk)
form = RoomUpdate(request.POST or None, instance=rooms)
beds = Bed.objects.filter(room_id=pk)
if form.is_valid():
form.save()
return redirect('/shelter/')
return render(request, template_name, {'form': form, 'rooms': rooms, 'beds':beds,})
def remove_client(request, pk):
rooms = get_object_or_404(Room, pk=pk)
bed = Bed.objects.filter(room_id=pk)
form = RoomUpdate(request.POST)
template_fail = 'clients/invalid_permissions.html'
if request.method=='POST':
if form.is_valid():
bed.objects.update(client_assigned=None)
bed.save()
else:
return redirect(request, template_fail)
return render_to_response(request, {'rooms': rooms, 'bed': bed})
template
<form action="" method="POST">
{% csrf_token %}
<div class="room box-shadow">
<h4>Room {{ rooms.room_number }}</h4>
<table>
{% for i in rooms.beds.all %}
<tr>
<td>Bed ID: </td>
<td>{{i.bed_id }}</td>
</tr>
<tr>
<td>Bed Size: </td>
<td>{{i.bed_size }}</td>
</tr>
<tr>
<td valign="top">Client: </td>
<td>
{% if i.client_assigned %}
{{ i.client_assigned }}
<br \>
Remove Client
{% else %}
{{ form.client_assigned }}
{% endif %}
</td>
</tr>
<tr>
<td colspan="2">
<hr class="style-two" />
</td>
</tr>
{% endfor %}
<tr>
<td><input type="submit" value="Submit" /></td>
<td></td>
</tr>
</table>
</div>
</form>
I've been playing around with this a bit and making some sort of progress. If I change the url from the same as the edit, I get it to work in that it deletes from the table and redirects the user to a new page.
I would prefer it not redirect the user to a new page, but rather, update the page that's there.
Thoughts?
The new view looks like this:
def remove_client(request, pk, template_name='shelter/test.html'):
bed = Bed.objects.filter(bed_id=pk).update(client_assigned=None)
return render(request, template_name, { 'bed':bed })
Further diving into this, I found a solution I rather like and actually works in a way I wanted but couldn't figure out. Instead of focusing on the room, I realized that I needed to focus on the smaller container -- the bed -- and since it can move around, it would be the better choice.
Currently, this functionality allows me to move beds to different rooms, remove clients by selecting the '----' selector, and allows me to add clients.
So here is the answer I came up with:
forms.py
class RoomUpdate(forms.ModelForm):
bed_id = forms.CharField()
room_id = forms.ModelChoiceField(queryset=Room.objects.all())
bed_size = forms.ModelChoiceField(queryset=BedSize.objects.all(), required=False)
client_assigned = forms.ModelChoiceField(queryset=Clients.objects.all(), required=False)
class Meta:
model = Bed
fields = ('bed_id', 'client_assigned', 'room_id', 'bed_size' )
views.py
def room_update(request, pk, template_name='shelter/room_edit.html'):
beds = get_object_or_404(Bed,pk=pk)
form = RoomUpdate(request.POST or None, instance=beds)
if form.is_valid():
form.save()
return redirect('/shelter/')
return render(request, template_name, {'form': form, 'beds':beds,})
room_edit.html
<form action="" method="POST">{% csrf_token %}
<div class="room box-shadow">
<h4>Room </h4>
<table>
<tr>
<td>Room: </td>
<td>{{ form.room_id }}</td>
</tr>
<tr>
<td>Bed ID: </td>
<td>{{ form.bed_id }}</td>
</tr>
<tr>
<td>Bed Size: </td>
<td>{{ form.bed_size }}</td>
</tr>
<tr>
<td valign="top">Client: </td>
<td>{{ form.client_assigned }}</td>
</tr>
<tr>
<td colspan="2"><hr class="style-two" /></td>
</tr>
<tr>
<td><input type="submit" value="Submit" /></td>
<td></td>
</tr>
</table>
</div>
</form>

Categories

Resources