Django bootstrap modal after form submission - django

I am working with django and have a bootstrap3 'contact' form that I submit after jquery validation. This is working correctly and I now want to redirect to a bootstrap modal 'thank you' page. I'm not exactly sure how to do this in Django. In my main page, under the form I've added:
<div class="row">
<div class="col-lg-5 col-lg-offset-1 col-sm-push-6 col-sm-6"
<div class="clearfix"></div>
<h2 class="section-heading">Registration form</h2>
{% block 'form' %}
{% endblock %}
</div>
<a data-toggle="modal" href="#thanksModal">thanksModal</a>
{% include "thanks.html" %}
<div class="col-lg-5 col-sm-pull-6 col-sm-6">
<img class="img-responsive" src="../static/img/dog.png" alt="" />
</div>
</div>
The modal itself is:
<div class="modal hide" id="thanksModal">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
</div>
<div class="modal-body">
<h1>Thank you</h1>
</div>
<div class="modal-footer">
<input name="cancel" class="btn" type="submit" value="Cancel"/>
</div>
</div>
In my view I have:
def contact(request):
errors = []
if request.method == 'POST'
if not request.POST.get('subject', ''):
errors.append('Enter a subject.')
if not request.POST.get('message', ''):
errors.append('Enter a message.')
if request.POST.get('email') and '#' not in request.POST['email']:
errors.append('Enter a valid e-mail address.')
if not errors:
send_mail(
request.POST['subject'],
request.POST['message'],
request.POST.get('email', 'noreply#simplesite.com'),
['administrator#simplesite.com'], #email address where message is sent.
)
return HttpResponseRedirect('/thanks/')
return render(request, 'form.html',{'errors': errors})
def thanks(request):
return render_to_response('thanks.html')
As it is currently, I see an unclickable link that says 'thank you' on the main page and upon submission a redirection occurs to the 'contact' page. How can I get this working?

If I understand correctly, after the contact form is submitted you want a modal to appear saying thanks.
Instead of:
return HttpResponseRedirect('/thanks/')
Do:
import json
...
return HttpResponse(json.dumps({"success":True}), content_type="application/json")
And in your JS that submits the form check the response for success before reloading the HTML form:
if (typeof jqXhr.success != 'undefined') {
$('#success-modal').modal('show');
} else {
$('#my-form').html(jqXhr);
}

Related

Simple Django Form with Ajax Submission Not Updating Model

