Django UpdateView及其相关模型

Django UpdateView及其相关模型,django,django-class-based-views,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, b

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

#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))
我还有模型表单:TaskForm和TaskDetailsForm。与此无关。 这两个表格将同时显示和提交。 但它不更新Task和TaskDetails表中的现有记录,而是在这两个表中创建一个新记录

我认为我的问题在形式上有效。我应该在那里放什么?
非常感谢

方法后创建表单时没有实例。您必须在那里传递实例

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)

我认为这应该行得通。在这种情况下,您不需要
form\u valid
form\u 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:put
related\u name=task\u details
用于
OneToOneField
auto\u now\u add=True
用于任务的创建日期


尽管如此,为什么不将任务详细信息包含到任务中并停止使用此OneToOneKey?

您可以在代码中演示如何执行此操作吗?事实上,我在Django工作是新手!谢谢你,亲爱的。是的,这也行。但是你没有尽可能地使用
UpdateView
。这个也可以!但由于我正在学习并希望正确使用GCBV,我将选择的解决方案。没有问题(:我的项目中根本没有使用CBV,因此他的答案肯定更适合您的情况。此处
如果详细信息\u表单有效()
?我做了一些编辑来修复一些错误,但仍然出现了这个错误:“TaskDetails”对象没有属性“update”是的,因为您从
filter
更改为
get
。另一种方法是使用
task.task\u details
对象,并逐个更新其字段,但我是使用
filter
得到这个错误的:un哈希类型:“dict”如何解决它?现在可以了。小错误,它应该是
详细信息\u表单。清理的\u数据
而不是
{details\u表单。清理的\u数据}
,因为这已经是一个字典了