Affect total sum with start date and end date - django

My views:
class CentreRevenue(ListAPIView):
permission_classes = [IsAuthenticated, ]
pagination_class = CustomPagination
serializer_class = serializers.CentreRevenueSerializer
def get_queryset(self):
self.pagination_class.page_size = page_size
id = self.request.query_params.get("id")
start_date = self.request.query_params.get("start_date")
end_date = self.request.query_params.get("end_date")
data = center_models.Centers.objects.filter(center_type__in=['collection_center', 'direct_client'], id__isnull=False)
if id:
data = data.filter(id=id)
# if start_date and end_date:
# data = data.filter(created_at__date__range=[start_date, end_date])
return data
#Serializer
class CentreRevenueSerializer(serializers.BaseSerializer):
class Meta:
model = package_models.CollectionCenterLedger
def to_representation(self, instance):
tbc = booking_models.Booking.objects.filter(center=instance, center__isnull=False).values_list('id').count()
amount = sum(
package_models.CollectionCenterLedger.objects.filter(
package__isnull=False,
center=instance,
ledger_type='debit' if instance.type == 'prepaid' else 'credit'
).values_list('amount', flat=True)
)
remove_test_billing_client_billing = sum(
package_models.CollectionCenterLedger.objects.filter(
package__isnull=False,
ledger_type='credit' if instance.type == 'prepaid' else 'debit',
center=instance,
).values_list('amount', flat=True)
)
add_test_billing = sum(
package_models.CollectionCenterLedger.objects.filter(
package__isnull=False,
ledger_type='debit' if instance.type == 'prepaid' else 'credit',center=instance
).values_list('rcl_share', flat=True)
)
remove_test_billing = sum(
package_models.CollectionCenterLedger.objects.filter(
package__isnull=False,
ledger_type='credit' if instance.type == 'prepaid' else 'debit',
center=instance
).values_list('rcl_share', flat=True)
)
rcl_amount = add_test_billing - remove_test_billing
amount = amount - remove_test_billing_client_billing
return{
'ccdc_name':instance.name,
'sales_person':instance.sales_manager.user.username if instance.sales_manager else None,
'centre_type':instance.center_type,
'total_booking_count':tbc,
# 'total_revenue':sum([i for i in total_rev if i is not None]),
'total_revenue':amount,
'rcl_share':rcl_amount
}
Here i am calculating total_booking_count, total_revenue and rcl_share. I want to filter these data with start_date and end_date and accordingly these calculation will affect. Suppose if i selected date range 5 days then it will only show calculation of those 5 days. This is last thing i want to do. Is it possible to apply filter in serializer itself? Any help would be appreciated. Thank you !!

Related

Django: django-admin-lightweight-date-hierarchy to show today objects

I'm trying to use this django package:
https://github.com/hakib/django-admin-lightweight-date-hierarchy
to filter the objects by created dates.
But now I want to display today's created objects by default and if no date is selected. Otherwise and after selecting any date this should display the objects for the selected date.
class Test(models.Model):
full_name = models.CharField(max_length=200)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
deleted_at = models.DateTimeField(null=True, blank=True)
#admin.register(Test)
class MyModelAdmin(admin.ModelAdmin):
date_hierarchy = 'created_at'
date_hierarchy_drilldown = False
list_filter = (
RangeBasedDateHierarchyListFilter,
)
def get_queryset(self, request):
qs = super(ShareAdmin, self).get_queryset(request)
if request.user.is_superuser:
return qs
return qs.filter(owner=request.user)
def get_date_hierarchy_drilldown(self, year_lookup, month_lookup):
"""Drill-down only on past dates."""
today = timezone.now().date()
if year_lookup is None and month_lookup is None:
# Past 3 years.
return (
datetime.date(y, 1, 1)
for y in range(today.year - 2, today.year + 1)
)
elif year_lookup is not None and month_lookup is None:
# Past months of selected year.
this_month = today.replace(day=1)
return (
month for month in (
datetime.date(int(year_lookup), month, 1)
for month in range(1, 13)
) if month <= this_month
)
elif year_lookup is not None and month_lookup is not None:
# Past days of selected month.
days_in_month = calendar.monthrange(year_lookup, month_lookup)[1]
return (
day for day in (
datetime.date(year_lookup, month_lookup, i + 1)
for i in range(days_in_month)
) if day <= today
)

