2009-11-13 1 views
9

내 모델 중 하나에 데이터베이스에 저장되지 않은 속성이 있습니다. 보기 및 모델 수준에서는 모든 것이 잘되지만 내 템플릿에는 이러한 '비 데이터베이스'특성을 표시 할 수 없습니다.Django 모델의 임시 데이터베이스 (비 데이터베이스) 속성을 템플릿에 사용 가능하게 함

다음은 원하지 않는 동작을 보여주기 위해 실제 문제 도메인을 반영하는 인공 예제입니다.

뷰 :

def odometer(request): 
    cars = Car.objects.all() 
    for car in cars: 
     car.read_meters() 
    context = {'cars': cars} 
    return render_to_response('odometer.html', context) 

모델 :

class Car(models.Model): 
    name = models.CharField(_('name'), max_length=100, unique=True) 

    def read_meters(self): 
     for meter in self.meter_set.all(): 
      meter.read() 

    def __unicode__(self): 
     return '%s' % self.name 

class Meter(models.Model): 
    name = models.CharField(_('name'), max_length=100) 
    car = models.ForeignKey(Car) 

    difference = 0 
    previous = 0 
    changed = False 

    def read(self): 
     # this is completely artificial. in the real application we would interface with the hardware 
     # meter to get data 
     try: 
      previous_count = MeterReading.objects.filter(meter__id=self.id).order_by('-stamp')[0].count 
     except: 
      previous_count = 0 
     self.previous = previous_count 
     current_count = previous_count 

     if (random.randrange(0, 2) == 0): 
      self.difference = int(random.random() * 100) 
      if self.name == 'Odometer' or (random.randrange(0, 2) == 0): 
       current_count += self.difference 
      else: 
       current_count -= self.difference 
       if current_count < 0: 
        current_count = 0 
     if current_count > previous_count: 
      self.changed = True 
     new_reading = MeterReading() 
     new_reading.count = current_count 
     new_reading.meter = self 
     new_reading.save() 

    def __unicode__(self): 
     return '%s' % self.name 

class MeterReading(models.Model): 
    count = models.IntegerField(_('count')) 
    stamp = models.DateTimeField(editable=False, auto_now_add=True) 
    meter = models.ForeignKey(Meter) 
    def __unicode__(self): 
     return '%s' % self.count 

그리고 템플릿 :

{% for car in cars %} 
    <h2>{{ car }}</h2> 
    {% for meter in car.meter_set.all %} 
    <h3>{{ meter }}</h3> 
    <p>Difference: {{ meter.difference }}</p> 
    <p>Changed: {{ meter.changed }}</p> 
    <ul> 
     {% for reading in meter.meterreading_set.all %} 
     <li>{{ reading }}</li> 
     {% endfor %} 
    </ul> 
    {% endfor %} 
{% endfor %} 

문제는 'meter.difference'와 'meter.changed'돈 올바른 업데이트 된 값을 출력하지 않습니다. 내가 도대체 ​​뭘 잘못하고있는 겁니까? 모든 조언을 부탁드립니다.

감사합니다.

자동차 모델 :

class Car(models.Model): 
    name = models.CharField(_('name'), max_length=100, unique=True) 

    def read_meters(self): 
     for meter in self.meters: 
      meter.read() 

    def __unicode__(self): 
     return '%s' % self.name 

    @property 
    def meters(self): 
     if not hasattr(self, '_meters'): 
      self._meters = self.meter_set.all() 
     return self._meters 

그리고 템플릿 : 나는 내 자신의 코드에 비슷한 시도

{% for car in cars %} 
    <h2>{{ car }}</h2> 
    {% for meter in car.meters %} 
    <h3>{{ meter }}</h3> 
    <p>{{ meter.name }} difference: {{ meter.difference }}</p> 
    <p>Changed: {{ meter.changed }}</p> 
    <ul> 
     {% for reading in meter.meterreading_set.all %} 
     <li>{{ reading }}</li> 
     {% endfor %} 
    </ul> 
    {% endfor %} 
{% endfor %} 

답변

11

템플릿에이 값이 표시되지 않는 이유는 car.meter_set.all()에 전화 할 때마다 완전히 새로운 쿼리 세트를 데이터베이스에서 바로 가져올 수 있기 때문입니다.

Django 모델 인스턴스에는 ID가 없으므로 하나의 쿼리 세트에있는 Meter 오브젝트는 다른 데이터베이스 세트와 동일한 데이터베이스 값을 갖지만 동적 속성을 공유하지 않습니다.

최근 질문에 here을 표시 할 때이 작업을 수행하는 한 가지 방법은 각 자동차 내에 미터 개체를 캐시하는 것입니다. 그런 다음보기, 모델 및 템플릿에서 car.meter_set.all()을 참조하는 대신 car.get_meters() 또는 무엇이든 할 것이며 동적 속성과 함께 매번 동일한 객체 세트를 가져옵니다.

+0

감사합니다. –

1

하고 보이는

UPDATE : 다니엘의 답변에 따라 업데이트 코드 실행중인 문제가 read_meter() 방법과 odomoter()보기에서 발생하고 있습니다.

QuerySets를 반복하는 데 사용하는 객체 인 metercar은 범위를 벗어나서 속성에 대한 변경 사항이 적용됩니다.

템플릿에 meter.difference 및 meter.changed를 표시하면 Django가 DB에서 해당 객체를 (및 저장하지 않은 속성 값없이) 다시 생성합니다.

설명이 명확 할 것입니다. DB에 값을 저장하지 않는 이유는 무엇입니까?

+0

데이터를 저장하지 않은 이유는 일시적이라는 것입니다. 즉석에서 계산해야하는 데이터를 저장하는 것은 잘못된 것처럼 보이며 데이터베이스 필드에서 다시는 참조되지 않습니다.위의 예는 인위적이며 실제 애플리케이션에서 일시적인 데이터 중 일부는 수백MB 크기입니다. 당신의 도움을 주셔서 감사합니다. –