form is not saving changes in dialog modal (popup) Django

I’m really new in Django. I’m trying to implement Modal dialog using forms. The problem is that even when I make some changes in my form, this changes are not shown in database… I have no idea why. When I test form outside Modal dialog, form is working… Here is my form.py:

class anomalie_location_form(ModelForm):
    class Meta:
        model = Anomalie
        fields = ['localization', ]

here is my view.py

@login_required(login_url='login')
def fix_anomalie_stock(request, pk, type_anomalie):

    anomalie_pk = Anomalie.objects.get(id=pk)

    # form to change anomalie position
    form_location = anomalie_location_form(instance=anomalie_pk)
    if request.method == 'POST':
        print('printinng anomalie_location_form POST ', request.POST)
        form_location = anomalie_location_form(
            request.POST, instance=anomalie_pk)
        if form_location.is_valid():
            form_location.save()
            return redirect('/')

    context = {'anomalie_pk': anomalie_pk,
                'form_location': form_location}

    return render(request, "anomalie/fix_anomalie_stock.html", context)

and my html:

<div class="modal fade" id="myModal2" role="dialog">
    <div class="modal-dialog modal-lg">
        <div class="modal-content">
            <div class="modal-header">
                <h4>{{product.product_name }}</h4>
            </div>
            <form action="" method="POST">
                {% csrf_token %}
                <div class="modal-body">
                    {{form_location}}
                </div>
                <div class="modal-footer">
                    <input type="submit" class="btn btn-primary" value="Treter" data-dismiss="modal">
                </div>
            </form>
        </div>
    </div>
</div>

this is the model.py

class Anomalie (models.Model):
    ANOMALIE = (
        ("Etiquette absente", "Etiquette absente"),
        ("Etiquette decalee", "Etiquette decalee"),
        ("Etiquette inconnue", "Etiquette inconnue"),
    )

    ANOMALIE_STATE = (
        ("traité", "traité"),
        ("mise à jour", "mise à jour"),
        ("signalé", "signalé"),


    )
    type = models.CharField(
        max_length=200, choices=ANOMALIE, null=False)
    date_report = models.DateTimeField(null=False, blank=False)

  
    localization = models.TextField(max_length=30, null=False, blank=False)
    state = models.CharField(
        max_length=200, choices=ANOMALIE_STATE, null=False)
  
    aisle = models.ForeignKey(Aisle, null=True, on_delete=models.SET_NULL)
    product = models.ForeignKey(
        Product, null=True, on_delete=models.SET_NULL)
   

    def datepublished(self):
        return self.date_report.strftime('%B %d %Y')

    def __str__(self):
        return self.type

and this is the url.py

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', home_screen_view, name="home"),
    path('consult/<str:pk>/', consult_anomalie, name="consult_anomalie"),
    path('fix_anomalie_stock/<str:pk>/<str:type_anomalie>',
         fix_anomalie_stock, name="fix_anomalie_stock"),
   
]

So the question is why form is working outside of Dialog Modal ?

Upvotes: 2

Views: 1853

Answers (3)

Neeraj
Neeraj

Reputation: 783

Modal should be inside the form tag and not the other way around.

<form action="" method="POST">{% csrf_token %}

<div class="modal fade" id="myModal2" role="dialog">
    <div class="modal-dialog modal-lg">
        <div class="modal-content">
            <div class="modal-header">
                <h4>{{product.product_name }}</h4>
            </div>
                <div class="modal-body">
                    {{form_location}}
                </div>
                <div class="modal-footer">
                  <button type="button" class="btn btn-secondary" data dismiss="modal">Close</button>
                 <button type="submit" class="btn btn-primary">Save changes</button>
                </div>
        </div>
    </div>
</div>

</form>

Upvotes: -1

Achuth Varghese
Achuth Varghese

Reputation: 2451

The mistake is simple.

That is, the form in the modal have a submit button. This button has the bootstrap modal data-dismiss attribute which makes the modal to dismiss and not the form to submit.

<input type="submit" class="btn btn-primary" value="Treter" data-dismiss="modal">

Remove the bootstrap data-dismiss attribute from submit button.

<input type="submit" class="btn btn-primary" value="Treter">

Code snippet in action

Run the code snippet to see it in action. I've added the modal code from the question. Form submit() to alert the form data and 'hidden.bs.modal' to alert when modal closes. For demo purpose, form has two submit buttons. One with the data-dismiss attribute and the other without. You can see that the button (2) alerts the data while the other closes the modal

<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet"/>

<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>

<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#myModal2">
  Launch modal
</button>

<div class="modal fade" id="myModal2" role="dialog">
  <div class="modal-dialog modal-lg">
      <div class="modal-content">
          <div class="modal-header">
              <h4>Product Name</h4>
          </div>
          <form action="" method="POST">
              <div class="modal-body">
                  <input type="text" name="product" class="form-control">
                  (1) submit button with data-dismiss attribute<br>
                  (2) submit button without data-dismiss attribute
              </div>
              <div class="modal-footer">
                  <input type="submit" class="btn btn-primary" value="(1) Treter" data-dismiss="modal"> | <input type="submit" class="btn btn-primary" value="(2) Treter">
              </div>
          </form>
      </div>
  </div>
</div>
    
<script>
  $(document).ready(function() {
    console.log('start');
    $('form').submit(function() {
      alert($(this).serialize());
    })

    $('#myModal2').on('hidden.bs.modal', function (e) {
      alert('modal closes');
    })
  });
</script>

Upvotes: 2

Ozone
Ozone

Reputation: 1353

I'm missing some details but forms often don't submit properly when inputs are not named. Even your select elements need name and value pair parameters. Have you double checked this?

What can happen with bootstrap is that the modal can confuse the form action. You have it now set to = "". Try removing the action parameter and give your form a unique id.

if request.method == 'POST':

Also try checking if submit button was posted rather than just the request method.

Upvotes: 0

Related Questions