2012-02-28 1 views
2

세 가지 모델이 있습니다. 첫 번째는 DayOfWeek라고하는데, 이는 하루 레이블과 번호입니다. 그것은 다음과 같습니다Django Many To Many PrimaryKey에 대해 불평 함

class DayOfWeek(models.Model): 
    day = models.IntegerField() 
    label = models.CharField(max_length='20') 

    def __str__(self): 
    return self.label 

이 클래스는 다음과 같다, 내가 syncdb.Next 때마다, 나는 이벤트 모델이 고정물을 사용하여 채워집니다

마지막으로
class Event(AnnouncementBase, Location): 
    cost = CurrencyField(decimal_places=2, max_digits=10, blank=True, default=0.00) 
    start_date = models.DateField(default = datetime.now().date()) 
    start_time = models.TimeField(default = datetime.now().time()) 
    end_date = models.DateField(blank=True, default=None, null = True) 
    end_time = models.TimeField(blank=True, default=None, null = True) 

은 재발이 . 이벤트가 있으며 반복 이벤트에 대한 이벤트를 예약하는 데 사용됩니다. 그것은 다음과 같습니다

class Recurrence(models.Model): 

    event = models.ForeignKey(Event, related_name='event') 
    repeats = models.CharField(max_length = 50, choices = EVENT_REPEAT_CHOICES) 
    repeat_every = models.IntegerField(default = 1) 

    repeat_on = models.ManyToManyField(DayOfWeek, blank=True, null=True) 

    repeat_by = models.CharField(max_length = 50, choices = EVENT_REPEAT_BY_CHOICES, blank=True) 
    repeat_by_day_of_month = models.IntegerField(default = 0, blank=True) 

    repeat_ends = models.CharField(max_length = 50, choices = EVENT_REPEAT_END_CHOICES) 
    end_occurrences = models.IntegerField(default = 0, blank=True) 
    repeat_end_date = models.DateField(blank=True, default=None, null = True) 

    past_event_count = models.IntegerField(default=0, blank=True) 
    scheduled_events = models.ManyToManyField(Event, blank=True, default=None, related_name = 'scheduled_events') 
    is_active = models.BooleanField(blank=True, default=True) 

    def save(self, force_insert=False, force_update=False, using=None): 
     """Overridden to create events the first time.""" 

     self.full_clean() 
     #First do normal save so the data is there for the even scheduler. 
     self.save_base(force_insert=force_insert, force_update=force_update, using=using) 

     #If nothing is scheduled yet, schedule the first batch 
     if self.scheduled_events.count() == 0 and self.past_event_count == 0: 
      self.scheduleEvents() 


    def clean(self): 
     #repeat on weekly 
     if self.repeat_every < 1: 
      raise ValidationError('Repeat every must be at least 1.') 


     #weekly 
     if self.repeats == EVENT_REPEAT_CHOICES[1][0]: 
     #look for missing stuff 
     if not self.repeat_on: 
      raise ValidationError('Missing repeat on.') 

마지막으로, 나는 이것이는 다음과 같습니다 확인 작동 확인하는 단위 테스트가 있습니다

테스트는 다음을 제외하고, 실패를 실행할 때마다
def test_weekly_mon_wed_fri_occurrence(self): 
    event = Event() 
    event.start_date = date(year=2012, month=1, day=2) 
    event.start_time = time(hour=13, minute=30) 
    event.save() 

    recurrence = Recurrence() 
    recurrence.repeats = EVENT_REPEAT_CHOICES[1][0] 
    recurrence.repeat_on = (EVENT_DAY_CHOICES[1][0], EVENT_DAY_CHOICES[3][0], EVENT_DAY_CHOICES[5][0]) 
    recurrence.repeat_ends = EVENT_REPEAT_END_CHOICES[0][0] 
    recurrence.event = event 

    nextEvent = recurrence.getNextEvent(event) 

    self.assertEquals(date(year=2012, month=1, day=4), nextEvent.start_date) 
    self.assertEquals(event.start_time, nextEvent.start_time) 

    nextNextEvent = recurrence.getNextEvent(nextEvent) 

    self.assertEquals(date(year=2012, month=1, day=6), nextNextEvent.start_date) 
    self.assertEquals(event.start_time, nextNextEvent.start_time) 

. ValueError : '되풀이'인스턴스는 일대 다 키 값을 가져야 만 다 대다 관계를 사용할 수 있습니다.

clean 메서드에서 self.repeat_on을 사용하면 줄에 오류가 발생합니다.

repeat_on을 선택 사항으로 지정하려면 일부 재발 유형에만 필요합니다. 이 작업을 어떻게 수행합니까? 나는 그것을 놓치고 무엇이 실패하게 만들까?

답변

4

Many2Many 관계를 할당하기 전에 recurrence.save()으로 전화해야합니다. 귀하의 코드에서 당신은 먼저 재발을 저장하지 않고

recurrence.repeat_on = (EVENT_DAY_CHOICES[1][0], EVENT_DAY_CHOICES[3][0], EVENT_DAY_CHOICES[5][0]) 

을 저장하지 않아도됩니다. 저장되지 않았기 때문에 재발에는 아직 기본 키가 생성되지 않으며 Django ORM은 M2M 테이블에 외래 키로 삽입 할 내용을 알지 못합니다.

+0

아직 집에 없지만 한 가지 질문이 있습니다. 재발 호출을 저장하면 오류가 발생합니다. 또한이 오류가 발생하지 않았더라도 유효성 검사 오류를 일으킬 수 있습니다. repeat_on 값이 필요한 경우가 있습니다. repeat_on이 필요하지 않을 때 중단없이 검증하려면 어떻게해야합니까? save에 대한 첫 번째 호출은 항상 유효성을 검사하지 못합니다. – Jon

+0

당신이 맞습니다, 그리고 이것은 장고의 M2M 관계의 한계입니다. 모델 AND 형식 모두 고유 한 클린 방법이 있음에 유의하십시오. 모델의 'clean'은 자체적으로 충분해야하며 해당 모델에있는 데이터 만 유효성을 검사해야합니다. Many2ManyField에서'through'를 사용하여 자신 만의 M2M 테이블을 구현하고 intermediery 모델에'clean'을 추가하거나 직접 외래 키를 저장하거나, 더 잘 맞을 것이라고 생각하는 경우 Form의 clean을 사용하여 전체적으로 요청의 유효성을 검사 할 수 있습니다. – astevanovic