2017-10-05 21 views
0

モデルオブジェクトをDjangoのヘルパー関数に渡す正しい方法は何ですか?モデルオブジェクトをDjangoのヘルパー関数に渡す方法

例えば、私は、ユーザーオブジェクトがあります。

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

をしてから戻ってDBに保存する前に機能helpers.foo()を使用してuにいくつかの操作を実行したいです。

オブジェクト全体を渡して直接操作する必要がありますか?またはIDだけを取得してオブジェクトを再度取得するヘルパー関数内のDBを再クエリ...

+1

DBクエリは無料でも安価でもありません。高速ですが。 –

+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で比較しているため、彼らは同じ比較)、および1つの変更を与える - あなたは、保存するかどうか変更かどうかは、2番目のものに影響しません(もちろん、データベースからリフレッシュするまで)。また、あなたは両方を変更して保存した場合、結果はあなたが期待したものではないかもしれません。

>>> 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アクセスコストを考慮にした場合、あなたがあなたのヘルパー関数が第二をロードしたくないことは明らかと思われますdbからの(別個の)インスタンス。

非同期呼び出し(通常はセロリタスク)のケースは異なります。ここでは、オブジェクトのIDを渡して、タスクをdbから新たにロードする必要があります。主な理由は、データベース・レコードmighがタスク・コールとその実行の間で変更されていることです(また、それらの変更を上書きしたくないということです)。

+0

素晴らしい、素晴らしい答え。 – Rob

+0

@Robを明確にしていただきありがとうございます。あなたは歓迎されており、回答をアップヴォートしたり、受け入れることができます。 –

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' 
関連する問題