I'm trying to write a simple form using Ajax. After multiple attempts, I keep getting "POST /app/emails/ HTTP/1.1" 200 13950 in Terminal, but the model doesn't update (even when I look in the shell).
I really would like the abilityt to submit the form within the modal, and update the image behind it. However if that's not possible I can settle for an alternative.
Really stuck here, would love any advice!
emails.html
<div class="modal fade" id="addEmailModal" data-bs-backdrop="static" data-bs-keyboard="false"
tabindex="-1" aria-labelledby="staticBackdropLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered modal-sm">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="staticBackdropLabel">Add New Email</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"
aria-label="Close"></button>
</div>
<div class="modal-body">
<form method="POST" id='add-email'>
{% csrf_token %}
<fieldset class="form-group">
{{ form|crispy }}
</fieldset>
<div class="form-group">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close
</button>
<button class="btn btn-primary" type="submit">Add</button>
</div>
</form>
</div>
</div>
</div>
Javascript
$("#add-email").submit(function (e) {
e.preventDefault();
alert('working');
$.ajax({
type: 'POST',
url: "{% url 'add-emailname' %}",
data: {
email_name = $(this).email_name,
cadence = $(this).cadence
},
success: function (response) {
alert("Email name successfully added!")
$("#add-email").trigger('reset'); //clear the form
},
error: function (response) {
// alert the error if any error occured
alert(response["responseJSON"]["error"]);
}
})
}
views.py
def emails(request):
context = {
'emails': UserEmail.objects.all(),
'form': EmailCreateForm()
}
return render(request, 'app/emails.html', context)
def addEmailName(request):
if request.is_ajax and request.method == "POST":
form = EmailCreateForm(request.POST)
if form.is_valid():
form.save()
returned_email_name = form.cleaned_data.get('email_name')
messages.success(request, f'{returned_email_name} added as new Email!')
# send to client side.
return JsonResponse({"success": True}, status=200)
else:
# some form errors occured.
return JsonResponse({"error": form.errors}, status=400)
# some error occured
return JsonResponse({"error": ""}, status=400)
forms.py
class EmailCreateForm(ModelForm):
class Meta:
model = UserEmail
fields = ['email_name', 'cadence']
def __init__(self, *args, **kwargs):
super(EmailCreateForm, self).__init__(*args, **kwargs) # Call to ModelForm constructor
self.fields['email_name'].widget.attrs['rows'] = 1
self.fields['cadence'].widget.attrs['rows'] = 1
urls.py
urlpatterns = [
path('', views.home, name='app-home'),
path('emails/', views.emails, name='app-emails'),
path('post/ajax/addEmailName', addEmailName, name='add-emailname')]

Why isn't my page redirecting after I submit the form or refresh the page in Django?

I am working on a Django application but I am not getting the desired results. The create_job page is not rendering after I submit the the form or refresh the entire page.
This is the create_job_page view
def create_job_page(request):
current_customer = request.user.customer
if not current_customer.stripe_payment_method_id:
return redirect(reverse('customer:payment_method'))
# return render(request, 'customer/create_job.html')
# Filtering
create_job = Job.objects.filter(customer=current_customer, status=Job.CREATING_STATUS).last()
step1_form = forms.JobCreateStep1Form(instance=create_job)
if request.method == 'POST':
if request.POST.get('step') == '1': #If it's form one
step1_form = forms.JobCreateStep1Form(request.POST, request.FILES)
if step1_form.is_valid():
creating_job = step1_form.save(commit=False)
# Adding current customer to the form
creating_job.customer = current_customer
creating_job.save()
return redirect(reverse('customer:create_job'))
return render(request, 'customer/create_job.html', {
"step1_form": step1_form
})
This is the HTML code
<b>Create a Job</b>
<div class="tab-content" id="pills-Content">
<div class="tab-pane fade" id="pills-info" role="tabpanel" aria-labelledby="pills-info-tab">
<h1>Item Info</h1>
<form method="POST" enctype="multipart/form-data">
<b class="text-secondary">Item Information</b></br>
<div class="card bg-white mt-2 mb-5">
<div class="card-body">
{% csrf_token %}
{% bootstrap_form step1_form %}
</div>
</div>
<input type="hidden" name="step" value="1">
<button class="btn btn-primary" type="submit">Save & Continue</button>
</form>
</div>
In django i never use reverse, i generally just write redirect('app:url_name')

Django ImageField object not updating with input field

I tried updating a user's profile picture using a function view (ajax) but I keep getting the error below:
raise MultiValueDictKeyError(key)
django.utils.datastructures.MultiValueDictKeyError: 'emp_photo'
The same technique I am using is being used on CharField and TextField without issues.
Please see below for my codes.
views.py
#login_required(login_url='/login/')
#user_passes_test(user_type_combo)
def change_employee_photo(request, pk):
data = dict()
profile = get_object_or_404(Profile, pk=pk)
if request.method == 'POST':
form = EmployeePhotoForm(request.POST or None, request.FILES or None, instance=profile)
if form.is_valid():
newPic = profile(emp_photo=request.FILES['emp_photo'])
newPic.save()
data['is_valid'] = True
else:
form = EmployeePhotoForm(instance=profile)
data['form_is_valid'] = False
context = {
'form': form,
}
data['html_form'] = render_to_string('employees/partial_employee_photo.html',
context,
request=request
)
return JsonResponse(data)
forms.py
class EmployeePhotoForm(forms.ModelForm):
class Meta:
model = Profile
fields = ['emp_photo',]
{% load crispy_forms_tags %}
<form action="{% url 'change_employee_photo' form.instance.pk %}" class="js-change-employee-photo-form"
enctype="multipart/form-data" id="ProfileUpdateForm" method="post" runat="server">
{% csrf_token %}
<div class="modal-header">
<h5 class="modal-title">Change Employee Photo</h5>
<button aria-label="Close" class="close" data-dismiss="modal" type="button">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<div class="form-group col">
<div id="emp_photo_holder">
<img alt="{{profile.first_name}}_{{profile.last_name}}" height="200px" id="emp_img"
src="/media/default.jpg/" width="200px"/>
<input id="emp_photo" name="emp_photo" type="file" value="{{profile.emp_photo}}"/>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script>
function readURL(input) {
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function(e) {
$('#emp_img').attr('src', e.target.result);
}
reader.readAsDataURL(input.files[0]);
}
}
$("#emp_photo").change(function() {
readURL(this);
});
</script>
</div>
<div class="modal-footer">
<button class="btn btn-default" data-dismiss="modal" type="button">Close</button>
<button class="btn btn-warning confirmation"
onclick="return confirm('Are you sure you want upload a new photo for this employee?')"
type="submit">
<i class="fa fa-upload"></i> Upload
</button>
</div>
</form>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
I will most definitely appreciate any help to have this issue resolved.
i Guess you have forgot to mention the below lines in your settings.py
MEDIA_ROOT = os.path.join(BASE_DIR, "media")
MEDIA_URL = "/media/"
You can think of using request.FILES.getlist('emp_photo')
and additionally check if emp_photo key exists by printing it in your code if it holds some value.

Django: How to use modal as a form to update an object

