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>
Related
I am trying to add a modal dialog to confirm the user's comment. After user finishes editing title and comment then clicks submit button, a modal dialog will pop up for user to confirm. How can I get the data from html after user clicks confirm button on modal?
form.py
class PostForm(FlaskForm):
title_field = StringField('Title')
comment_field = TextAreaField('Comment')
submit = SubmitField('Update')
routes.py
#posts.route('/update_post/<post_id>', methods=['GET', 'POST'])
def post(post_id):
form = PostForm()
post= Post.query.get_or_404(post_id)
if request.method == 'POST':
print(form.title_field.data)
print(form.comment_field.data)
return redirect(url_for('posts.post'))
return render_template('post.html', title='Post', form=form, post=post)
post.html
<!-- form-->
<form action= "" method="POST", enctype="multipart/form-data">
{{ form.hidden_tag() }}
<p></p>
<h4>New Post</h4>
<div class="form-group">
{{ form.title_field.label(class="form-control-label") }}
{{ form.title_field(class="form-control form-control-lg") }} <!-- Pass this data> -->
</div>
<div class="form-group">
{{ form.comment_field.label(class="form-control-label") }}
{{ form.comment_field(class="form-control form-control-lg") }} <!-- Pass this data> -->
</div>
{{ form.submit( class="btn btn-outline-info", data_toggle="modal", data_target="#updateModal") }}
</form>
<!-- Modal -->
<div class="modal fade" id="updateModal" tabindex="-1" role="dialog" aria-labelledby="updateModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="updateModalLabel">New Post?</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<form action="{{ url_for('post.post', post_id=post.id) }}" method="POST">
<input class="btn btn-success" type="submit" value="Confirm">
</form>
</div>
</div>
</div>
</div>
#NoCommandLine Thanks for the help
This is the final solution I have come out
Change form.submit to a button
<button type="button" class="btn btn-outline-info" data-toggle="modal" data-target="#updateModal">Update</button>
Add onclick for modal button
<button type="button" class="btn btn-success" id="btnConfirm" onclick="form_submit()">Confirm</button>
Add Javascript
function form_submit(){
// Close the Modal
$("#updateModal").modal("hide");
// submit it
document.getElementById("mainForm").submit();
}
I would approach this a different way
Remove the form in the modal and just have a normal button with an id e.g. id="btnConfirm".
Give your main form an id e.g.
<form action= "" method="POST", enctype="multipart/form-data" id="mainForm">
When user clicks on the button (confirm), use Javascript to close the modal, and then submit your main form. Sample code (note - this is untested sample code; it might have some bugs)
$("#btnConfirm").on("click", function(){
// Close the Modal
$("#updateModal").modal("hide");
// Get the contents of the main form and submit it
fetch(<URL>, {
method:'POST',
body: new FormData($("#mainForm"))
});
})
I am using an automatically generated Bootstrap form to allow the user to upload files to the database. The form is generated inside a modal like this:
<div class="modal fade" id="uploadModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Dateien hinzufügen</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<form method="post" enctype="multipart/form-data">
<div class="modal-body">
{% csrf_token %}
{% bootstrap_form form %}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Abbrechen</button>
<button type="submit" class="btn btn-primary">OK</button>
</div>
</form>
</div>
</div>
</div>
using a Django form and file structure that look like this:
import django.forms as forms
from .models import StandaloneFile
# Create the form class.
class StandaloneFileForm(forms.ModelForm):
file = forms.FileField(widget=forms.ClearableFileInput(attrs={'multiple': True}))
class Meta:
model = StandaloneFile
fields = ['file', 'profile', 'description']
and
from django.db import models
# Create your models here.
def file_directory_path(instance, filename):
# file will be uploaded to MEDIA_ROOT/<profile.abbr>/<filename>
return '{0}/{1}'.format(instance.profile.abbr, filename)
class StandaloneFile(models.Model):
file = models.FileField(upload_to=file_directory_path)
profile = models.ForeignKey('MeasurementProfile',on_delete=models.SET_NULL,null=True)
description = models.TextField()
date_uploaded = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.file.name.split("/")[-1]
Now if I click the submit button the fields file, profile and description should be send via POST however if I look at request.POST only the fields file and profile are send and the variable file does not exist.
What did I do wrong here?
# This text is here to fill the answer to get to 30 characters minimum
request.FILES
I have created loginview using class-based view concept as following:
class LoginView(NextUrlMixin,RequestformattachMixin,FormView):
form_class = login_page
template_name = 'login.html'
success_url = '/'
def form_valid(self, form):
next_url=self.get_next_url()
return redirect(next_url)
def form_invalid(self, form):
return super().form_invalid(form)
forms.py:
class login_page(forms.Form):
Email = forms.EmailField(required=True,widget=forms.EmailInput(
attrs={"class": "form-control", "placeholder": "Email
address", "id": "exampleInputEmail2"}))
Password = forms.CharField(required=True,widget=forms.PasswordInput(attrs={"class": "form-control",'id':'exampleInputPassword2',
"placeholder": "Password"}))
I have modified on my login.html page to use bootstrap modal as the following:
{% block content %}
<div id="loginModal" class="modal fade">
<div class="loginModal-content">
<div class="loginModal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">Login</h4> </div><div class="loginModal-body">
<div class="row">
<div class="col-md-12"> via <div class="social-buttons">
<i class="fa fa-facebook"></i> Facebook
<i class="fa fa-twitter"></i> Twitter
</div>or
<form class="form" role="form" method="post" action="login" accept-charset="UTF-8" id="login-nav">
<div class="form-group">
<label class="sr-only" for="exampleInputEmail2">Email address</label>
{# <input type="email" class="form-control" id="exampleInputEmail2" placeholder="Email address" required>#}
{# {{ form.Email }}#}
</div>
<div class="form-group">
<label class="sr-only" for="exampleInputPassword2">Password</label>
{# <input type="password" class="form-control" id="exampleInputPassword2" placeholder="Password" required>#}
{# {{ form.Password }}#}
<div class="help-block text-right">
Forgot the password ?
</div>
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary btn-block">Sign in</button>
</div>
<div class="checkbox">
<label>
<input type="checkbox"> keep me logged-in
</label>
{{ form }}
</div>
</form>
</div>
<div class="bottom text-center"> New here ?
<b>Join Us</b> </div></div></div>
<div class="loginModal-footer">
</div>
</div>
</div>
{% endblock %}
As I am a newbie in Django, could you please help me how to use the bootstrap modal with my Django CBV
or even how to start as when I started using the Modal it is failed to appear, should I use ajax or what are other technologies should I use. please help from where could i start
Ok, the best way to render fields in django is django-widget-tweaks, this very simple and render all the error and fields with adding classes to that field.
Follow the installation of it - https://github.com/jazzband/django-widget-tweaks
here is simple and full guide of using django-widget-tweaks
I always suggest to use it, hope it will help you.
The plugin I wrote could be your starting point django-bootstrap-modal-forms. If you check the examples project you will also find a fully functional Login and Signup form in modals. You will be able to bind any form to the modal and all of the validation stuff will work out of the box.
You will create a trigger element opening the modal
Your selected form will be appended to the opened modal
On submit the form will be POSTed via AJAX request to form's URL
Unsuccessful POST request will return errors, which will be shown under form fields in modal
Successful POST request will redirects to selected success URL
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 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.