Django UpdateView与相关模型

时间:2014-12-19 11:55:41

标签: django django-class-based-views

我有以下情况,我不知道如何进行更新:

#models.py
class Task(models.Model):
    creation_date = models.DateField(
        default=None,
    )
    name = models.CharField(
        max_length=255,
    )
    description = models.TextField(
        max_length=500,
        blank=True,
        null=True, 
    )

class TaskDetails(models.Model):
    PEND = 1
    COMP = 2
    TASK_STATUS = (
        (PEND, 'pending'),
        (COMP, 'completed'),
    )
    task = models.OneToOneField(
        Task,
        primary_key=True, 
        on_delete=models.CASCADE
    )
    solution = models.CharField(
        max_length=255,
    )
    due_date = models.DateField(
        null=True,
        default=None,
        blank=True,
    )    
    status = models.PositiveSmallIntegerField(
        default=1,
        choices=TASK_STATUS,
    )

现在我的观点

#views.py
class TaskUpdate(UpdateView):
    model = Task
    second_model = TaskDetails
    form_class = TaskForm
    second_form_class = TaskDetailsForm
    pk_url_kwarg = 'task_id'

    def get_context_data(self, **kwargs):
        context = super(TaskUpdate, self).get_context_data(**kwargs)
        if self.request.method == 'POST':
            details_form = self.second_form_class(self.request.POST, prefix='details')
        else:
            details_object = self.second_model.objects.get(pk=self.kwargs.get(self.pk_url_kwarg))
            details_form = self.second_form_class(instance=details_object, prefix='details')

        context['details_form'] = details_form
        return context

    def post(self, request, *args, **kwargs):
        self.object = self.get_object()
        form = self.form_class(request.POST)
        details_form = self.second_form_class(request.POST, prefix='details')
        if form.is_valid() and details_form.is_valid():
            return self.form_valid(form, details_form)
        else:
            return self.form_invalid(form, details_form)

    def form_valid(self, form, details_form):
        form.instance.creation_date = datetime.now().date()
        self.object = form.save()
        details_form.instance.task = self.object
        details_form.save()
        return HttpResponseRedirect(self.success_url)

    def form_invalid(self, form, details_form):
        return self.render_to_response(self.get_context_data(form=form, details_form=details_form))

我还有ModelForms: TaskForm TaskDetailsForm 。这里不相关。 这两个表格一次显示和提交。 但是,不是更新Task和TaskDetails表中的现有记录,而是在两个表中创建一个新记录

我认为我的问题出在 form_valid 。我该放什么? 非常感谢

2 个答案:

答案 0 :(得分:1)

帖子方法中,表单是在没有实例的情况下创建的。你必须在那里传递实例。

def post(self, request, *args, **kwargs):
    # get current task
    obj = self.get_object()
    #initiate the task form with this object as instance
    form = self.form_class(request.POST, instance=obj)

    #get realted details object or None. 
    #I can't check if this string works, but it should.
    details_obj = getattr(object, 'taskdetails', None)

    #initiate the details_form with this details_object as instance
    details_form = self.second_form_class(request.POST, prefix='details',
                                                        instance=details_obj)

    if form.is_valid() and details_form.is_valid():
        return self.form_valid(form, details_form)
    else:
        return self.form_invalid(form, details_form)

def form_valid(self, form, details_form):

    #save object
    obj = form.save(commit=False)
    obj.creation_date = datetime.now().date()
    obj.save()

    #save details_object
    details_obj = details_form.save(commit=False)
    details_obj.task = obj
    details_obj.save()

    return HttpResponseRedirect(self.success_url)

答案 1 :(得分:0)

我认为这应该有效。在这种情况下,您不需要form_validform_invalid方法,

def post(self, request, *args, **kwargs):
    response = super(TaskUpdate, self).post(request, *args, **kwargs)
    details_form = self.second_form_class(self.request.POST, prefix='details')
    if details_form.is_valid():
        task = self.get_object()
        self.second_model.objects.filter(task=task)
                                 .update(**details_form.cleaned_data)
        return response
    return render(request, self.template_name, {
        'form': self.get_form(self.get_form_class()),
        'details_form': details_form,
    })

PS:为related_name=task_detailsOneToOneField添加auto_now_add=True作为任务的创建日期

然而,为什么不将任务详细信息包含在任务中并停止使用此OneToOneKey?