2017-10-05 63 views
0

什麼是模型對象傳遞給在Django一個輔助函數的正確方法是什麼?應該如何模型對象傳遞給一個輔助功能,在Django

例如,我有一個用戶對象:

u = User.objects.get(pk=1) 

,然後希望在u使用功能helpers.foo()保存回數據庫之前執行某些操作。

我應該通過整個對象和直接操縱?或者僅僅是ID,則輔助函數來獲得再次對象中重新查詢數據庫...

+1

數據庫查詢既不免費也不便宜;雖然很快。 –

+0

如果這是同步完成的,則傳遞該實例。對於類似於芹菜任務的異步調用,傳遞該id(只有id可以序列化)。 – schwobaseggl

回答

2

讓我們做一個小測試:

>>> from django.contrib.auth.models import User 
>>> u1 = User.objects.get(pk=1) 
>>> u2 = User.objects.get(pk=1) 
>>> u1 == u2 
True 
>>> u1 is u2 
False 
>>> u1.first_name 
u'Ruth' 
>>> u2.first_name 
u'Ruth' 
>>> u2.first_name = u"Route" 
>>> u2 == u1 
True 
>>> u1.first_name 
u'Ruth' 
>>> u2.save() 
>>> u1.first_name 
u'Ruth' 
>>> 
>>> u1.refresh_from_db() 
>>> u1.first_name 
u'Route' 

正如你所看到的,在加載相同記錄兩次給了兩個不同的對象(它們比較相同的,因爲Model比較了PK),和改變一個 - 你是否保存是否改變 - 不影響第二個(直到你從db中刷新它當然)。此外,如果您修改並保存兩者的結果可能不是你所期望的:

>>> u1.last_name 
u'FOOBAR' 
>>> u2.last_name 
u'FOOBAR' 
>>> 
>>> u1.first_name = u"Ruth" 
>>> u2.last_name = u"ROOTZ" 
>>> u1.save() 
>>> u2.save() 
>>> ux = User.objects.get(pk=1) 
>>> ux.first_name 
u'Route' 
>>> ux.last_name 
u'ROOTZ' 

如果您在DB訪問的成本因素,似乎很明顯,你不想讓你的輔助函數加載第二個(不同的)實例從數據庫。

異步調用(一般芹菜任務)的情況下是不同的 - 在這裏你要傳遞的對象的ID和你的任務從數據庫中重新加載它。主要原因是數據庫記錄migh已在任務調用和它的執行之間被修改(並且您不想覆蓋這些修改)。

+0

真棒,很好的答案。感謝您澄清 – Rob

+0

@Rob歡迎您 - 隨時以upvote和/或接受答案順便說一句。 –

0

更好的方式來傳遞完整的對象,如果你通過ID唯一,那麼你必須再次命中數據庫來獲得用戶。

0

如果你是一般要求,我已經添加了從工作項目底部的一塊。然而,就你而言,我相信你可以定義一個實例方法來處理選定的對象 - 當然如果這些操作直接與模型相關。

class User(models.Model): 
    first_name = models.CharField(max_length=40) 
    last_name = models.CharField(max_length=40) 
    title = models.CharField(max_length = 50) 
    ... 

    def make_comrade(self): 
     return "Comrade " + self.last_name 

然後,

user = User.objects.get(pk=1) 
user.update(title=user.make_comrade()) 

我上面說的代碼。

views.py

from reports_helper import report_generator 

... 

def export_terminals_daily_turnover(request): 
    return report_generator('TerminalTurnover', 'daily_turnover', 'terminal_id', 'address_on_bill', 'summ') 

,這是我reports_helper.py

import csv 
import django 
from django.http import HttpResponse 


def get_model_name(model_name): 
    entity = django.apps.apps.get_model('reports', model_name) 
    return entity 


def report_generator(model_name, report_name, *args): 
    response = HttpResponse(content_type='text/csv') 
    response['Content-Disposition'] = 'attachment; filename="{}.csv"'.format(report_name) 

    headers = list(args) 
    klass = get_model_name(model_name) 

    writer = csv.writer(response) 
    writer.writerow(headers) 

    rows = klass.objects.all().values_list(*args) 
    for row in rows: 
     writer.writerow(row) 

    return response 

順便說一句,這裏的模型我指的是一個數據庫視圖,而不是表

class TerminalTurnover(models.Model): 
    terminal_id = models.IntegerField(primary_key=True) 
    summ = models.DecimalField(max_digits=15, decimal_places=2) 
    address_on_bill = models.CharField(max_length=100) 

    class Meta: 
     managed = False 
     db_table = 'reports_terminalturnover' 
相關問題