什麼是模型對象傳遞給在Django一個輔助函數的正確方法是什麼?應該如何模型對象傳遞給一個輔助功能,在Django
例如,我有一個用戶對象:
u = User.objects.get(pk=1)
,然後希望在u
使用功能helpers.foo()
保存回數據庫之前執行某些操作。
我應該通過整個對象和直接操縱?或者僅僅是ID,則輔助函數來獲得再次對象中重新查詢數據庫...
什麼是模型對象傳遞給在Django一個輔助函數的正確方法是什麼?應該如何模型對象傳遞給一個輔助功能,在Django
例如,我有一個用戶對象:
u = User.objects.get(pk=1)
,然後希望在u
使用功能helpers.foo()
保存回數據庫之前執行某些操作。
我應該通過整個對象和直接操縱?或者僅僅是ID,則輔助函數來獲得再次對象中重新查詢數據庫...
讓我們做一個小測試:
>>> 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已在任務調用和它的執行之間被修改(並且您不想覆蓋這些修改)。
真棒,很好的答案。感謝您澄清 – Rob
@Rob歡迎您 - 隨時以upvote和/或接受答案順便說一句。 –
更好的方式來傳遞完整的對象,如果你通過ID唯一,那麼你必須再次命中數據庫來獲得用戶。
如果你是一般要求,我已經添加了從工作項目底部的一塊。然而,就你而言,我相信你可以定義一個實例方法來處理選定的對象 - 當然如果這些操作直接與模型相關。
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.pyfrom 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'
數據庫查詢既不免費也不便宜;雖然很快。 –
如果這是同步完成的,則傳遞該實例。對於類似於芹菜任務的異步調用,傳遞該id(只有id可以序列化)。 – schwobaseggl