Django:在CreateView表单提交上触发新对象的创建

时间:2019-03-02 09:05:12

标签: python django django-models django-views

首先,如果我的问题太明显或在另一个主题中对此进行了讨论,我深表歉意。我已经在这个问题上工作了近一个星期,并且一直在寻找类似的主题,但没有成功。我不是专业程序员,但我喜欢创建一些有用的软件。

因此,我正在对一个Webapp进行编程,以控制实验室中的物质。我已经为一种物质设置了一个模型(该模型取自另一个名为SubstanceDict的模型的名称),另一个模型用于质量控制,另一个模型用于物质状态,可以这样说:

class Substance(models.Model):
 reg_num = models.CharField(max_length=11, default=adding_reg_num, editable=False)
 name = models.ForeignKey(SubstanceDict, on_delete=models.CASCADE)
 provider = models.CharField(max_length=20)
 '''some other fields and functions in here...'''

@receiver(post_save, sender=Substance)
def set_to_quaratine(sender, **kwargs):
    if kwargs.get('created', False):
        SubstanceStatus.objects.get_or_create(origen=kwargs.get('instance'), status=0, comments="Set to quarantine whilst reception.")

class QualityControl(models.Model):
    qc_reg_num = models.CharField(max_length=12, default=adding_qc_reg_num, editable=False)
    source = models.ForeignKey(Substance, on_delete=models.CASCADE, related_name='quality_control')
    '''whatever else'''

class SubstanceStatus(models.Model):
    source = models.ForeignKey(SustanciaDetalle, on_delete=models.CASCADE, related_name='status')
    status = models.IntegerField(choices=(
        (0, 'Quarantine'),
        (1, 'Approved'),
        (2, 'Rejected'),), null = False)
    quality_control = models.ForeignKey(QualityControl, on_delete=models.CASCADE, blank=True, null=True)
    date = models.DateTimeField(auto_now_add=True)
    comments = models.TextField()

因此,基本上,使用CreateView for Substance Model,每当我创建一个Substance的新实例时,@ receiver都会触发状态为0的SubstanceStatus实例的创建和一个注释,指出“在接收时设置为隔离状态”。

在物质的CreateView之后,它将(具有物质reg_number的GET方法)重定向到新表单,以创建关联的QualityControl实例。到这里的一切都还可以。然后,我对POST方法使用三个按钮:“保存并批准”,“保存并保留隔离区”和“保存并拒绝”。这是我的问题。我希望从QualityControl关联的CreateView中按“保存并批准”时,将使用与刚刚生成的QualityControl的QualityControl CreateView,status = 1和quality_control的源相同的源来触发SubstanceStatus的新实例,类似地,如果被拒绝,则状态= 2,如果被隔离,则状态= 0。我该怎么办?我已经在models文件中尝试了@receiver,但没有成功,因为它无法管理POST或Sessions请求。同样,更改form_valid()函数不会执行任何操作,甚至不会出错。视图如下:

class SubstanceCreate(CreateView):
    model = Substance
    fields = '__all__'
    autocomplete_fields = ['name']
    def get_form(self, form_class=None):
        form = super(SubstanceCreate, self).get_form(form_class)
        ''' some widgets '''
        return form


    def form_valid(self, form):
        substance = form.save()
        if 'quarantine' in self.request.POST:
            return super(SubstanceCreate, self).form_valid(form)
        elif 'addcc' in self.request.POST:
            return redirect(reverse('create-quality-control') + '?source=' + str(substance.reg_num))
        else:
                return super(SubstanceCreate, self).form_valid(form)


class QualityControlCreate(CreateView):
      model = QualityControl

      def get_form(self, form_class=None):
          form = super(QualityControlCreate, self).get_form(form_class)
          initial = self.request.GET['source']
          initial = Susbtance.objects.get(reg_num=initial)
          form.instance.origen = initial
          return form


      def form_valid(self, form):
          y = super(QualityControlCreate, self).form_valid(form)
          if 'approve' in request.POST:
              request.session['status'] = 1

          source = "000001"
          source = Substance.objects.get(reg_num=source)
          status = SubstanceStatus(status=1, comments="")
          status.save(commit=false)
          status.source = source
          status.save()
          return y

编辑:

因此,我在阅读How to pass kwargs from save to post_save signal之后得到了解决方法。

问题是我可以从接收方创建的模型中访问属性并使用getattr,但是我仍然无法传递属于要实例化的模型的变量。所以我可以通过Source和quality_control,但不能传递状态或评论...

编辑#2:

只是碰碰。我无法解决这个问题。也许自定义类会做到这一点?不确定如何在CreateView中使用它们...

1 个答案:

答案 0 :(得分:-1)

尝试将此def添加到您的CreateView类中。出于非调试目的,请删除print语句,然后将表单错误返回到其他视图或CreateView作为上下文以提供用户反馈。

def form_invalid(self, form):
        print("form is invalid")
        print(form.errors)
        return http.HttpResponse("form is invalid.. this is just an HttpResponse object")

希望这会有所帮助!