与用户具有多对一关系的 Django CRUD 更新对象

Django CRUD update object with many to one relationship to user

我遵循了 Vitor Freitas 的精彩教程 How to Implement CRUD Using Ajax and Json。对于我的项目,我有一个与用户具有多对一关系的对象,我希望用户能够添加和更新该对象。我可以添加对象,但是当我尝试更新它时会抛出一个 ValueError: Cannot query "Case object": Must be "User" instance.

views.py

def case_update(request, pk):
    case = get_object_or_404(Case, pk=pk)
    if request.method == 'POST':
        form = CaseForm(request.POST, instance=case)
    else:
        form = CaseForm(instance=case)
    return save_case_form(request, form, 'cases/includes/partial_case_update.html')

当我尝试保存编辑时它中断了,但我正在努力寻找解决这个问题的方法。要编辑此案例,我需要表单作为此特定案例的实例,因为用户可能有很多案例。当我将实例设置为用户时,没有任何反应,当我完全删除实例时,它显然只是复制了一个案例,所以我有两个相同的案例。

如有必要,我可以 post 更多代码。谢谢

编辑 我仅使用 inlineformset 重构了我的代码并且它正在工作......有点。我现在可以编辑案例,但我仍然无法编辑单个案例。当我尝试使用内联表单集执行 case = get_object_or_404(Case, pk=pk) 的实例时,我继续收到 ValueError: Cannot query "Case object": Must be "User" instance。当我将其更改为用户实例时,它会显示该特定用户的所有案例,但它会正确保存。

def save_case_form(request, case_formset, template_name):
    data = dict()

    if request.method == 'POST':
        if case_formset.is_valid():
            case_formset.save()
            data['form_is_valid'] = True
            cases = Case.objects.all()
            data['html_case_list'] = render_to_string('cases/includes/partial_case_list.html', {
                'cases': cases
            })
        else:
            data['form_is_valid'] = False
    context = {'case_formset' : case_formset}
    data['html_form'] = render_to_string(template_name, context, request=request)
    return JsonResponse(data)


def case_create(request):
    if request.method == 'POST':
        case_formset = CaseFormset(request.POST, instance = request.user)
    else:
        case_formset = CaseFormset()
    return save_case_form(request, case_formset, 'cases/includes/partial_case_create.html')


def case_update(request, pk):
    case = get_object_or_404(Case, pk=pk)
    if request.method == 'POST':
        case_formset = CaseFormset(request.POST, instance=request.user)
    else:
        case_formset = CaseFormset(instance=request.user)
    return save_case_form(request, case_formset, 'cases/includes/partial_case_update.html')

forms.py

class CaseForm(forms.ModelForm):
    class Meta:
        model = Case
        fields = ('title', 'publication_date', 'author', 'price', 'pages', 'case_type', )


CaseFormset = inlineformset_factory(User,Case, 
                                    fields = ('title', 'publication_date', 
                                              'author', 'price', 
                                              'pages', 'case_type', ), 
                                    can_delete = False,
                                    extra = 1)

编辑

有效的非 DRY 实现:

forms.py

class CaseForm(forms.ModelForm):
    class Meta:
        model = Case
        fields = ('title', 'publication_date', 'author', 'price', 'pages', 'case_type', )


CaseFormset = inlineformset_factory(User,Case, 
                                    fields = ('title', 'publication_date', 
                                              'author', 'price', 
                                              'pages', 'case_type', ), 
                                    can_delete = False,
                                    extra = 1)

CaseFormsetUpdate = inlineformset_factory(User,Case, 
                                    fields = ('title', 'publication_date', 
                                              'author', 'price', 
                                              'pages', 'case_type', ), 
                                    can_delete = False,
                                    extra = 0)

views.py

def save_case_form(request, case_formset, template_name):
    data = dict()

    if request.method == 'POST':
        if case_formset.is_valid():
            case_formset.save()
            data['form_is_valid'] = True
            cases = Case.objects.all()
            data['html_case_list'] = render_to_string('cases/includes/partial_case_list.html', {
                'cases': cases
            })
        else:
            data['form_is_valid'] = False
    context = {'case_formset' : case_formset}
    data['html_form'] = render_to_string(template_name, context, request=request)
    return JsonResponse(data)


def case_create(request):

    if request.method == 'POST':
        case_formset = CaseFormset(request.POST, instance = request.user)
    else:
        case_formset = CaseFormset()
    return save_case_form(request, case_formset, 'cases/includes/partial_case_create.html')


def case_update(request, pk):

    case = get_object_or_404(Case, pk=pk)
    if request.method == 'POST':
        case_formset = CaseFormsetUpdate(request.POST, instance=request.user)
    else:
        case_formset = CaseFormsetUpdate(instance=request.user, queryset = Case.objects.filter(pk=pk))
    return save_case_form(request, case_formset, 'cases/includes/partial_case_update.html')

我无法找到一种方法来更改在视图中实例化的内联表单集上的额外参数。所以我刚刚制作了第二个,将额外设置为 0,并将其添加到我的更新案例视图中。我仍然对更好的方法感兴趣。

经过反复试验,我找到了解决办法。我一直在使用内联表单集,因为我一直在寻找指向那个方向的答案,但如果可能的话,我宁愿手动完成,而且我一直在尝试,但由于某种原因,我一直在这样做的方式在这种情况下不起作用。

我一直在尝试类似的东西:

case = form.save(commit = False)
case.user = request.user

form = (request.POST, instance = request.user)
form.save()

我遇到了 this solution,它现在可以在没有内联表单集的情况下按预期工作。

form.instance.user = request.user
form.save()

这看起来几乎与我一直在做的相同,但它奏效了。