在Django中将模型对象传递给辅助函数的正确方法是什么?
例如,我有一个用户对象:
u = User.objects.get(pk=1)
然后想要在保存回DB之前使用函数u
在helpers.foo()
上执行一些操作。
我应该通过整个对象并直接操作吗?或者只是ID然后在辅助函数中重新查询数据库以再次获取对象...
答案 0 :(得分: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'
如果考虑数据库访问成本,很明显您不希望让辅助函数从数据库加载第二个(不同的)实例。
异步调用(通常是芹菜任务)的情况不同 - 在这里你要传递对象的id并让你的任务从数据库重新加载它。主要原因是数据库记录migh在任务调用和执行之间被修改(并且您不想覆盖这些修改)。
答案 1 :(得分:0)
传递完整对象的更好方法,如果只传递id,则必须再次点击数据库以获取用户。
答案 2 :(得分: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
不过,我所指的模型是db视图而不是表
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'