Dynamic queryset filtering with multiple query parameters

I have the following view I have implemented to filter transactions depending on a certain query provided. Is there a way I could filter dynamically depending on what query is provided, for example one would want to only query year and month only or even filter using one query. The rest of the query values will end up having a None value an should not be included in the filter.
class ReportTransactionsFilterAPIView(APIView):
def get(self, request, format=None):
year = self.request.GET.get('year')
month = self.request.GET.get('month')
subcounty = self.request.GET.get('subcounty')
ward = self.request.GET.get('ward')
fromDate = self.request.GET.get('fromDate')
toDate = self.request.GET.get('toDate')
qs = LiquorReceiptTrack.objects.all()
qs = LiquorReceiptTrack.objects.filter(
Q(date_recieved__range=[fromDate,toDate])|
Q(date_recieved__year=year)|
Q(date_recieved__month=month)|
Q(sub_county__iexact=subcounty)|
Q(ward__iexact=ward)
)
You can use django-filter for your solution. Also for more information you can visit https://www.django-rest-framework.org/api-guide/filtering/
Just use if, why Q do you use here?:
year = self.request.GET.get('year')
month = self.request.GET.get('month')
subcounty = self.request.GET.get('subcounty')
ward = self.request.GET.get('ward')
fromDate = self.request.GET.get('fromDate')
toDate = self.request.GET.get('toDate')
qs = LiquorReceiptTrack.objects.all()
if year:
qs = qs.filter(date_recieved__year=year)
if month:
qs = qs.filter(date_recieved__month=month)
...
Went over the django-filter documentation and refactored the list view:
class TransactionFilter(django_filters.FilterSet):
date_range = DateFromToRangeFilter()
month = django_filters.NumberFilter(field_name='date_recieved', lookup_expr='month')
year = django_filters.NumberFilter(field_name='date_recieved', lookup_expr='year')
date = django_filters.DateFilter(field_name='date_recieved', lookup_expr='exact')
sub_county = django_filters.CharFilter(lookup_expr='icontains')
ward = django_filters.CharFilter(lookup_expr='icontains')
class Meta:
model = LiquorReceiptTrack
fields = ['date','month','year','date_range','sub_county','ward']
class ReportTransactionsFilterAPIView(generics.ListAPIView):
queryset = LiquorReceiptTrack.objects.all()
serializer_class = ReceiptDetailSerializer
filter_backends = (filters.DjangoFilterBackend,)
filterset_class = TransactionFilter

how to automatically generate a csv file when a user press the search button

