【问题标题】:Django Python Forms - submitting complex view with multiple forms and formsetsDjango Python Forms - 提交具有多个表单和表单集的复杂视图
【发布时间】:2020-07-18 17:35:10
【问题描述】:

想象一下这个概念, 我有一辆出租车,可以由一个团体订购一整天多次访问,我应该为每次预订指定一个团体负责人。 现在我有一个预订 (PNR),其中包含 客户 旅行路线,以及为该预订分配的组长 (Operator)。

我的观点是:

  1. 选择运算符的表单
  2. 要添加 客户的表单集

在此视图中,我试图通过ajax 分别保存每个表单或通过视图底部的按钮保存表单的所有数据来使用户更轻松。

我已经搜索了几天,我在这两个链接12 上找到了最接近的方法,但仍然无法让我的代码正确运行并完成它应该做的事情。 :( 任何支持都将受到高度赞赏!

我的models.py

class Operator (models.Model):
    name = models.CharField(max_length=50)
    # Other Fields

    def __str__(self):
        return self.code


class PNR (models.Model):
    date_created = models.DateTimeField(auto_now_add=True)
    # Other Fields

    def __str__(self):
        return self.pk


class Client (models.Model):
    related_pnr = models.ForeignKey(PNR, on_delete=models.CASCADE)
    name = models.CharField(max_length=200)
    # Other Fields

    def __str__(self):
        return self.related_pnr+" "+self.name

我的forms.py

class ChooseOperatorCode(forms.Form):
    operator = forms.ModelChoiceField(queryset=Operator.objects.all())

    def clean(self, *args, **kwargs):
        operator = self.cleaned_data.get('operator')

        return super(ChooseOperatorCode, self).clean(*args, **kwargs)


class NewClientForm(forms.Form):
    name = forms.CharField(widget=forms.TextInput(attrs={}), label=False, max_length=200)
    # Other Fields

    def clean(self, *args, **kwargs):
        name = self.cleaned_data.get('name')
        # Other Fields

        return super(NewClientForm, self).clean(*args, **kwargs)

我的views.py

@login_required
def create_pnr(request):

    pnr = PNR.objects.create(created_by_user=request.user)

    choose_operator_form = ChooseOperatorCode(request.POST or None)
    if choose_operator_form.is_valid():
        pnr.created_by_operator = choose_operator_form.cleaned_data.get('operator')
        pnr.save()
        choose_operator_form.save()

    clients_form = NewClientForm(request.POST or None)
    if clients_form.is_valid():
        client = Client()
        client.related_pnr = pnr.pk
        client.name = clients_form.cleaned_data.get('name')
        client.save()
        clients_form.save()
    context = {
        'pnr': pnr.pk,
        'choose_operator_form': choose_operator_form,
        'clients_form': clients_form,
    }
    return render(request, 'reservation_new.html', context)


@login_required
def edit_pnr(request, pnr_id):
    pnr = PNR.objects.get(id=pnr_id) 

    choose_operator_form = ChooseOperatorCode(request.POST or None)
    if choose_operator_form.is_valid():
        pnr.created_by_operator = choose_operator_form.cleaned_data.get('operator')
        pnr.save()

    clients_form = NewClientForm(request.POST or None)
    if clients_form.is_valid():
        client = Client()
        client.related_pnr = pnr.pk
        client.name = clients_form.cleaned_data.get('name')
        client.save()
        clients_form.save()
    context = {
        'pnr': pnr.pk,
        'choose_operator_form': choose_operator_form,
        'clients_form': clients_form,
    }
    return render(request, 'reservation_edit.html', context)

我的url.py

    path('operation/reservation/new/', views.create_pnr, name='new_pnr'),
    path('operation/reservation/existing/<int:pnr_id>/', views.edit_pnr, 
       name='existing_pnr'),

最后是我的 template.html:(对于 newedit

<form  method="POST" action="{% url 'existing_pnr' pnr_id=pnr %}" id="choose_operator_form">
     {% csrf_token %}
     {{choose_operator_form}}
</form>
<form  method="POST" action="{% url 'existing_pnr' pnr_id=pnr %}" id="clients_form">
     {% csrf_token %}
     {{clients_form}}
</form>
<script type="javascript">
    $(document).('submit', '#choose_operator_form', function(e){
        e.preventDefault();

        $.ajax({
            type:'POST',
            url:"{% url 'existing_pnr' %}",
            data: $('#choose_operator_form').serialize(),
            success: function (result) {
                // show success msg
            },
            error: function (data) {
                // show error msg
            }
        });
    });

    //same code for clients form
</script>

【问题讨论】:

  • 有什么问题?什么不工作?你有错误吗?您的代码的某些部分是否没有按照您的预期执行?
  • 我想知道两件事,我是否可以实际应用这个概念让用户能够使用 ajax 分别保存每个表单并能够一次提交所有表单和表单集? 以及如何应用这种方法?当我点击保存choose_Operator_form 时,它给我的第二件事是'WSGIRequest' object has no attribute 'pnr'
  • 是的,从概念上讲,您可以这样做,只要您在通过 ajax 成功提交表单后将其删除,这样如果用户单击“全部提交”,它就不会被提交两次。
  • 但是我告诉过你,你为什么希望request.pnr 工作? pnr 来自哪里? Django 不知道pnr。通常,在编辑视图中,您在 url 中有要编辑的对象的 id,在 path (urls.py) 中定义一个变量并将其传递给您的视图,即 def edit_pnr(request, pnr_id): ...
  • {% url 'existing_pnr' pnr_id=pnr %}path('../&lt;int:pnr_id&gt;/', ...)

标签: django python-3.x ajax django-forms ajaxform


【解决方案1】:

pnr 不会被添加到 request 对象中,因此 request.pnr 没有任何意义。您需要通过URL传递PNRid,这样才能在视图中访问:

  • 在 urls.py 中,确保 edit_pnr 视图的 url 获得 pnr_id:类似于 path('pnr/&lt;int:pnr_id&gt;/edit/', ..., name="existing_pnr")
  • 在您的模板中,构造用于编辑 pnr 的 url,如下所示:{% url 'existing_pnr' pnr_id=pnr %}
  • 在您看来,接收pnr_iddef edit_pnr(request, pnr_id): ...

现在您可以像这样获取正在编辑的PNRpnr = get_object_or_404(PNR, pk=pnr_id),如果有人尝试访问不存在的PNR,它将正确返回 404 Not Found。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-11-27
    • 2019-07-27
    • 2011-07-13
    • 1970-01-01
    • 2019-04-13
    • 1970-01-01
    • 2011-06-17
    相关资源
    最近更新 更多