2016-12-06 14 views
0

我有一個系統的工作,用於跟蹤員工工作時間,並且需要計算這些員工的年終信息。在我們的應用程序的單獨部分中,前一個開發人員通過具有數小時的員工/員工任務進行迭代,並創建字典以傳遞給視圖以進行顯示。我發現,我可以顯着運用「臨時屬性」的僱員削減必要做這個代碼量,因爲我遍歷它們,然後通過簡單地將員工的queryset到視圖,但是這是不好的做法,是有解決這個問題的更好方法是什麼?下面有一個例子的片段:是否將臨時屬性應用於django模型以用於視圖不良練習?

models.py

class Employee(models.Model): 
    user = models.ForeignKey(User) 

class EmployeeTask(models.Model): 
    emp = models.ForeignKey(Employee) 
    hours = models.FloatField() 

views.py

def employee_report(request): 
    employees = Employees.objects.all() 
    tasks = EmployeeTask.objects.all() 

    for employee in employees: 
     emp_tasks = [task for task in tasks 
          if task.employee == employee] 

     employee.total_hours = 0 

     for emp_task in emp_tasks: 
      employee.total_hours += emp_task.hours 

    context = { 
     'employees': employees 
    } 

    return render(request, 'app/employees.html', context) 

我試圖通過創建檢索的僱員的任務,做了方法放置在模型中的邏輯計算但導致大量的sql查詢。獲得並匹配員工與視圖中的任務是我可以找到的避免這種情況的唯一途徑。這種方法很有效,但我擔心它不一定是'pythonic'(或'djangonic',因爲現在感覺就像是一件事情)的方式。

注意:我在實際視圖中做了比這更多的工作,例如根據類型過濾任務(支付時間等),並根據總公司小時數計算員工使用率,所有這些都是作爲臨時屬性的視圖,但爲簡潔起見,我不包括這裏的全部內容。

+1

IMO這是一個很好的做法,如果計算AREN您可以通過彙總條款來表達某些內容。我經常這樣做。我不知道是否有權威或引用,除了我的意見之外,所以我毫不猶豫地將此作爲一個明確的答案。但我認爲Python的「鴨子打字」方法適合這一點。你的模板不關心它是迭代查詢集還是其他迭代,只是它可迭代。 –

+0

@PeterDeGlopper我相信我試着用'select_related'但遇到了一個問題,將採取另一個打擊它,順其自然我。謝謝你指出我在聚合條款的方向,沒有意識到存在! – joshcrim

+0

由於一個員工可以有很多任務,因此您需要使用Employee.objects.prefetch_related('task')'。 'select_related()'創建一個內部聯接,所以只有當只有一個相關的'EmployeeTask'實例時才能工作。 – knbk

回答

0

這不是不好的做法,你可以把它變得更好,把它在你的模型,像這樣的(未經測試,但應該給你的想法):

class Employee(models.Model): 
    user = models.ForeignKey(User) 

    @property 
    def total_hours(self): 
     return self.task_set.all().aggregate(models.Sum('hours')) 


class EmployeeTask(models.Model): 
    emp = models.ForeignKey(Employee) 
    hours = models.FloatField() 
+1

您應該使用聚合查詢,而不是像這樣求和。由於數據庫將負責總結,因此速度會更快。 – Soviut

+0

如果我這樣做,這樣一來,不會在數據庫查詢最終爲每個員工檢索他們的相關任務和裝載視圖時導致顯著放緩? – joshcrim

+0

@Soviut你是絕對正確,修復它... –

相關問題