【问题标题】:Editing without using id hidden field in form?编辑而不使用表单中的 id 隐藏字段?
【发布时间】:2012-07-01 06:22:57
【问题描述】:

我不确定这是否是最简洁的编辑方式。但经过数小时的研究,这是我能想到的最好的。但是,我不喜欢我必须将 id 存储在隐藏字段中才能再次将其作为 POST 检索以实际更新模型的事实。

有没有更有效的方法?

def edit_contact_view(request):
    profile = request.user.get_profile()
    if 'id' in request.GET:
        try:
            id = request.GET['id']
            contacts = profile.company.contact_set.all()
            form = ContactsForm(profile.company, instance=contacts.get(id=id))
            form.data['id'] = id
            variables = RequestContext(request, {'form':form })
            return render_to_response("contact.html", variables)
        except Contact.DoesNotExist:
            raise Http404(_(u'Contact not found'))
    else:
        if request.method == 'POST':
            form = ContactsForm(profile.company, request.POST)
            if form.is_valid():
                contacts = profile.company.contact_set.all()
                contact = contacts.get(id=form.cleaned_data['id'])
                contact.last_name = form.cleaned_data['last_name']
                contact.save()
    return HttpResponseRedirect('/')

【问题讨论】:

    标签: django


    【解决方案1】:

    是的,你让这变得比它需要的更复杂。

    首先,在 Django 中,更常见的是在 URL 本身中传递 id,而不是在 GET 参数中 - 例如 /contact/edit/3/ 而不是 /contact/edit?id=3。例如,请参阅 this question 以了解如何配置这样的 URL。

    其次,无论您采用哪种方式,都无需在隐藏变量中传递 id,因为它已经可以从 URL 获得。您始终可以从那里获取实例。

    第三,我假设ContactForm 是一个ModelForm,但你没有使用save 功能,这进一步简化了事情。

    把它们放在一起:

    def edit_contact_view(request, id=None):
        profile = request.user.get_profile()
        if id is not None:
            contact = get_object_or_404(Contact, pk=id)
        else:
            contact = Contact(company=profile.company)
        if request.POST:
           form = ContactForm(request.POST, instance=contact)
           if form.is_valid():
               contact = form.save()
               return redirect(...)
    
        else:
            form = ContactForm(instance=contact)
        return render_to_response('contact.html', {'form': form})
    

    【讨论】:

    • 非常感谢丹尼尔,这个解决方案非常干净和完整。我已经实施了您的所有三个建议,并且效果很好。这么短,它结合了添加和编辑。唯一的事情是当我添加一个Contact 时,代码看到没有id,因此创建了一个Contact 的新实例以将其传递到一个表单中。一旦它以 POST 的形式返回,它会再次创建 Contact 的新实例并将其传递到表单中。请求.POST。这看起来让我有点困惑,为什么我们要创建一个新的 Contact 实例并将其再次传递到 POST 表单中。
    • 这只是为了简化模式——否则你需要一个额外的 if/else 围绕两个表单实例化。无论如何它只是一个未保存的实例,所以没有 db 调用。
    【解决方案2】:

    我一定是在这里遗漏了一些东西,但你为什么不按照标准对 url 中的 id 进行编码?

    即在urls.py:

    url('^/contact/?P<contact_id>[0-9]+)/edit/$', edit_contact_view, name='edit_contact_view')
    

    你的看法:

    def edit_contact_view(request, contact_id):
        profile = request.user.get_profile()
        contact = get_object_or_404(Contact, id=contact_id)
        if contact not in profile.company.contact_set.all():
            return Http404
    

    在你的模板中

    <form method="POST">
       {{ form.as_p }}
       ...
    </form>
    

    【讨论】:

    • 我认为get_object_or_404(profile.company.contact_set.all(), id=contact_id) 应该是get_object_or_404(Contact, pk=contact_id)
    • 好点 - get_object_or_404 采用模型类,而不是查询集。
    • 我也使用 pk 而不是 id 或任何你可能已经覆盖你的主键的东西,只是稍微少一点依赖模型。但是,总的来说,我同意您的方法。 (stackoverflow.com/questions/2165865/django-queries-id-vs-pk)
    • 其实get_object_or_404可以接受查询集。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-17
    • 1970-01-01
    • 1970-01-01
    • 2014-07-01
    • 1970-01-01
    相关资源
    最近更新 更多