在模型中自动生成多个M2M关系

时间:2012-10-07 01:45:16

标签: django django-models

我有以下模型(简化):

class InscriptionDate(models.Model):
    start_date = models.ForeignKey('Date', related_name='+')
    end_date = models.ForeignKey('Date', related_name='+')
    dates_in_range = models.ManyToManyField('Date', blank=True)

class Date(models.Model):
    year = models.IntegerField(max_length=4)
    era = models.CharField(max_length=2, choices=ERA_CHOICES, default=BC)

我希望在选择开始日期和结束日期后,在保存时为dates_in_range生成所有相关的M2M关系。我们的想法是可以查询范围内的任何日期,并返回与该日期相关的条目。

以下是不正确的,但这是我想要采取的一种方法:

 def save(self):
       start = self.start_date.year
       end = self.end_date.year
       for i in range(start, end):
          self.dates_in_range.add(year)
       super(InscriptionDate, self).save()

是否可以通过这种方式为M2M关系循环add()?我可以用这种方式从输入数据生成并添加完整的M2M关系列表吗?

2 个答案:

答案 0 :(得分:0)

为什么不呢?只记得在/ save()调用之后执行此操作,因为您需要PK来添加m2ms。

super(...).save()
self.dates_in_range.clear()
for year in range(start_year, end_year):
    date, created = Date.objects.get_or_create(year=year)
    self.dates_in_range.add(date)

答案 1 :(得分:0)

您可以轻松使用已有的代码并使用post-save signal

实施

e.g。

from django.dispatch import receiver

@receiver(models.signals.post_save, sender=InscriptionDate)
def add_dates_in_range(sender, instance, **kwargs):
    #assumes both years are in AD
    start_year = instance.start_date.year
    end_year = instance.end_date.year
    for year in range(start_year, end_year+1) #to include end_year
        date = Date.objects.get_or_create(year = year, era = 'AD')[0]
        instance.dates_in_range.add(date)

您还可以将dates_in_range实现为方法而不是多对多关系,但这实际上取决于您计划如何使用模型。

e.g。 (假设您已经拥有start_date和end_date之间所有年份的Date对象,并且所有时代都是AD)

class InscriptionDate(models.Model):
    start_date = models.ForeignKey('Date', related_name='+')
    end_date = models.ForeignKey('Date', related_name='+')
    def dates_in_range(self):
        return Date.objects.filter(year__lte = self.end_date.year, year__gte = self.start_date.year, era = 'AD')