AlliDeacon
AlliDeacon

Reputation: 1495

Django form POST resulting in 404

I am attempting to take in a form for update or delete, run the process and either return the updated url, or the updated list of objects. I've got the dynamic url building working, but when I hit submit I get a 404. I am struggling with the how to process the POST, as it doesn't even seem to be hitting that far in the code. Code below:

urls.py

    path("customers/", views.customers, name="customers"),
    path("customers/customer/<int:id>/", views.customer),

forms.py

    class CustomerMaintForm(ModelForm):
        class Meta:
            model = AppCustomerCst
            fields = ('id_cst', 'is_active_cst', 'name_cst', 'address_1_cst', 'address_2_cst', 'address_3_cst',
                      'city_cst', 'state_cst', 'zip_cst', 'country_cst', 'salesrep_cst', 'type_cst',
                      'is_allowed_flat_cst', 'iddef_cst', 'date_created_cst', 'date_suspended_cst',
                      'date_first_tran_cst', 'date_last_tran_cst', 'is_credit_hold_cst',
                      'old_balance_cst', 'balance_notify_cst', 'balance_statement_cst',
                      'balance_conversion_cst', 'balance_cst', 'receive_emails_cst',
                      'contact_domain_cst'
                      )
            labels = {'id_cst': 'Customer ID', 'is_active_cst': 'Active?', 'name_cst': mark_safe('<p>Name'),
                      'address_1_cst': 'Address 1',
                      'address_2_cst': 'Address 2', 'address_3_cst': 'Address 3', 'city_cst': 'City', 'state_cst': 'State',
                      'zip_cst': 'Zip', 'country_cst': 'Country', 'salesrep_cst': 'Sales Rep', 'type_cst': 'Type',
                      'is_allowed_flat_cst': 'Allowed Flat?', 'iddef_cst': mark_safe('<p>Id'),
                      'date_created_cst': 'Created Date', 'date_suspended_cst': 'Suspended Date',
                      'date_first_tran_cst': 'First Tran Date', 'date_last_tran_cst': 'Last Tran Date',
                      'is_credit_hold_cst': 'Credit Hold?', 'old_balance_cst': 'Old Balance',
                      'balance_notify_cst': 'Balance Notify', 'balance_statement_cst': 'Balance Statement',
                      'balance_conversion_cst': 'Balance Conversion', 'balance_cst': 'Current Balance',
                      'receive_emails_cst': 'Receive Emails?', 'contact_domain_cst': mark_safe('<p>Contact Domain')}

views.py

def customer(request, id):
    if request.method == "GET":
        obj = AppCustomerCst.objects.get(id_cst=id)
        instance = get_object_or_404(AppCustomerCst, id_cst=id)
        form = CustomerMaintForm(request.POST or None, instance=instance)
        ContactFormSet = modelformset_factory(AppContactCnt, can_delete=True, fields=(
            'name_cnt', 'phone_cnt', 'email_cnt', 'note_cnt', 'receives_emails_cnt'))
        formset = ContactFormSet(queryset=AppContactCnt.objects.filter(idcst_cnt=id), prefix='contact')
        tpList = AppCustomerTpRel.objects.filter(idcst_rel=id).select_related('idcst_rel', 'idtrp_rel').values(
            'idtrp_rel__id_trp', 'idtrp_rel__tpid_trp', 'idtrp_rel__name_trp', 'sender_id_rel', 'category_rel',
            'cust_vendor_rel')
        TPFormSet = formset_factory(TPListForm, can_delete=True)
        tp_formset = TPFormSet(initial=tpList, prefix='tp')
        doc_list = DocData.objects.document_list(id)
        DocFormSet = formset_factory(DocumentListForm)
        DocFormSet = formset_factory(DocumentListForm)
        doc_formset = DocFormSet(initial=doc_list, prefix='doc')
        context = {'form': form, 'formset': formset, 'tp_formset': tp_formset, 'doc_formset': doc_formset, 'id': id}
        print(form.errors)
        return render(request, 'customer.html', context=context)

    elif '_edit' in request.POST:
        print(id, request.POST)
        cust_name = request.POST['name_cst']
        instance = get_object_or_404(AppCustomerCst, name_cst=cust_name)
        form = CustomerMaintForm(request.POST, instance=instance)
        if form.is_valid():
            form.save()
            return HttpResponseRedirect("/customers/customer/{id}")
        else:
            context = {'form': form, 'contact_form': contact_form}
            return redirect(request, 'customer.html', context=context)

    elif '_delete' in request.POST:
        cust_name = request.POST['name_cst']
        instance = get_object_or_404(AppCustomerCst, name_cst=cust_name)
        form = CustomerMaintForm(request.POST, instance=instance)
        if form.is_valid():
            AppCustomerCst.objects.filter(id_cst=id).delete()
            return render(request, 'customers.html')

    else:
        pass

customer.html

{% extends 'base.html' %}
{% load crispy_forms_tags %}
{% url customer string %}
{% block content %}


<form method="post" action="/customer">
    {% csrf_token %}

    <div style="height:300px;overflow:auto;">
        {{ form }}
    </div>
    <input type="submit" value="Edit" name="_edit">
    <input type="submit" value="Delete" name="_delete">
</form>
{% endblock %}

Upvotes: 1

Views: 261

Answers (1)

markwalker_
markwalker_

Reputation: 12849

The 404 is because the form sends a POST to /customer and your URLs are

  • /customers/
  • /customers/customer/<int:id>/

So I'd first add a name to your path so it becomes something like path("customers/customer/<int:id>/", views.customer, name='customer')

Then change your form action to use django URL reversal;

<form method="post" action="{% url 'customer' id=id %}">

By doing this it'll generate the URL for you based on the ID of the customer form you're on, assuming id is in the context which it appears to be from your view code.

That should solve the 404 and improve things a little.

Upvotes: 1

Related Questions