【问题标题】:Django - ModelForm Create or Update? [duplicate]Django - ModelForm 创建还是更新? [复制]
【发布时间】:2012-04-29 15:27:39
【问题描述】:

我需要一个允许创建或添加计划会话的表单

型号

class Session(models.Model):
    tutor = models.ForeignKey(User)
    start_time = models.DateTimeField()
    end_time = models.DateTimeField()

表格

class SessionForm(forms.ModelForm):
    class Meta:
        model = Session
        exclude = ['tutor']

视图呈现表单

def editor(request):
    if request.method == 'GET':
        if request.GET['id'] != '0':
            # The user has selected a session
            session = Session.objects.get(id=request.GET['id'])
            form = SessionForm(instance=session)
        else:
            # The user wants to add a new session
            form = SessionForm()
        return render_to_response('planner/editor.html',
            {'form': form,}, context_instance=RequestContext(request),)

模板editor.html

<form action="/planner/post" method="post">{% csrf_token %}
{{ form.as_p }}
</form>

查看以发布值

def post(request):
    if request.method == 'POST':
        form = SessionForm(request.POST)
        if form.is_valid():
            form.instance.tutor = request.user
            form.save()
            obj = {'posted': True}
            return HttpResponse(json.dumps(obj), mimetype='application/json')
        else:
            return render_to_response('planner/editor.html',
                form, context_instance=RequestContext(request),)

问题

会话总是被创建(从不更新)

问题

  • 在我看来post 我怎么知道会话必须更新而不是创建?
  • 有没有办法简化这段代码?

【问题讨论】:

  • 解决方案:将实例传递给表单,目前它没有什么可更新的。
  • 这确实是个问题,但我怎样才能得到实际的实例呢?我是否必须手动将 id 添加到模板中?
  • 您希望您的应用如何知道该做什么:创建新会话或编辑现有会话?我认为标准的解决方案是为这些使用不同的 URL。
  • 编辑器或帖子的不同 URL ?我知道我的视图不知道是否必须创建会话。现在我想知道获取实际实例的最佳/简单方法。

标签: django django-models django-forms django-views


【解决方案1】:

如果要更新会话,需要在绑定表单时提供实例。

如果表格有效,您可以savecommit=False,并更新导师。

form = SessionForm(instance=instance, data=request.POST)
if form.is_valid():
    instance = form.save(commit=False)
    instance.tutor = request.user
    instance.save()

【讨论】:

  • 如果我不知道已发布会话的 ID,我如何拥有实例?我是否必须手动将其添加到 html 表单中?
  • 在 Django 中,通常会在您的 url 中包含对象的 id(例如,参见 part 3 of the tutorial)。如果您不这样做,那么您可以将 id 作为GETPOST 参数包含在内。您必须手动将其添加到表单中。顺便说一句,您可能需要确保用户有权更改他们尝试编辑的会话。
  • 所以你认为我的模板表单应该像&lt;form action="/planner/post/{{ form.id }}" method="post"&gt;
  • 就是这样,虽然reverse your urls是个好习惯,那么你可以action="{% url edit_session session.pk %}"
  • 好的,我明白了,谢谢。使用 URL 调度器来放置参数对我来说还不自然
【解决方案2】:
from django.shortcuts import render_to_response, get_object_or_404
from django.http import HttpResponseRedirect, Http404
from django.template import RequestContext
from application.models import Session
from application.forms import SessionForm

def allInOneView(request):
    session_id = request.POST.get('session_id')

    if session_id:
        session = get_object_or_404(Session, pk=session_id)
    else:
        session = None

    """
    A subclass of ModelForm can accept an existing model instance 
    as the keyword argument instance; 
    if this is supplied, save() will update that instance. 
    If it's not supplied, save() will create a new instance of the specified model.
    """
    form = SessionForm(instance=session)

    if request.method == 'POST':
        form = SessionForm(request.POST, instance=session)
        if form.is_valid():
            form.save()
            return HttpResponseRedirect(request.path)

    return render_to_response('planner/editor.html', {
        'form': form
    }, context_instance=RequestContext(request))

【讨论】:

  • 您的回答对我来说似乎是最有趣的(尚未测试)。可以输入if session_id 吗?它不是总是会评估为False 吗?
  • request.POST.get() 方法返回给定键的值。如果密钥不可用,则返回默认值 None。如果您在变量中设置了任何值,则不会将其评估为 False。
  • 实际上.. 我猜 request.POST.get() 可以更改为 request.REQUEST.get() 所以它可以同时处理 GET 和 POST 请求; stackoverflow.com/a/4162731/784642
【解决方案3】:

我现在通常做的(按照这里提到的建议)只使用一个视图,将可选的 session_id(没有用于创建的 session_id)传递给 URL 调度程序。

<form action="{% url session_edit session_id=session_id|default_if_none:"" %}"
    method="post">{% csrf_token %}
{{ form.as_p }}
</form>
url('^planner/edit$', session_edit, name='session_edit'),
url('^planner/edit/(?P<session_id>\d+)$', session_edit, name='session_edit'),

我发现重新组合所有 4 个案例

  • 获取创作表格
  • 获取更新表单
  • 帖子创建表单
  • 更新后表单

进入一个视图更易于维护。

【讨论】:

    【解决方案4】:

    在一个视图中完成所有操作。类似的东西:

    def session_manager(request):
    
        session = None
        try:
            session = Session.objects.get(id=request.POST['id'])
        except Session.DoesNotExist:
            pass
    
        if request.method == "POST":
           kwargs = {
                data = request.POST
           }
           if session:
                # Update
                kwargs['instance'] session 
           form = SessionForm(**kwargs)
           if form.is_valid():
                ...
        else:
            form = SessionForm(instance=session)
    

    【讨论】:

    • 问题是id 从未在帖子视图中发布。我的编辑器模板就像{{ form.as_p }}。我应该手动输入id 吗?
    • 您可以尝试执行Session.object.get(tutor=request.user, start_time=request.POST['start_time'], end_time=request.POST['end_time']) 之类的操作,但将Session id 作为隐藏字段包含在表单中并使用它来检索Session 对象会更容易。
    • 我比较同意第二种方案,但是手动添加正常吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-05
    • 2020-07-24
    • 1970-01-01
    相关资源
    最近更新 更多