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
)
Related
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 !!
I am learning django or a month now. I created a model called "Leave" to mark employees leave. Then I created a model called "Salarie".In this I need to create a field like "Total_Leave" which will show an employees leave count in a month.( In january 2020 how many leave a particular employee took) ( If i mention the "Employee_Name" as "Samantha" in salary model, it need to show samantas' leave in the particular month,year)
I tried to do it like this and tried some coding but nothing worked.
#property
def Total_Leave(self):
return self.
Can anyone explain me how to do that please?
Models.py
class Leave(models.Model):
Leave_ID = models.CharField(max_length=5, primary_key=True,default=" ")
Employee_Name = models.ForeignKey('Employee_Detail',models.DO_NOTHING)
Dept_Name = models.ForeignKey('Department', models.DO_NOTHING)
l = (
("Paid","Paid"),("Non-Paid","Non-Paid")
)
Leave_Type = models.CharField(max_length=10, choices= l, default="Non-Paid")
m = (
("January","January"),("February","February"),("March","March"),("April","April"),("May","May"),("June","June"),("July","July"),("August","August"),("September","September"),("October","October"),("November","November"),("December","december")
)
Month = models.CharField(max_length=10, choices= m)
Year = models.IntegerField(max_length=4)
Start_Date = models.DateField()
End_Date = models.DateField(null=True, blank = True)
Reason = models.CharField(max_length=200)
s = (
("Accepted","Accepted"),("Pending","Pending"),("Canceled","Canceled")
)
Status = models.CharField(max_length=10, choices= s, default="Pending")
def __str__(self):
return str(self.Employee_Name)
class Salarie(models.Model):
Salarie_ID = models.CharField(max_length=5,primary_key=True,default=" ")
Employee_Name = models.ForeignKey('Employee_Detail', models.DO_NOTHING)
Dept_Name = models.ForeignKey('Department', models.DO_NOTHING)
Basic_Salary = models.IntegerField(default=0)
Extra_Hours = models.IntegerField(default=0)
#property
def Extra_Payment(self):
return self.Extra_Hours * 350
Bonus = models.IntegerField(default=0)
#property
def Total_Payment(self):
return self.Extra_Payment + self.Basic_Salary + self.Bonus
m = (
("January","January"),("February","February"),("March","March"),("April","April"),("May","May"),("June","June"),("July","July"),("August","August"),("September","September"),("October","October"),("November","November"),("December","december")
)
Month = models.CharField(max_length=10, choices= m)
Year = models.IntegerField(max_length=4)
Status = models.BooleanField()
Paid_Date = models.DateField(null=True,blank=True)
def __str__(self):
return str(self.Employee_Name)
class Employee_Detail(models.Model):
Employee_ID = models.CharField(primary_key=True, max_length=6)
Employee_Name = models.CharField(unique=True, max_length=30)
Primary_Phone = models.IntegerField(unique=True, max_length=10)
p = (
("Manager","Manager"),("Supervisor","Supervisor"),("Employee","Employee")
)
Position = models.CharField(max_length=15, choices= p, default="Employee")
Address = models.TextField(max_length=500)
Email = models.EmailField(max_length=50, unique=True)
def __str__(self):
return str(self.Employee_Name)
You can do this by using annotate or aggregate
If you want leave count for all the employees then
from django.db.models import Count
employees = Employee_Detail.objects.filter(leave__Status='Accepted').annotate(leave_count=Count('leave'))
you can access this by <employee Obj>.leave_count
If you want leave count for all employee order_by Month then
employees = Employee_Detail.objects.filter(leave__Status='Accepted').order_by('leave__Month').annotate(leave_count=Count('leave')).values('leave_Month','leave_count')
And last you want leave count for a particular employee for a particular month than in your employee model write #property function like this
#property
def get_leave_count(self):
leaves = Employee_Detail.objects.filter(id=self.id,leave__Status='Accepted').aggregate(leave_count=Count('leave'))
return leaves['leave_count']
for month and year wise provide month and year and then
month = 'January' #For example
leaves = Employee_Detail.objects.filter(id=employee_id,leave__Month=month,leave__Status='Accepted').aggregate(leave_count=Count('leave'))
#{'leave_count':3}
year = '2020' #For example
leaves = Employee_Detail.objects.filter(id=employee_id,leave__Year=year,leave__Status='Accepted').aggregate(leave_count=Count('leave'))
#{'leave_count':13}
I tried something like this, maybe of some use.
def total_leave(emp_name,month,year):
leaves = Leave.objects.filter(Emp_name= emp_name,Month=month,Year=year)
Count=0
for leave in leaves:
if leaves.status== "Accepted":
Count +=1
return Count
Like if you only need to get leave count for the year, just use year as a parameter for function.
After much research and trouble i came up with a non DRY solution, Hope someone can make it DRY.
All im trying to get is a calculated Price which takes a parameter and displays in the template accordingly.
i have a function get_price on model vehiclecategory which takes a parameter duration which is received from frontend forms.
MODELS.PY
class VehicleCategory(models.Model):
CATEGORY_CHOICES=(
('E-Cycle', 'E-Cycle'),
('E-Scooter', 'E-Scooter')
)
main_category = models.CharField(max_length=15, choices= CATEGORY_CHOICES)
title = models.CharField(unique=True, max_length=200)
image = models.ImageField(
null=True,
blank=True,
width_field="width_field",
height_field= "height_field",
default= 'e-bike.png',
upload_to='category')
width_field = models.IntegerField(default=250)
height_field = models.IntegerField(default=250)
slug =models.SlugField(max_length=200, db_index=True, unique=True)
def __str__(self):
return self.title
#GET PRICE
def get_price(self, duration):
for item in VehiclePrice.objects.all():
if item.vehicle_category.title == self.title and (duration >= item.slab.start and duration <= item.slab.end):
return item.total_price
class Meta():
verbose_name = "Vehicle Category"
verbose_name_plural = "Vehicle Categories"
class PriceSlab(models.Model):
start = models.IntegerField()
end = models.IntegerField()
timestamp = models.DateTimeField(auto_now_add=True)
def __str__(self):
return '%s - %s ' % (self.start, self.end)
class VehiclePrice(CustomerStatus):
help_text= "Ensure no more than 2 digits after decimal"
vehicle_category = models.ForeignKey(VehicleCategory, on_delete= models.SET_NULL, null=True, related_name='vehicle_category_price')
slab = models.ForeignKey(PriceSlab, on_delete=models.CASCADE)
net_price = models.DecimalField(help_text= help_text, max_digits=5, decimal_places=2)
tax_percent = models.DecimalField(help_text=help_text, max_digits=4, decimal_places=2, default=18.00)
discount_percent = models.DecimalField(help_text=help_text,max_digits=4, decimal_places=2, default=0, blank=True)
#property
def total_tax(self):
tax = (self.net_price * self.tax_percent)/100
return tax
#property
def get_price(self):
total = self.net_price + self.total_tax
return total
#property
def total_discount(self):
discount = (self.get_price * self.discount_percent)/100
return discount
#property
def total_price(self):
total = self.get_price - self.total_discount
return round(total)
class Meta():
unique_together=('customer_status','vehicle_category' ,'slab')
def __str__(self):
return '%s - %s - %s' % (self.customer_status, self.vehicle_category, self.slab)
VIEWS.PY
class HomeView(ListView):
template_name = 'app/home.html'
def get(self, request):
if request.method == "GET":
start_date = request.GET.get('start_date')
end_date = request.GET.get('end_date')
if start_date and end_date:
start_date = datetime.strptime(start_date, "%d/%m/%Y").date()
end_date = datetime.strptime(end_date, "%d/%m/%Y").date()
duration = (end_date - start_date).days +1
print(duration)
vehiclecategory= VehicleCategory.objects.all()
context = {
'price1': VehicleCategory.objects.get(main_category= 'E-Cycle', title="Sporty").get_price(duration),
'price2': VehicleCategory.objects.get(main_category= 'E-Cycle', title="Step-Through").get_price(duration),
'price3': VehicleCategory.objects.get(main_category= 'E-Cycle', title="Fatbike").get_price(duration),
'price4': VehicleCategory.objects.get(main_category= 'E-Scooter', title="Scooter").get_price(duration),
'vehiclecategory1': vehiclecategory.filter(main_category= 'E-Cycle', title="Sporty"),
'vehiclecategory1': vehiclecategory.filter(main_category= 'E-Cycle', title="Step-Through"),
'vehiclecategory1': vehiclecategory.filter(main_category= 'E-Cycle', title="Fatbike"),
'vehiclecategory2': vehiclecategory.filter(main_category= 'E-Scooter', title="Scooter"),
'form':CartQuantityForm(),
'dateform': DateForm(),
}
else:
context={'dateform': DateForm(),}
return render(request, self.template_name, context )
after the user inputs the date range, the vehicles are displayed, but when u go to the cart and come back the same page, the page refreshes as a new one. how can keep the date range values intact and render the same page as the user got first time he searched for a vehicle, so that he can add or modify the vehicles selected???
You may put your start & end dates into your URL.
You can create 2 urls record dispatching the same view:
path(r'/prices/', HomeView.as_view())
path(r'/prices/(?P<start>\d{4}-\d{2}-\d{2})_(?P<end>\d{4}-\d{2}-\d{2})', HomeView.as_view())
Then you need to make some changes in your view:
class HomeView(ListView):
template_name = 'app/home.html'
def get(self, request, **kwargs):
start = kwargs.get('start')
end = kwargs.get('end')
if start is None or end is None:
# Ask for dates & Redirect to its new url with dates.
else:
# Check the dates, convert them to date object & do the rest.
Maybe not the best solution but the first thing came to my mind is this one.
I am trying to add object to m2m with add method but neither its showing error nor adding item, I can't understand why
Here is my view :
class UpdateCartView(generic.UpdateView):
model = Cart
fields = ['products']
template_name = 'update_cart.html'
success_url = reverse_lazy('carts:home')
def form_valid(self,form):
product = ProductCreateModel.objects.get(pk = self.request.POST.get('product'))
size = Size.objects.get(pk = self.request.POST.get('size'))
colour = Colour.objects.get(pk = self.request.POST.get('colour'))
products = Products.objects.create(product = product,
size = size,
quantity = int(self.request.POST.get('quantity')),
colour = colour)
product.save()
cart = self.get_object()
print(products)
cart.products.add(products)
cart.save()
return super(UpdateCartView,self).form_valid(form)
def get_object(self):
cart_obj, cart_created = Cart.objects.new_or_get(self.request)
return cart_obj
Here is my models :
class Products(models.Model):
product = models.ForeignKey(ProductCreateModel,on_delete=models.CASCADE,related_name='cart_product')
quantity = models.PositiveIntegerField(default=1,validators=[MinValueValidator(1)])
size = models.ForeignKey(Size,related_name='cart_product_size',on_delete=models.CASCADE,null=True,blank=False)
colour = models.ForeignKey(Colour,related_name='cart_product_colour',on_delete=models.CASCADE,null=True,blank=False)
def __str__(self):
return '{product}({quantity})'.format(product=self.product,quantity=self.quantity)
class Cart(models.Model):
MESSAGE_CHOICES = (
('A' , 'Items are added to you cart'),
('R' , 'Items are removed from cart'),
('PC' , 'Price of some items has changed'),
)
messages = models.CharField(max_length=1, choices=MESSAGE_CHOICES,null=True,blank=True)
user = models.ForeignKey(User, null=True, blank=True, on_delete=models.CASCADE)
products = models.ManyToManyField(Products, blank=True)
subtotal = models.DecimalField(default=0.00, max_digits=100, decimal_places=2)
total = models.DecimalField(default=0.00, max_digits=100, decimal_places=2)
updated = models.DateTimeField(auto_now=True)
timestamp = models.DateTimeField(auto_now_add=True)
objects = CartManager()
def __str__(self):
return str(self.id)
def m2m_changed_cart_receiver(sender, instance, action, *args, **kwargs):
if action == 'post_add' or action == 'post_remove' or action == 'post_clear':
products = instance.products.all()
total = 0
for x in products:
total += (x.product.final_price * x.quantity)
if instance.subtotal != total:
instance.subtotal = total
instance.save()
def pre_save_cart_receiver(sender, instance, *args, **kwargs):
if instance.subtotal > 0:
instance.total = Decimal(instance.subtotal) * Decimal(1.08) # 8% tax
else:
instance.total = 0.00
Everything is working fine, no errors, also print the products but in my admin panel its showing empty cart means cart.products.add(products) not added products why ?
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)