2016-04-17 5 views
0

私は値を記録するいくつかのプローブを持っていると言います。私はDjangoモデルを設定して、プローブとそれが記録する測定値を表現したいと思っています。したがって、このような何かが働くだろう:更新されたフィールドの以前の値を自動的に保存するモデル保存メソッドをオーバーライドします

class Probe(models.Model): 
    name = models.CharField(max_length=256) 

    def __unicode__(self): 
     return u'<Probe: %s>' % self.name 

class Observation(models.Model): 
    probe = models.ForeignKey(Probe) 
    obstime = models.DateTimeField() 
    # the above field should be understood to represent the time in the world 
    # represented by the measurement value recorded. *not* the time at which 
    # that value was written to the database. 
    value = models.FloatField() 

    class Meta: 
     unique_together = (('probe', 'obstime'),) 

    def __unicode__(self): 
     tup = (self.probe.name, 
       self.obstime.strftime('%Y%m%d-%H%M%S'), 
       '%0.2f' % self.value) 
     return u'<Observation: %s @ %s = %s>' % tup 

しかし、これを超えたが、私は少しより多くの情報を追跡できるようにするには、私のデータベースやアプリを本当にしたいと思います。特に、私は実際にObservationモデルに3つの追加フィールド、つまり,previous_valueprevious_db_recording_timeを追加したいと考えています。私は、ユーザが上記のエントリだけを直接操作しようとしますが、他のフィールドは予想通りに自動的に動作します。私はObservationクラスのsaveメソッドをオーバーライドすることでこれを可能にするべきだと思いますが、私はいくつかの助けが必要です!

人が1月5日の正午に自分のコンピュータに戻ってきて、コンピュータに座っているとします。彼らは、ProbeAがJan1stの2AMで3.14を読み取ったことを示すいくつかの(決して前に入力された)データを記録したい。同じ人が見ることができることを、その後、数時間後に(2PMJan5th)

probe: ProbeA, 
obstime: 2AMJan1st, 
value: 3.14, 
db_recording_time: NoonJan5th, 
previous_value: Null, 
previous_db_reording_time: Null 

:私は彼らが3.14と2AMJan1stを指定する必要がするだけしたいと思いますが、私は観察をしてDBに行きたいと思います彼らのノートブックで、 "おっと、私は私のノートブックの価値を誤解...それは本当に2.14だった"を実現する。だから私は(管理者やPythonコンソールを使って)既存の観測を呼び出し、3.14を2.14に修正して欲しいと思います。彼らは私がDB内の観察を示したいと思います、ということでした場合:

probe: ProbeA, 
obstime: 2AMJan1st, 
value: 2.14, 
db_recording_time: 2PMJan5th, 
previous_value: 3.14, 
previous_db_reording_time: NoonJan5th 

私はこのように感じるの管理インターフェイスで読み取り専用フィールドのいくつかの組み合わせだけでなく、いくつかの合理的なビットと非常に簡単でなければなりませんObservationクラスのsaveメソッドでオーバーライドします。どんな助けでも大歓迎です!あなたが保存する前に、データベースから古いレコードを取得でき

+1

をあなたはそれが参照する観測モデルでself' 'への外部キーを追加する方が理にかなって思います観察は早く行われ、これらのフィールドを複製する必要はありませんか?あるいは、あなたはいつも同じ観察を参照したいですか?その場合、前回の観測値からのみ値が得られます。その前のものではありません。しかし、「自己」への外部キーを使用すると、一連の観測結果を保存し、相互にリンクさせることができます。 – AKS

+0

これは非常にクールなアイデアです。したがって、自己への外部キーは、early_observation_draftのように呼び出されます。意味をなさないしかし、もし私がそうするなら、与えられたプローブの観察時間の範囲に対して最も最近入力された値だけを返すクエリを書く効率的な方法はありますか?私。拡張の前に、Observation.objects.filter(probe = choseprobe)またはObservation.objects.filter(probe = selectedprobe、obstime__gte = start、obstime__lte = end)を実行できます。しかし、強化した後は、「現在考慮されている権利」の値と修正された草案の両方が得られます。 – 8one6

+0

回答として私のコメントを追加し、あなたの他の質問にも答えようとしました。 – AKS

答えて

1

recording_time = models.DateTimeField(auto_now=True) 
previous_value = models.FloatField(null=True, default=None) 
previous_recording_time = models.DateTimeField(null=True, default=None) 

def save(self, force_insert=False, force_update=False, using=None, 
     update_fields=None): 
    try: 
     obj = Observation.objects.get(pk=self.pk) 
     # this is the record of this instance before editing 
    except Observation.DoesNotExist: # self.pk==None: this is a new Observation 
     pass 
    else: # this is indeed an update 
     self.previous_value = obj.value 
     previous_db_recording_time = obj.db_recording_time 
    super(Observation, self).save(force_insert=force_insert, force_update=force_update, using=using, 
     update_fields=update_fields) 

を、誰もがこれまで手動でrecording_timeprevious_value、またはprevious_recording_timeを設定する必要はないはずです。したがって、のAdminクラスで使用するModelFormからこれらのフィールドを除外することができます。

0

私がコメントで示唆したように、Observationモデルの外部キーをselfに追加することができます。これは先に取った観測を参照しています。これらのフィールドを複製する必要はありません。 previous_value,previous_db_recording_time

class Observation(models.Model): 
    ... 
    prev_observation = models.ForeignKey('self', null=True) 

    # you can also add a `is_recent` field to this model so you set it to True when its created 
    is_recent = models.BooleanField(default=True) 

それでは、これらすべての7 is_recenttがTrueになるためにあなたがそう週[o1, o2, o3, o4, o5, o6, o7]で7つの観測を追加しましょう。次のように

そして、あなたはこれらの観察を取得することができます:

Observation.objects.filter(probe=chosenprobe, 
          obstime__gte=start, obstime__lte=end, 
          is_recent=True) 

# [o1, o2, o3, o4, o5, o6, o7] 

を今、あなたはので、この時点であなたはo1o3o6ためis_recentを設定することができo8o9o10o1o3o6を修正しました〜にFalse。

そして、再度上記のクエリを実行すると、更新された(最近の)観測与える:

# [o2, o4, o5, o7, o8, o9, o10] 
+0

申し訳ありませんが、わかりません。 Observationに "recorded_at"と呼ばれるフィールドを追加し、それ以外の場合は提案どおりに進みます。その場合、与えられた日付範囲*で撮影された測定値を表す特定のプローブのすべての観測値を取得する方法はありますが、最も最近に記録された各タイムスタンプの測定値のみが表示されます*。だから私は1週間毎日データを表す測定値を作成し記録しています。そして私は戻って3つを修正します。 db内の10回の観測で、7つのタイムスタンプを表します。どのようにして7回の「最新の測定」を返すことができますか? – 8one6

+0

私はあなたの質問の第二の部分を誤解したと思います。更新された答えを見てください。 – AKS

関連する問題