i have a class base view which i want to automatically download a csv file but dont seem to know what am doing. here is code
Model.py
class Pv(models.Model):
accounts =(
('Sub CF','Sub CF'),
('Special','Special'),
('Directors','Directors'),
('Operations','Operations'),
('LSGDP','LSGDP'),
('DWAP','DWAP'),
('Capacity(USD)','Capacity(USD)')
)
acc =(
('Yes','Yes'),
('No', 'No')
)
source =(
('GOG','GOG'),
('Others', 'Others')
)
pv =(
('General','General'),
('Honorarium','Honorarium')
)
center=(
('Cost Center 1','Cost Center 1'),
('Cost Center 2','Cost Center 2'),
('Cost Center 3','Cost Center 3'),
('Cost Center 4','Cost Center 4'),
('Cost Center 5','Cost Center 5')
)
stat =(
('Completed','Completed'),
('Returned','Returned'),
('Cancelled','Cancelled')
)
IA_System_Code = models.AutoField(primary_key = True)
IA_code = models.CharField(max_length = 150)
Date_recieved = models.DateField()
Pv_reference = models.CharField(unique = True, max_length = 120)
Source_of_Funding = models.CharField(max_length=50, choices = source)
Cost_center = models.CharField(max_length=50, choices = center)
Payee = models.CharField(max_length=500)
Description = models.CharField(max_length = 500)
Account_code = models.CharField(max_length=350)
Gross_amount = models.DecimalField(max_digits=19, decimal_places=2)
Withholding_tax = models.DecimalField(max_digits=19, decimal_places=2)
Net_amount = models.DecimalField(max_digits=19, decimal_places=2)
Status = models.CharField(max_length = 60, choices = stat )
Remarks =models.CharField(max_length = 500, blank = True)
Acc_Impress = models.CharField(max_length = 350,choices=acc)
Date_returned =models.DateField(null=True,blank = True)
Type_of_accounts= models.CharField(max_length = 100, choices = accounts)
Type_of_pv = models.CharField(max_length = 20, choices = pv)
returned_to_chest = models.DecimalField(max_digits=19, decimal_places=2)
created = models.DateTimeField(null=True)
created_by = models.ForeignKey('auth.User', blank=True,\null=True,\
default=None,on_delete=models.CASCADE,\
related_name='create')
modified = models.DateTimeField(null=True)
modified_by = models.ForeignKey('auth.User', blank=True,null=True,\
default=None ,on_delete=models.CASCADE,\
related_name='modified')
class Meta():
ordering = ["IA_System_Code"]
def __str__(self):
return self.Description
def save(self, *args, **kwargs):
user = get_current_user()
if user and not user.pk:
user = None
if not self.pk:
self.created_by = user
self.created = datetime.now()
else:
self.modified_by = user
self.modified = datetime.now()
super(Pv, self).save(*args, **kwargs)
view.py
class ReportView(ListView):
model = Pv # model been used
template_name = 'pv/report.html'
context_object_name = 'all_search_results'
def get_queryset(self):
result = super(ReportView, self).get_queryset()
query = self.request.GET.get('search') # get the search critirial from the template
today = datetime.datetime.now()
if query:
if query == "Withholding":
postresult = Pv.objects.filter(Withholding_tax__gt\
=0.00,Date_recieved__year=today.year)
elif query =="Non-Withholding":
postresult = Pv.objects.filter(Withholding_tax__lte\
=0.00, Date_recieved__year=today.year)
elif query =="Accountable-Impress":
postresult = Pv.objects.filter(Acc_Impress__exact\
='Yes',Date_recieved__year=today.year)
elif query =="Non-Accountable-Impress":
postresult = Pv.objects.filter(Acc_Impress__exact\
= 'No',Date_recieved__year=today.year)
else:
postresult = Pv.objects.all()
result = postresult
response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename="report.csv"'
today = datetime.datetime.now()
data = result
pvlist =data.filter(Date_recieved__year=today.year)\
.order_by('IA_System_Code')
writer = csv.writer(response)
writer.writerow(['IA_System_Code','IA_code',\
'Date_recieved','Pv_reference',\
'Source_of_Funding','Cost_center','Payee',\
'Description','Account_code',\
'Gross_amount','Withholding_tax',\
'Net_amount','Status','Acc_Impress',\
'Date_returned','Type_of_accounts','Type_of_pv'])
for pv in pvlist :
writer.writerow([pv.IA_System_Code,pv.IA_code,pv.Date_recieved,\
pv.Pv_reference,pv.Source_of_Funding,\
pv.Cost_center, pv.Payee,pv.Description,\
pv.Account_code,pv.Gross_amount,
pv.Withholding_tax,pv.Net_amount,\
pv.Status,pv.Acc_Impress,\
pv.Date_returned,pv.Type_of_accounts,\
pv.Type_of_pv])
else:
result = None
return result
looks like i dont know what am doing. obviously my code is wrong . can any one here me out .
what i want to achieve is the moment the person finish filtering , the csv file should generate automatically.
Edited
here is my new code
view.py
this is my coded my new code.
class ReportView(ListView):
model = Pv # model been used
template_name = 'pv/report.html'
context_object_name = 'all_search_results'
def get_queryset(self):
result = super(ReportView, self).get_queryset()
query = self.request.GET.get('search')
today = datetime.datetime.now()
if query:
if query == "Withholding":
postresult = Pv.objects.filter(Withholding_tax__gt\
=0.00,Date_recieved__year=today.year)
elif query =="Non-Withholding":
postresult = Pv.objects.filter(Withholding_tax__lte =0.00,\
Date_recieved__year=today.year)
elif query =="Accountable-Impress":
postresult = Pv.objects.filter(Acc_Impress__exact\
='Yes',Date_recieved__year=today.year)
elif query =="Non-Accountable-Impress":
postresult = Pv.objects.filter(Acc_Impress__exact =\
'No',Date_recieved__year=today.year)
else:
postresult = Pv.objects.all()
result = postresult
else:
result = None
return result
def get(self, request, *args, **kwargs):
response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename="report.csv"'
writer = csv.writer(response)
writer.writerow(['IA_System_Code','IA_code',\
'Date_recieved','Pv_reference',
'Source_of_Funding','Cost_center','Payee',\
'Description','Account_code',\
'Gross_amount','Withholding_tax',\
'Net_amount','Status','Acc_Impress',\
'Date_returned','Type_of_accounts',\
'Type_of_pv','returned_to_chest'])
pvs = self.get_queryset()
for pv in pvs:
writer.writerow([pv.IA_System_Code,pv.IA_code,\
pv.Date_recieved,pv.Pv_reference,\
pv.Source_of_Funding,pv.Cost_center,\
pv.Payee,pv.Description,pv.Account_code,\
pv.Gross_amount,pv.Withholding_tax,\
pv.Net_amount,pv.Status,pv.Acc_Impress,\
pv.Date_returned,pv.Type_of_accounts,\
pv.Type_of_pv,pv.returned_to_chest])
return response
the edited version of the code works but it does not even open the template for u to filter, it just run the get function . is there a way the code can allow you to filter before it runs the get function.
i seem to not know what am doing. any help will do thank u
Probably you need to return your model queryset (that is PV.objects.filter() or something) in get_queryset method
And then render the result in get method:
def get(self, request, *args, **kwargs):
response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = 'attachment;\
filename="somefilename.csv"'
writer = csv.writer(response)
for item in self.get_queryset():
writer.writerow([item.IA_System_Code, item.IA_code...])
return response
Haven't tested the code, but I hope it helps
Edited
this is my coded my new code.
class ReportView(ListView):
model = Pv # model been used
template_name = 'pv/report.html'
context_object_name = 'all_search_results'
def get_queryset(self):
result = super(ReportView, self).get_queryset()
query = self.request.GET.get('search')
today = datetime.datetime.now()
if query:
if query == "Withholding":
postresult = Pv.objects.filter(Withholding_tax__gt\
=0.00,Date_recieved__year=today.year)
elif query =="Non-Withholding":
postresult = Pv.objects.filter(Withholding_tax__lte =0.00,\
Date_recieved__year=today.year)
elif query =="Accountable-Impress":
postresult = Pv.objects.filter(Acc_Impress__exact\
='Yes',Date_recieved__year=today.year)
elif query =="Non-Accountable-Impress":
postresult = Pv.objects.filter(Acc_Impress__exact =\
'No',Date_recieved__year=today.year)
else:
postresult = Pv.objects.all()
result = postresult
else:
result = None
return result
def get(self, request, *args, **kwargs):
response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename="report.csv"'
writer = csv.writer(response)
writer.writerow(['IA_System_Code','IA_code',\
'Date_recieved','Pv_reference',
'Source_of_Funding','Cost_center','Payee',\
'Description','Account_code',\
'Gross_amount','Withholding_tax',\
'Net_amount','Status','Acc_Impress',\
'Date_returned','Type_of_accounts',\
'Type_of_pv','returned_to_chest'])
pvs = self.get_queryset()
for pv in pvs:
writer.writerow([pv.IA_System_Code,pv.IA_code,\
pv.Date_recieved,pv.Pv_reference,\
pv.Source_of_Funding,pv.Cost_center,\
pv.Payee,pv.Description,pv.Account_code,\
pv.Gross_amount,pv.Withholding_tax,\
pv.Net_amount,pv.Status,pv.Acc_Impress,\
pv.Date_returned,pv.Type_of_accounts,\
pv.Type_of_pv,pv.returned_to_chest])
return response
the code works but it does not even open the template for u to filter, it just run the get function . is there a way the code can allow you to filter before it runs the get function.

