Django ManyToManyField跨模型删除

时间:2016-05-05 13:19:45

标签: django django-models

我使用以下效率低下的“破坏”方法来删除在刺激中保留的等级,而刺激本身保留在实验中(出于清晰的原因,我简化了我的模型)。

你能否就更有效的方法提出建议?

class Rating(models.Model):
    rater = TextField(null=True)
    rating = FloatField(null=True)
    created = models.DateTimeField(null=True)


class Stimulus(TimeStampedModel):
    genes = TextField()
    weights = ListField()
    ratings = ManyToManyField(Rating, null=True)
    evaluation = FloatField(null=True)
    complete = BooleanField(default=False)


Class Experiment(models.Model):
        all_individuals = ManyToManyField(Stimulus, null=True)

        def destroy(self):
            all_ratings = Rating.objects.all()
            for ind in self.all_individuals.all():
                ratings = ind.ratings.all()
                for rating in ratings:
                    if rating in all_ratings:
                        Rating.objects.filter(id = rating.id).delete()

背景:我正在使用Django进行实验(实验),向用户展示许多刺激(刺激)。每个刺激都会被评分多次。因此,我需要为每个刺激保存多个等级(以及每个实验的多个刺激)。

2 个答案:

答案 0 :(得分:2)

一些简单的改进

  1. 删除if rating in all_ratings,每个评分都会在所有评分列表中

  2. 执行数据库端的delete

  3.  ind.ratings.all().delete()
    
    1. 使用prefetch_related获取外键对象
    2. self.all_individuals.prefetch_related('ratings'):  
      

      合并将是:

      def destroy(self):
          for ind in self.all_individuals.prefetch_related('ratings'):  
              ratings = ind.ratings.all().delete()
      

答案 1 :(得分:0)

我认为在这种情况下使用ManyToManyField不是最好的选择。

使用常见的ForeignKey改变一下这种模型的结构,你会遇到更少的问题。

例如

class Rating(models.Model):
    rater = TextField(null=True)
    rating = FloatField(null=True)
    created = models.DateTimeField(null=True)

    stimulus = models.ForeignKey('Stimulus', related_name='ratings')

class Stimulus(TimeStampedModel):
    genes = TextField()
    weights = ListField()
    #ratings = ManyToManyField(Rating, null=True)
    evaluation = FloatField(null=True)
    complete = BooleanField(default=False)

    experiment = models.ForeignKey('Experiment', related_name='stimulus')

class Experiment(models.Model):
    #all_individuals = ManyToManyField(Stimulus, null=True)
    name = models.CharField(max_length=100)

这是一个更清晰的结构,当您删除实验时,experiment_instance.delete()删除级联将删除所有其他相关模型。

希望它有所帮助。