I'm trying to use modal as a edit form but I don't know good way.
Currently my views.py is like this.
def edit_entry(request, entry_pk):
entry = get_object_or_404(Entry, pk=entry_pk)
if request.method != 'POST':
form = EntryForm(instance=entry, user=request.user)
else:
form = EntryForm(instance=entry, data=request.POST, user=request.user)
if form.is_valid():
form.save()
and I have a template for this view.
What I want to do is
from the page that lists a bunch of entry objects, the edit form for the object is shown when I click edit button.
{% for entry in entries %}
...
<button class="btn btn-outline-primary" data-toggle="modal" data-target="#editEntryModal">Edit</button>
<!-- modal for the object -->
Anyone who could give me tips?
You need to send back your form as html and stick it in the modal before you show it. so on click, you would first do you ajax request, and this will send back your form as html. For example,
def edit_entry(request, entry_pk):
....
entry = get_object_or_404(Entry, pk=entry_pk)
if request.method != 'POST':
form = EntryForm(instance=entry, user=request.user)
return HttpResponse(form.as_p()) # This will return the plain html of a form
....
Hope this helps!
I had a similar task and first created an ajax request from the template to load the data:
<script>
$(document).ready(function(){
$("#myBtn").click(function(){
var pk = $(this).data('pid')
$("#myModal").modal("show");
});
$("#myModal").on('show.bs.modal', function(event){
var modal = $(this)
var pk = $(this).data('pid')
$.ajax({
data: {'pk': pk},
url: "{% url 'search:load_paper' %}",
context: document.body,
error: function(response, error) {
alert(error);
}
}).done(function(response) {
modal.html(response);
});
});
});
</script>
The load_paper function looks like the following:
def load_paper(request):
pk = request.GET.get('pk')
object = get_object_or_404(Paper, pk = pk)
form = PaperForm(instance=object)
return render(request, 'edit_paper_modal.html', {
'object': object,
'pk': pk,
'form': form,
})
The data is rendered in the 'edit_paper_modal.html', which looks like this:
<div class="modal-dialog modal-lg" role="document">
<form action="{% url 'search:edit_paper' pk=object.pk %}" method="post" class="form" enctype="multipart/form-data">
{% csrf_token %}
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
<span class="sr-only">Close</span>
</button>
<h4 class="modal-title">Edit Paper</h4>
</div>
<div class="modal-body">
{% csrf_token %}
{{form|crispy}}
{{ form.media }}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<input type="submit" class="btn btn-primary" value="Save changes" />
</div>
</div><!-- /.modal-content -->
</form>
</div>
The key thing here is that I am passing the pk of the paper back to the edit_paper function in views.py which actually saves the form.
Hope this is useful!
what you are trying to possible only with django template.
you need js or jquery or any frontend framework .
when you click edit button A edit from will appeared in current dom and you need to make ajax call to get initial data for edit from. the edit the data and submit the data vai ajax and in backend update the object. django rest framework is more suitable for this kind of task.

pass parameter to form from template in Django 2

in Django I make a form which get an email address and save it in database and this my form.py:
class NewsletterUserSignUpForm(forms.ModelForm):
class Meta:
model = NewsletterUsers
fields = ['email']
def clean_email(self):
email = self.cleaned_data.get('email')
return email
and this is my views.py :
def newsletter_signup(request):
form = NewsletterUserSignUpForm(request.POST or None)
if form.is_valid():
instance = form.save(commit=False)
if NewsletterUsers.objects.filter(email=instance.email).exists():
messages.warning(request, 'Your Email Already Exist In Our DataBase.',
'alert alert-warning alert-dismissible')
else:
instance.save()
messages.success(request, 'Your Has Been Submitted To Our DataBase.',
'alert alert-success alert-dismissible')
context = {
'form': form,
}
return render(request, 'newsletter/subscribe.html', context)
the problem is here that this form has it own input which the input must put inside it but I want to design my own template and get input in my template then pass it to this form and my question is how do I can pass inputs in my .html template file to my form?
this is my html file and don't know to put what in href for input tag :
<form method="post" class="login100-form validate-form">
{% csrf_token %}
<span class="login100-form-title p-b-43">
Subscribe
</span>
<div>
<inputtype="email" name="Email">
<span class="label">Email</span>
</div>
<button type="submit" href="">
Subscribe
</button>
</div>
and what should I put in my href and how pass input to form from here?
In addition, I'm sorry for writing mistakes in my question.
From what I understand, you want to create your own custom input box and when that box is filled, you want the form input box to also get filled.
Hide the form input box using display:none.
Create your own custom input box, use javascript to fill the form input box when custom input box is filled.
Ex :
<script>
form_input_box = document.getElementById('id_of_form_input_box')
custom_input_box = documen.getElementById('id_of_custom_input_box')
$("id_of_custom_input_box").change(function(){
form_input_box.value = custom_input_box.value
});
</script>
the problem it was for my html code, I Should add an id and name attribute to my input tag and use this id and name for getting input from html and pass it to my form, and for href attribute I write the url that redirect to my form.
fixed html code:
<form method="post" class="login100-form validate-form">
{% csrf_token %}
<span class="login100-form-title p-b-43">
Subscribe
</span>
<div class="wrap-input100 container-login100-form-btn rs1 rs2 validate-input padding-50"
data-validate="Username is required">
<input id="email" maxlength="100" class="input100" type="email" name="email">
<span class="label-input100">Email</span>
</div>
<div class="container-login100-form-btn">
<button type="submit" href="{% url 'newsletter_subscribe' %}" class="login100-form-btn">
Subscribe
</button>
</div>
<div class="text-center w-full p-t-23">
<a style="font-size: 15px" href="{% url 'newsletter_unsubscribe' %}" class="txt1">
Click Here To Unsubscribe.
</a>
</div>
</form>