I am strating to learn Django and I want to display some forms in bootstrap modal view.
I have a template with a HTML table, this table have a column with a drop down button with several options.
the table is rendered with django-tables2 and the forms are rendered with django-crispy-forms
My form definition for the modal form:
class RecepcionForm(forms.ModelForm):
fecha_recepcion = forms.DateField(widget=DateInput())
def __init__(self,*args,**kwargs):
super(RecepcionForm,self).__init__(*args,**kwargs)
self.helper = FormHelper(self)
self.helper.layout = Layout(
Field('id_proveedor',
'anio',
'mes',
'usuario',
readonly = True
),
Fieldset('',
'fecha_recepcion',
'num_archivos',
Submit('save','Grabar'),
HTML('<a class="btn btn-danger" href={% url "monitor" %}>Cancelar</a>')
)
)
class Meta:
model = DetalleRecepcion
My view for the modal form:
#login_required(login_url='/login/')
def RecepModalView(request):
idp = request.GET.get('i')
anio = request.GET.get('a')
mes = request.GET.get('m')
if request.method == 'POST':
r = DetalleRecepcion.objects.get(id_proveedor=idp,anio=anio,mes=mes)
form = RecepcionForm(request.POST, instance=r)
if form.is_valid():
form.save()
return HttpResponseRedirect('/monitor/')
else:
r = DetalleRecepcion.objects.get(id_proveedor=idp,anio=anio,mes=mes)
r.usuario = request.user
form = RecepcionForm(instance=r)
return render_to_response('recepmodal.html',
{'form':form},
context_instance=RequestContext(request))
My template for the modal form
{% load crispy_forms_tags %}
<div class="modal fade" id="recmodal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title" id="myModalLabel">Register </h4>
</div>
<div class="modal-body">
<form action="" method=post">
<div class="tab-content">
<div class="tab-pane active" id="tab1">
{% crispy form %}
</div>
</form>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-primary">Submit</button>
</div>
</div>
</div>
</div>
I don't know how to open and pass arguments to the modal form.
I try using the django tag include
Example snippet:
<body>
<table>
.
.
.
</table>
{% include 'recmodal.html' %}
</body>
but I get this error
Exception Value: Failed lookup for key [form] in
In simple word how can I pass values and open a bootstrap modal form in django using django-crispy-forms.
Any advice
Thansk in advance
I know it's too late to answer, but I render my forms in a modal using this into a "modal-body" tag:
<form method="post">
{% csrf_token %}
{% form.as_p %}
</form>
I hope this work for all people like me that we came here finding an answer.
Regards.
Related
I want to do edit on a modal pop up form, edit is working but cant see the existing instance, how I can do it? any help is appreciated.
Here I have passed the form as below
class DomainListView(ListView):
model = Domain
template_name = 'super_admin/domain_list.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
form = DomainEditForm(self.request.POST or None)
context['form'] = form
return context
and the template is as follows
<div class="modal fade" id="domain-edit-{{ item.pk }}">
<div class="modal-dialog" role="document">
<form class="form-valide" action="{% url 'domain_edit' item.pk %}" method="POST" id=""
enctype="multipart/form-data">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title"> Edit Domain </h5>
<button type="button" class="close" data-dismiss="modal"><span>×</span>
</button>
</div>
<div class="modal-body">
<div class="basic-form">
<div class="form-group">
{% csrf_token %}
{{ form.errors }}
{{ form | crispy }}
</div>
</div>
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-primary">submit</button>
</div>
</div>
</form>
</div>
</div>
this is inside for loop along with list items, I tried to fetch the instance as follows in get context data override, but it gives key error
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
obj = get_object_or_404(Domain, kwargs={'pk': self.kwargs['pk']})
form = DomainEditForm(self.request.POST or None, instance=obj)
context['form'] = form
return context
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 ?
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>
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.
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>
How can I trigger the bootstrap modal to popup after my django form was submitted?
In my index.html template I have a standard looking modal like this
<div class="modal fade" id="exampleModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Modal title</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
...
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>
below in the same index.html I have a django form
{{ form.non_field_errors }}
{% csrf_token %}
<ul id="robul">
<div class="form-group">
<div class="col-xs-6">
<li id="name" name="{{ form.name.name }}" class="form-control">{{ form.name }}</li>
</div>
</div>
<div class="form-group">
<div class="col-xs-6">
<li id="email" class="form-control">{{ form.email }}</li>
</div>
</div>
<div class="form-group">
<div class="col-xs-6">
<li id="contactmessage" class="form-control">{{ form.contactmessage }}</li>
</div>
</div>
</ul>
in my view.py it looks like this:
if request.method == 'POST':
form = forms.FormName(request.POST)
if form.is_valid():
contact_name = request.POST.get(
'name', '')
contact_email = request.POST.get(
'email', '')
form_content = request.POST.get('contactmessage', '')
template = get_template('contact_template.txt')
context = {'name': contact_name,
'email': contact_email,
'contactmessage': form_content,}
content = template.render(context)
mail = EmailMessage("New contact form submission", content, "Some Name" +'', ['somegmail#gmail.com'],
headers = {'Reply-To': "noreply#gmail.com" })
mail.send()
return render(request, 'index.html', {'form': form})
The modal and JS code to trigger it live in a different context than your Django form submission code. Rendering 'index.html' is basically starting fresh when you're returning from your form submission, so it essentially amounts to showing the modal on page load. But, maybe you only want to show it after a successful submit. What you'll have to do is have some JS code to show the modal on page load, and have something in your template rendering context to conditionally render that. Here's what I'm thinking:
In index.html:
{% if successful_submit %}
<script type="text/javascript">
$(document).ready(function(){
$("#exampleModal").modal('show');
});
</script>
{% endif %}
In your view function, add the successful_submit context variable to your return:
return render(request, 'index.html', {'form': form, 'successful_submit': True})
Now, that <script> tag will only be rendered if successful_submit is True, which will only be set after a successful form POST.
I am using bootstrap to display my django forms but am having trouble getting them to resize. One of the forms is a text input area and I want it to span most of my panel width. I've tried multiple things but haven't been able to resize it/make the input area bigger.
The html:
<div class="container-fluid">
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="text-center">
Raw sQL Query
</h4>
</div>
<form action="/InterfaceApp/table_search/" method="post" class="form">
{% csrf_token %}
<div class="panel-body text-center">
{% bootstrap_form rawsQL %}
</br>
<div class="container-fluid">
<button type="submit" class="btn btn-primary center-block" value="Submit" name="rawsQL">
{% bootstrap_icon "fire" %} Submit
</button>
</div>
</div>
</form>
</div>
The form:
class TextFieldForm(forms.Form):
def __init__(self,*args,**kwargs):
section_label = kwargs.pop('section_label')
initial_value = kwargs.pop('initial_value')
required_val = kwargs.pop('required')
super(TextFieldForm,self).__init__(*args,**kwargs)
self.fields['text'].label=mark_safe(section_label)
self.fields['text'].initial=initial_value
self.fields['text'].required=required_val
text = forms.CharField()
Right now it looks like this:
Can anyone help me with making the input area wider??
Have a look at grid system and form control sizing.
So it turns out that when you pass in forms to django templates like {% bootstrap_form formname %} you have to go into where you defined the form to edit how it looks. I fixed my resizing issue by doing:
Form:
class TextFieldForm(forms.Form):
def __init__(self,*args,**kwargs):
section_label = kwargs.pop('section_label')
initial_value = kwargs.pop('initial_value')
required_val = kwargs.pop('required')
super(TextFieldForm,self).__init__(*args,**kwargs)
self.fields['text'].label=mark_safe(section_label)
self.fields['text'].initial=initial_value
self.fields['text'].required=required_val
text = forms.CharField(widget=forms.TextInput(attrs={'class':"form-control text-center",'placeholder':".col-md-8"}))
html:
<div class="col-md-8 centering">
{% bootstrap_form rawsQL %}
</div>
I'd like to show last_item in a Twitter-Bootstrap modal after django form submission, however I don't know how to handle the modal. I tried the form button suggested in documentation, but it doesn't process the form data. What do I have to do?
<button data-toggle="modal" data-target="#myModal2">Submit</button>
views.py
def main(request):
if request.method == 'POST':
form = MyModelForm(request.POST)
if form.is_valid():
name = form.cleaned_data['name']
request.session['name'] = name
mm = MyModel.objects.create(name=name)
mm.save()
return HttpResponseRedirect('/') # Redirect after POST
else:
form = MyModelForm()
args = {}
args['last_item'] = MyModel.objects.all().order_by('pk').reverse()[0]
args['form'] = form
return render(request, 'form.html', args)
form.html
{% extends "base.html" %}
{% block content %}
<form method="POST" id="" action="">
{% csrf_token %}
{{ form.as_p }}
<button>Submit</button>
</form>
<div class="modal" id="myModal2" tabindex="-1" role="dialog"
aria-labelledby="myModal2Label" aria-hidden="true" style="display: none">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h3 id="myModal2Label">Modal header</h3>
</div>
<div class="modal-body">
<p>Last item: {{ last_item }}</p>
</div>
</div>
{% endblock %}
{% block scripts %}
{% endblock %}
It seems like bootstrap calls event.preventDefault() on click, which prevents the form from being submited.
You should bind your own event on this button and close the modal programaticaly.
It could look like:
$('form').submit(function() {
$('#myModal2').modal('hide');
})
I did not test this code but it should be a good start.