如何在相关模型保存中保存父django模型

时间:2021-03-16 20:16:09

标签: python django

有两种模型 - 程序和段。我需要从相关段中的字段计算程序条目中的总时间。我试图通过覆盖保存方法来做到这一点,但是当输入一个新段时,它不会更新程序模型条目,除非我直接进入程序表单并保存/更新它。

我不知道如何获取段更新以导致程序保存/更新发生。

我如何为其提供上下文以在 Segment 更新中调用程序保存方法(在保存该段之后)。 模型代码为:

from django.db import models
from django.urls import reverse
from datetime import datetime, timedelta

class Program(models.Model):
    air_date             = models.DateField(default="0000-00-00")
    air_time             = models.TimeField(default="00:00:00")
    service              = models.CharField(max_length=10)
    block_time           = models.TimeField(default="00:00:00")
    block_time_delta     = models.DurationField(default=timedelta)
    running_time         = models.TimeField(default="00:00:00")
    running_time_delta   = models.DurationField(default=timedelta)
    remaining_time       = models.TimeField(default="00:00:00")
    remaining_time_delta = models.DurationField(default=timedelta)
    title                = models.CharField(max_length=190)
    locked_flag          = models.BooleanField(default=False)
    deleted_flag         = models.BooleanField(default=False)
    library              = models.CharField(null=True,max_length=190,blank=True)
    mc                   = models.CharField(null=True,max_length=64)
    producer             = models.CharField(null=True,max_length=64)
    editor               = models.CharField(null=True,max_length=64)
    remarks              = models.TextField(null=True,blank=True)
    audit_time           = models.DateTimeField(null=True)
    audit_user           = models.CharField(null=True,max_length=32)

    def calculate_time(self):
      total_run_time_delta = timedelta(minutes=0)
      for segs in self.segments.all():
        total_run_time_delta += segs.length_time_delta
      self.running_time_delta = total_run_time_delta
      self.running_time = f"{self.running_time_delta}"
      hold_time = self.block_time.strftime("%H:%M:%S")
      t = datetime.strptime(hold_time,"%H:%M:%S")
      self.block_time_delta = timedelta(hours=t.hour,
                    minutes=t.minute,seconds=t.second)
      self.remaining_time_delta = self.block_time_delta - total_run_time_delta
      self.remaining_time = f"{abs(self.remaining_time_delta)}"

    def save(self, *args, **kwargs):
      self.calculate_time()
      super().save(*args,**kwargs)

    def __str__(self):
        return f"{self.pk} : {self.title}"

    def get_absolute_url(self):
        return reverse('program_detail', args=[str(self.id)])
        #return reverse('program-update', kwargs={'pk': self.pk})

class Segment(models.Model):
    program_id = models.ForeignKey(Program,
        on_delete=models.CASCADE,
        related_name='segments',   #new link to Program
    )
    sequence_number = models.DecimalField(decimal_places=2,max_digits=6,default="0.00")
    title           = models.CharField(max_length=190)
    bridge_flag     = models.BooleanField(default=False)
    length_time     = models.TimeField(null=True,default=None, blank=True)
    length_time_delta = models.DurationField(default=timedelta)
    author          = models.CharField(max_length=64,null=True,default=None,blank=True)
    voice           = models.CharField(max_length=64,null=True,default=None,blank=True)
    library         = models.CharField(max_length=190,null=True,default=None,blank=True)
    summary         = models.TextField()
    audit_time      = models.DateTimeField(null=True)
    audit_user      = models.CharField(null=True,max_length=32)

    def save( self, *args, **kwargs):
      super().save(*args,**kwargs)
      return super(Program,self.program_id).save()

    def __str__(self):
        return f"{self.title}"

视图看起来像这样...

class ProgramUpdateView(LoginRequiredMixin,UpdateView):
    class Meta:
      model = Program
      widgets = {
        'remarks': Textarea(attrs={'row':10, 'cols':80}),
      }
    model = Program
    success_url = "/program/{id}/"
    template_name = 'program_update.html'
    fields = [
        'title',
        'service',
        'library',
        'air_date',
        'air_time',
        'producer',
        'editor',
        'mc',
        'block_time',
        'remaining_time',
        'running_time',
        'remarks',
    ]

    def form_valid(self, form):
        return super(ProgramUpdateView, self).form_valid(form)



class SegmentUpdate(LoginRequiredMixin,UpdateView):
  model = Segment
  fields = '__all__'
  template_name = 'segment_update.html'

我原本以为我可以在模型中做到这一切,但现在我不太确定。

感谢您提供的任何信息......

2 个答案:

答案 0 :(得分:0)

尝试通过fk直接调用Program.save()方法

在 Segment 模型中

    def save( self, *args, **kwargs):
      super().save(*args,**kwargs)
      self.program_id.save()

或使用 django 信号 https://docs.djangoproject.com/en/3.1/topics/signals/

from django.db.models.signals import post_save, post_delete

@receiver([post_save, post_delete], sender=Segment)
def update_program(sender, instance, **kwargs):
   program = Program.objects.get(pk=instance.program_id.pk)
   program.save()

答案 1 :(得分:0)

请保持您的数据库原子性。不要在其中保存可以从其他字段计算的内容,除非您有充分的理由这样做。你这样做的原因似乎不太好。 当您获得节目列表时,您想要片段的总时间吗?很好,只需用总和注释查询字符串。你每次都会这样做吗?创建一个自定义查询集/管理器来为你做这件事。

相关问题