2

I have the following model structure below:

class Master(models.Model): 
    name = models.CharField(max_length=50)          
    mounting_height = models.DecimalField(max_digits=10,decimal_places=2)   

class MLog(models.Model):                  
    date = models.DateField(db_index=True)
    time = models.TimeField(db_index=True)      
    sensor_reading = models.IntegerField()      
    m_master = models.ForeignKey(Master)

The goal is to produce a queryset that returns all the fields from MLog plus a calculated field (item_height) based on the related data in Master

using Django's raw sql:

querySet = MLog.objects.raw('''
    SELECT a.id,
           date,
           time,
           sensor_reading,
           mounting_height,
          (sensor_reading - mounting_height) as item_height 
    FROM db_mlog a JOIN db_master b 
                     ON a.m_master_id = b.id
''')                                

How do I code this using Django's ORM?

4

2 に答える 2

7

に依存せずにこれを実行する2つの方法を考えることができますraw()1つ目は、@tylerlが提案したものとほとんど同じです。このようなもの:

class Master(models.Model):
    name = models.CharField(max_length=50)
    mounting_height = models.DecimalField(max_digits=10,decimal_places=2)

class MLog(models.Model):
    date = models.DateField(db_index=True)
    time = models.TimeField(db_index=True)
    sensor_reading = models.IntegerField()
    m_master = models.ForeignKey(Master)

    def _get_item_height(self):
        return self.sensor_reading - self.m_master.mounting_height
    item_height = property(_get_item_height)

この場合、MLog呼び出されたのカスタム(派生)プロパティを定義していitem_heightます。このプロパティはsensor_reading、インスタンスのと、関連するマスターインスタンスのmounting_heightの差として計算されます。詳細はproperty こちら

次に、次のようなことを行うことができます。

In [4]: q = MLog.objects.all()

In [5]: q[0]
Out[5]: <MLog: 2010-09-11 8>

In [6]: q[0].item_height
Out[6]: Decimal('-2.00')

これを行う2番目の方法は、extra()メソッドを使用してデータベースに計算を行わせることです。

In [14]: q = MLog.objects.select_related().extra(select = 
          {'item_height': 'sensor_reading - mounting_height'})

In [16]: q[0]
Out[16]: <MLog: 2010-09-11 8>

In [17]: q[0].item_height
Out[17]: Decimal('-2.00')

の使用に注意してくださいselect_related()。これMasterがないと、テーブルはクエリに結合されず、エラーが発生します。

于 2010-09-11T09:30:01.017 に答える
0

私は常に DB ではなくアプリで計算を行っています。

class Thing(models.Model):
    foo = models.IntegerField()
    bar = models.IntegerField()     
    @Property
    def diff():
        def fget(self):
            return self.foo - self.bar
        def fset(self,value):
            self.bar = self.foo - value

その後、他のフィールドと同じように操作でき、基になるデータで定義したことは何でも実行します。例えば:

obj = Thing.objects.all()[0]
print(obj.diff)  # prints .foo - .bar
obj.diff = 4     # sets .bar to .foo - 4

ちなみに、プロパティは単なる標準のプロパティ デコレータであり、この場合は次のようにコード化されています (どこから来たのか覚えていません)。

def Property(function):
    keys = 'fget', 'fset', 'fdel'
    func_locals = {'doc':function.__doc__}
    def probeFunc(frame, event, arg):
        if event == 'return':
            locals = frame.f_locals
            func_locals.update(dict((k,locals.get(k)) for k in keys))
            sys.settrace(None)
        return probeFunc
    sys.settrace(probeFunc)
    function()
    return property(**func_locals)
于 2010-09-11T08:56:39.037 に答える