开发者

Django beginner: How to query in django ORM to calculate fields based on dates

开发者 https://www.devze.com 2023-02-01 18:33 出处:网络
Task: Querying a model in Django ORM so that I can calculate fields based on dates. Specifically, extract months from a model.datefield and calculate values based on these months.

Task: Querying a model in Django ORM so that I can calculate fields based on dates. Specifically, extract months from a model.datefield and calculate values based on these months.

Example model:

class PersonProjectHours(models.Model):  
    project = models.ForeignKey('projects.Project')  
    person = models.ForeignKey('projects.Person')  
    rate = models.ForeignKey('PersonIncome')  
    work_date = models.DateField(help_text=_('Enter date'))  
    hours = models.IntegerField(help_text=_('Enter hours worked on this day.'))  


class PersonIncome(models.Model):  
    person = models.ForeignKey('projects.Person')  
    income = models.DecimalField(help_text=_('Enter new income'), max_digits=10, decimal_places=2)  
    validdate = models.DateField(help_text=_('Enter date from which new income is valid.'))  

In my views.py, I can extract the months and hours worked per month like this (I use a range because I couldn't figure out how to query for month in months in ORM). And I can calculate the cost o开发者_开发问答f the hours worked by the different people who worked on the project by looping through the entries in each month (just doesn't work right now because entry.rate is a unicode and I somehow can't covert it to an integer...):

for month in range(1, 13):
    entries_per_month = PersonProjectHours.objects.filter(work_date__month=month)
    hours = entries_per_month.aggregate(value=Sum('hours'))
    cost = 0
    for entry in entries_per_month:
        cost = cost + (entry.hours * entry.rate)
    work_per_year.append([month,hours,cost])

Just to complete this example, I loop through the entries in my templates like this:

{% for month, hours, cost in work_per_year %}  
<tr>  
<td>{{ month }}</td>  
<td>{{ hours.value }}</td>  
<td>{{ cost }}</td>  
</tr>  
{% endfor %}  

What I have done in views.py doesn't seem very elegant, is there a better way to pull date ranges like years, months or days from datefields? And on the sidelines, how do I get entry.rate to be an integer I can calculate?

Thanks for your input! (yes, I am very new to coding, python, and django... took me a week to write this up) :-)


Here's the solution that I ultimately developed with the above input and other stackoverflow posts.

project = get_object_or_404(Project, code=pcode)
project_entries = PersonProjectHours.objects.filter(project=project)
project_years = project_entries.dates('work_date', 'year', order='DESC')

month_dict = {}
year_list = []


for year in project_years:
    year_hours=0
    year_costs=0

    year = int(year.strftime("%Y"))

    for month in range(1,13):
        month_entries = project_entries.filter(work_date__year=year).filter(work_date__month=month)
        hours=0
        costs=0
        for entry in month_entries:
            hours = hours + entry.hours
            costs = int(costs + (entry.hours * entry.rate.income))
        year_hours= year_hours + hours
        year_costs= year_costs + costs

        try:
            month_dict[year].append([datetime(year,month,1), hours, costs])
        except KeyError:
            month_dict[year] = ([[datetime(year,month,1), hours, costs]])
    year_list.append([year,year_hours,year_costs])


Your date range pulling seems fine for me. entry.rate is a foreign key to the model PersonIncome. Would make no sense to multiply the hours with the pk of the PersonIncome instance.

I would add the rate field to the Person:

class Person(models.Model):  
    name = models.CharField(max_length=100)  
    rate = models.IntegerField(max_length=4)  

Then you can do this in the view:

cost = cost + (entry.hours * entry.person.rate)

Whereas this assumes that a Person has always the same rate for any kind of work done. HTH

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号