DateTime filter in django rest

I am creating an api which returns weather data of particular city for n number of days given.(api definition: weatherdata/city_name/ndays/).I have problem sorting out data for ndays.
I sorted out the city name using simple icontains. similarly I want to sort out for ndays. previous ndays data needs to be shown. example: suppose today is 2019-08-29, on providing ndays to be 6, weather data of particular city has to be provided from 2019-08-24 to 2019-08-26.
views.py
class weatherDetail(APIView):
def get_object(self, city_name, ndays):
try:
x = weatherdata.objects.filter(city_name__icontains=city_name)
now = datetime.datetime.now()
fromdate = now - timedelta(days=ndays)
y =
return x
except Snippet.DoesNotExist:
raise Http404
def get(self,*args,**kwargs):
city_name = kwargs['city_name']
snippet = self.get_object(city_name,ndays)
serializer = weatherdataserializer(snippet,many =True)
return Response(serializer.data)
models.py
class weatherdata(models.Model):
city_name = models.CharField(max_length = 80)
city_id = models.IntegerField(default=0)
latitude = models.FloatField(null=True , blank=True)
longitude = models.FloatField(null=True , blank=True)
dt_txt = models.DateTimeField()
temp = models.FloatField(null = False)
temp_min = models.FloatField(null = False)
temp_max = models.FloatField(null = False)
pressure = models.FloatField(null = False)
sea_level = models.FloatField(null = False)
grnd_level = models.FloatField(null = False)
humidity = models.FloatField(null = False)
main = models.CharField(max_length=200)
description = models.CharField(max_length=30)
clouds = models.IntegerField(null=False)
wind_speed = models.FloatField(null = False)
wind_degree = models.FloatField(null = False)
urls.py
urlpatterns = [
path('admin/', admin.site.urls),
path('weatherdata/', views.weatherList.as_view()),
path('weatherdata/<str:city_name>/<int:ndays>/', views.weatherDetail.as_view()),
]
I want 'y' to be filtering objects based on dates. previous ndays data has to be returned. get_object should return the objects which falls under both x and y what needs to be modified in my code.
You have to change your query like below
class weatherDetail(APIView):
def get_queryset(self, city_name, ndays):
x = weatherdata.objects.filter(city_name__icontains=city_name)
today_date = timezone.now().date()
fromdate = today_date - timedelta(days=ndays)
x = x.filter(dt_txt__gte=fromdate).order_by('dt_txt')
return x
def get(self,*args,**kwargs):
city_name = kwargs['city_name']
snippet = self.get_queryset(city_name, ndays)
serializer = weatherdataserializer(snippet, many=True)
return Response(serializer.data)

