1

Rather a curious problem: My modal works perfectly until I associate the template containing it with a CreateView! So for example if I change template_name in BrandCreateView to new_brand_form1.html, new_brand_form2.html will load perfectly in the modal. But as it stands now, when I click the button that triggers the modal, I get this.

views.py:

class BrandCreateView(SuccessMessageMixin ,generic.edit.CreateView):

    template_name = 'new_brand_form2.html'
    model = Brand
    fields = ['name']


    def get_success_url(self):
        current_business = Business.objects.filter(owner=self.request.user).first()

        current_business.brands.add(self.object.pk)
        return reverse_lazy('index', kwargs={'pk': self.object.pk})

    # pre assign-current business to the business field
    def get_initial(self):
        initial = super().get_initial()
        initial['business'] = Business.objects.filter(owner=self.request.user).first()
        self.business_name = initial['business']
        return initial

    def form_valid(self, form):
        form.instance.user = self.request
        form.instance.business = self.business_name
        try:
            return super(BrandCreateView, self).form_valid(form)
        except IntegrityError:
            form.add_error('name' ,'You already have a brand by that name')
            return self.form_invalid(form)

new_brand_form2.html:

<div class="modal fade" tabindex="-1" role="dialog" id="createbrand">
  <div class="modal-dialog" role="document">
    <div class="modal-content">
      <div class="modal-header">
        <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
        <h4 class="modal-title">Modal title</h4>
      </div>
      <div class="modal-body">
        <form class="form-horizontal">
            {{ form.as_p }}
        </form>
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
        <button type="button" class="btn btn-primary">Save changes</button>
      </div>
    </div><!-- /.modal-content -->
  </div><!-- /.modal-dialog -->
</div>

EDIT:

Might this be the problem? The button that triggers the modal obviously points to the the URL that is associated with the CreateView in the urls.py (named 'createbrand`), maybe it's going in an un-ending cycle...?

Here's the button that triggers the modal

<button class="btn btn-default btn-sm" type="button" data-toggle="modal" href="{% url "createbrand" %}"  data-target="#createbrand">
   <span class="glyphiconglyphicon-plus">Add New</span>
</button>
zerohedge
  • 1,968
  • 1
  • 19
  • 50

1 Answers1

2

You're trying to set href attr to HTML button tag?

Anyway, your button after your click tryin to act like a bootstrap-modal since you add all attributes need for it. That's why maybe you get some bootstrap-modal acting in your page. But in fact, it cannot find data-target="#createbrand" in your page, because your modal is somewhere else :)

Try these:

modal-snippet.html:

<div class="modal fade" tabindex="-1" role="dialog" id="createbrand">
  <div class="modal-dialog" role="document">
    <div class="modal-content">
      <div class="modal-header">
        <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
        <h4 class="modal-title">Modal title</h4>
      </div>
      <form method="POST" action="{% url 'createbrand' %}" class="form-horizontal" id="brandForm">
      <div class="modal-body">

            {% csrf_token %}
            <input type="text" id="id_your_field_name"  name="your_field_name" placeholder="Enter..."/>

      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
        <button type="submit" class="btn btn-primary">Save changes</button> <!-- onclick="addBrand()" -->
      </div>
      </form>
    </div><!-- /.modal-content -->
  </div><!-- /.modal-dialog -->
</div> 

{% block javascript %}
// You can use also AJAX request, but you 
// need to change your view and add onclick for this method to button
function addBrand(e){
    var brandForm = $("#brandForm");

    $.ajax({
        type: 'POST',
        url: "{% url 'createbrand' %}",
        data: brandForm.serialize(),
        success: function(res){
            if(res.msg !== "Error") {
               // Do something if error
            } else {
               // Do something if success
            }
    }
})}
{% endblock javascript %} 

views.py:

// I believe you can make it better
def add_brand(request):
    if request.method == "POST":
        form = BrandForm(request.POST)

        if form.is_valid():
            form.save(commit=True)
    return reverse_lazy('your-page')

urls.py:

...

from .views import add_brand
url(r'^url/path/$', add_brand, name='createbrand'),

...

And in your main page where you want to place your modal add:

{% include 'app/snippets/modal-snippet.html' %}
catscoolzhyk
  • 545
  • 4
  • 25
  • 1
    Thanks. Same problem. I copied your code as is, removing comments. It's working when I visit the actual `CreateView` URL (displays error, redirects on success, saves model), but when invoking the modal it doesn't display at all, get the same screen as before. – zerohedge Nov 04 '17 at 12:16
  • By the way, the modal *is* "loading" in the page source. and its attributes are changing when I press the button. [Here's a screenshot](https://imgur.com/a/eetBF). – zerohedge Nov 04 '17 at 12:20
  • 1
    I can confirm 100% that the modal is being called. If I change the `data-target` from `#createbrand` to `#justastring`, then absolutely nothing happens when I click the button, but if it's set correctly to `#createbrand`, then the screen turns darker but the modal never actually shows up (even though its attributes show in source). I'm pretty much at loss on what to do now. [Here's my full page source after your code](https://pastebin.com/AgvrecH7). – zerohedge Nov 04 '17 at 12:33
  • @zerohedge sorry dude, i was writing almost sleepy at last time :) I've edit answer, you can check the difference. In my answer actually, we don't use CreateForm instead for the form we manually add field inputs like ``. And in your view add also redirecting to your main page. I've tried it on my own. Should Work – catscoolzhyk Nov 04 '17 at 14:41
  • also you can safely remove `href` from your button or anchor `Add new` it is not necessary – catscoolzhyk Nov 04 '17 at 14:54
  • to make some debugging try to add some `print("I'm in testing view, passing ", request.POST)` to make sure that you have been reached your view. – catscoolzhyk Nov 04 '17 at 14:57
  • really want to accept your answer as I'm making progress, but I'm still stuck in a cycle: Now the object is being created in the modal perfectly (and saved to db), but because the form action is the same as the view, after the modal I also get the next screen in /createbrand, with only a submit button, and that one is obviously not a valid form. A little hard to expain. – zerohedge Nov 04 '17 at 23:01
  • I actually think the POST request should be handled by the index view, not the add_brand? That will solve the "stuck in a cycle" issue. – zerohedge Nov 04 '17 at 23:03
  • Ok. I got to work by redirecting but now there's no error validation at all. – zerohedge Nov 04 '17 at 23:35
  • @zerohedge let me clarify. As I see, you want to create something on your index view. And it has a related field with `Brand`. So, you want to create a `Brand` if it does not exist in your options? That is why you use a modal to create and update your `Brand`s. In your code, you have two different forms of different actions for the different views, but I think there is a problem, when you click submit button what's going on? Which form is submitting? And how do trigger each form? You may see these links: [link](https://stackoverflow.com/questions/392784/how-to-process-two-forms-in-one-view) – catscoolzhyk Nov 05 '17 at 00:05
  • And [here](https://stackoverflow.com/questions/1395807/proper-way-to-handle-multiple-forms-on-one-page-in-django) – catscoolzhyk Nov 05 '17 at 00:06
  • I've decided to take your AJAX code and verify everything with the view and handling the response on the modal. A lot of hard work injecting stuff but the result is worth it. With some modifications, I was able to use your answer and get to my solution. – zerohedge Nov 05 '17 at 00:47
  • @zerohedge totally agree! I'm really happy for you. – catscoolzhyk Nov 05 '17 at 00:55