1

So I have a delivery model with a foreign key relation to customer. I would like to introduce the "add foreign key" button, just like the admin area does.

I've read the thread on the custom widget showed here: Django: adding an “Add new” button for a ForeignKey in a ModelForm Unfortunately I couldn't get it working, so I tried a different approach.

In the delivery form, I've added a "Add Customer" button. This button opens up a modal which shows a form to add a customer with ajax.

So I got the form working, it adds a new customer to the database without leaving the delivery form area. The trick is, I would like to have the newly added customer selected in the customer dropdown.

I need have to retrieve the customer.id from the newly created customer and select him or her in the dropdown, this is were I'm stuck. The ID is not available in the customer form yet so I would have to retrieve it from the database with GET...

Any thoughts about this? Any help would be greatly appreciated!

urls.py

urlpatterns += [  # Links to create, update and delete deliveries
url(r'^delivery/create/$', login_required(views.DeliveryCreate.as_view()), name='delivery_create'),
url(r'^delivery/add_customer/$', login_required(views.delivery_add_customer), name='delivery_add_customer'),
]

views.py

# A function based view to add a customer on the fly in the delivery form
def delivery_add_customer(request):
data = dict()

if request.method == 'POST':
    form = CustomerForm(request.POST)
    if form.is_valid():
        form.save()
        data['form_is_valid'] = True

    else:
        data['form_is_valid'] = False

else:
    form = CustomerForm()

context = {'form': form}
data['html_form'] = render_to_string('includes/partial_delivery_add_customer.html',
    context,
    request=request
)

return JsonResponse(data)

delivery_form.html

{% block content %}
<div id="modal_form" class="modal">
  <div class="modal-content"></div>
</div><!-- End of modal -->
<div class="container">
  <div class="row">
    <div class="card">
        <div class="card-action">
            <button class="btn orange modal-trigger js-delivery-add-customer" data-url="{% url 'delivery_add_customer' %}">
                <i class="material-icons btn__icon">add</i>
                Add Customer
            </button>
        </div>
        <form class="form-on-card" action="" method="POST">
          {% csrf_token %}
          {% form form=form %}
          {% endform %}
          <input button class="waves-effect waves-light btn" type="submit" value="Add" /></button>
        </form>
    </div>
  </div><!-- End of row -->
</div><!-- End of container -->
{% endblock %}

partial_delivery_add_customer.html

<form class="form-on-card--modal modal-trigger js-add-customer-form" action="{% url 'delivery_add_customer' %}" method="POST" novalidate>
<div class="row row--flex">
    <div class="col s12 m12 l8">
        <div class="form-content">
          {% csrf_token %}
          {% form form=form %}
          {% endform %}
        </div><!-- End of form content -->
    </div><!-- End of columns -->
</div><!-- End of row -->

delivery.js

$(function () {

  var loadForm = function () {
  var btn = $(this);

  $.ajax({
    url: btn.attr("data-url"),
    type: 'get',
    dataType: 'json',
    beforeSend: function () {
      $("#modal_form").modal("open");
      console.info('%c message: Function(loadForm): Open modal', 'color: green;');
    },
    success: function (data) {
      console.info('%c message: Function(loadForm): Insert form in modal', 'color: green;');
      $("#modal_form .modal-content").html(data.html_form);
    }
  });
};

  var saveForm = function () {
  var form = $(this);
  $.ajax({
    url: form.attr("action"),
    data: form.serialize(),
    type: form.attr("method"),
    dataType: 'json',
    success: function (data) {
        if (data.form_is_valid) {
            console.info('%c message: Function(saveForm): Open modal', 'color: green;');
            $("#id_customer_container .select-dropdown").val(); // Select the customer just saved
            $("#modal_form").modal("close");
      }
      else {
          console.info('%c message: Function(saveForm): Form data is invalid', 'color: red;');
          $("#modal_form .modal-content").html(data.html_form);
      }
    }
  });
    return false;
  };

  $(".js-delivery-add-customer").click(loadForm);
  $("#modal_form").on("submit", ".js-add-customer-form", saveForm);

});
Kevin D.
  • 315
  • 2
  • 19

1 Answers1

0

If your project uses bootstrap 3 or bootstrap 4, there is admin-like ForeignKey widget, which allows to add / delete foreign related instances:

https://django-jinja-knockout.readthedocs.io/en/latest/widgets.html#foreignkeygridwidget

It can be adapted to non-bootstrap layouts, but that would require additional work.

enter image description here

Dmitriy Sintsov
  • 3,821
  • 32
  • 20