Django foreign key backreference filter results

I have a model as follows:
class Event(models.Model):
name = models.CharField(max_length=50, blank=False, verbose_name="Event name", )
date = models.DateField(auto_now=False, auto_now_add=False, )
hall = models.ForeignKey(Hall, on_delete=models.CASCADE, null=True, related_name='events', )
I have a view just for trying out results:
#api_view(('GET',))
def get_specific_hall(request, cityId, year = None, month = None, day = None):
hall = Hall.objects.filter(city=cityId)
testHall = Hall.objects.get(city=cityId)
date = year + '-' + month + '-' + day
events = []
for event in testHall.events.filter(~Q(date=date)):
events.append(event)
eventSerializer = EventSerializer(events, many=True)
serializer = HallSerializer(hall, many=True)
return Response(serializer.data + eventSerializer.data)
What I want is: I am passing date as a url parameter. I want to return those Hall objects from a specific city and which do not have any associated event for that date. i.e. only available hall.
How can I achieve that?
I updated my view as follows:
#api_view(('GET',))
def get_specific_halls(request, cityId, year = None, month = None, day = None):
date = year + '-' + month + '-' + day
hall = Hall.objects.all().filter(Q (city=cityId) , ~Q(events__date=date))
serializer = HallSerializer(hall, many=True)
return Response(serializer.data)