I need to compare a value (variable) extracted from a page to context.
For example:
Color is a dropdown selection.
$(document).ready(function(){
$("#color").change(function() {
var selected_color = $(this).val() ;
{% if context_value == selected_color %}
.. do something
{% endif %}
})};
Is this possible ? If not, is there some solution for such case ?
I recommend you use Ajax to communicate asynchronously between JavaScript and python (without refreshing the page).
your JS:
$(document).ready(function(){
$("#color").change(function() {
var selected_color = $(this).val() ;
$.ajax({
method: "POST",
url: 'color_check',
data: selected_color,
success: handleFormSuccess,
error: handleFormError,
})
})
function handleFormSuccess(data, textStatus, jqXHR){
.. do something
}
function handleFormError(jqXHR, textStatus, errorThrown){}
};
Your python view:
def color_check(request):
if request.is_ajax():
selected_color = request.POST
context_value = 'Red'
if selected_color == context_value:
return JsonResponse(True)
EDIT: Arun Singh's solution is simpler and works too. I would only make the paragraph hidden from the user:
<p style="display:none" id="my-data" data-name="{{context_value}}"></p>
<p id='data'>{{ context_value }}</p>
or
<p id="my-data" data-name="{{context_value}}"></p>
$(document).ready(function(){
$("#color").change(function() {
var selected_color = $(this).val() ;
var djangoData = $('#data').val();
if (djangoData === selected_color){
console.log('do something)
}else{
console.log('do something else')
}
})};
Related
I am doing a search page in which parameters are sent by ajax and then upon reception of the queryset I rebuild my cards. The whole thing is classic and working ok, here is a simplified version of the thing. Lots of lines killed or modified since it is not really the subject of the post
let getobject = async (value,url) => {
var res2 = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
"X-CSRFToken": getCookie("csrftoken"),
},
body: JSON.stringify({
value: value,
})
})
let data2 = await res2.json();
videoitems.innerHTML = ''
modalbin.innerHTML = ''
data2["data"].forEach(async item => {
if (item.ext == '.mp4') {
const dynamicreation = async () => {
let dyncontent3 = await createnewcard(item)
let placing = await videoitems.appendChild(dyncontent3);
}
const nooncares2 = await dynamicreation()
} else if (item.ext == ".pdf") {
const dynamicreation2 = async () => {
let dyncontent4 = await createnewcard(item)
let placing2 = await videoitems.appendChild(dyncontent4);
}
const nooncares4 = dynamicreation2()
}
})
}
the createnewcard function
var createnewcard = item => {
var dyncontent = document.createElement("div");
dyncontent.innerHTML =
`<div class="m-2 extralarge-modal video${item.id}">
<div data-reco="${item.id}"
class="extralarge-modal bg-white rounded-lg border border-gray-200 shadow-md dark:bg-gray-800 dark:border-gray-700">
<div class="p-5">
<p class="mb-3 font-normal text-gray-700 dark:text-gray-400">
${item.title}
</p>
</div>
</div>
</div>`;
return dyncontent
}
What I would like to know is if it would be possible to mix this js with the django "include" function and instead of using js template litterals use an html component of the card that I would include upon looping in the data reveived. I could also maybe include it inside the createnewcard js function but so far it all failed quite miserably.
Thanks a lot
Yes, you've to create card.html or whatever you can name then you've to just include inside your js make sure you use same variables while looping in js eg.(item)
card.html
<div class="m-2 extralarge-modal video${item.id}">
<div data-reco="${item.id}"
class="extralarge-modal bg-white rounded-lg border border-gray-200 shadow-md dark:bg-gray-800 dark:border-gray-700">
<div class="p-5">
<p class="mb-3 font-normal text-gray-700 dark:text-gray-400">
${item.title}
</p>
</div>
</div>
</div>
and inside your Js do like this
var createnewcard = item => {
var dyncontent = document.createElement("div");
dyncontent.innerHTML = `{% include "card.html" %}`
return dyncontent
}
I have an user profile where he can crop his image, and so after cropping, and printing data in view nothing is passed to view
Form
<form method="post" action="change_photo/" id="avatar_changing_form">
{% csrf_token %}
<label for="upload_image">
{% if item.image%}
<img src="{{item.image.url}}" alt="" style="max-height:300px">
{%else%}
<img src="{%static 'avatar_sample.png' %}" id="uploaded_image"
class="img-responsive img-circle" />
{%endif%}
<div class="overlay">
<div class="text">Click to Change Profile Image</div>
</div>
<!-- <input type="file" name="image" class="image" id="upload_image" style="display:none" /> -->
{{imageForm.image}}
</label>
</form>
JS & Ajax
$(document).ready(function(){
const imageForm = document.getElementById('avatar_changing_form')
const confirmBtn = document.getElementById('crop')
const input = document.getElementById('upload_image')
const csrf = document.getElementsByName('csrfmiddlewaretoken')
var $modal = $('#modal');
var image = document.getElementById('sample_image');
var cropper;
$('#upload_image').change(function (event) {
var files = event.target.files;
var done = function (url) {
image.src = url;
$modal.modal('show');
};
if (files && files.length > 0) {
reader = new FileReader();
reader.onload = function (event) {
done(reader.result);
};
reader.readAsDataURL(files[0]);
}
});
$modal.on('shown.bs.modal', function () {
cropper = new Cropper(image, {
aspectRatio: 1,
viewMode: 3,
preview: '.preview'
});
}).on('hidden.bs.modal', function () {
cropper.destroy();
cropper = null;
});
$('#crop').click(function () {
cropper.getCroppedCanvas().toBlob((blob) => {
console.log('confirmed')
const fd = new FormData();
fd.append('csrfmiddlewaretoken', csrf[0].value)
fd.append('file', blob, 'my-image.png');
$.ajax({
type: 'POST',
url: imageForm.action,
enctype: 'multipart/form-data',
data: fd,
success: function (response) {
console.log('success', response)
$modal.modal('hide');
$('#uploaded_image').attr('src', fd);
},
error: function (error) {
console.log('error', error)
},
cache: false,
contentType: false,
processData: false,
})
});
});
})
View
def change_photo(request):
if request.user.is_authenticated and Guide.objects.filter(user = request.user).exists():
item = Guide.objects.get(user=request.user)
if request.method == "POST":
Photoform = ChangeImageForm(request.POST or None, request.FILES or None, instance = item)
if Photoform.is_valid():
print(Photoform.cleaned_data['image'])
Photoform.save()
return HttpResponseRedirect('/profile/')
form
class ChangeImageForm(ModelForm):
class Meta:
model = Guide
fields = ['image']
def __init__(self, *args, **kwargs):
super(ChangeImageForm, self).__init__(*args, **kwargs)
self.fields['image'].widget = FileInput(attrs={
'name':'image',
'class':'image',
'id':'upload_image',
'style':'display:none'
})
When i print image field from cleaned data in terminal displays "none", and when i load image through admin everything working good, can pls someone tell me where the problem is?
Each form's input is associated with a unique data-comment-pk. I'm trying to access the value of data-comment-pk of the input which is submitted. Currently, the AJAX success function's alert(comment_pk) is only fetching me the comment_pk of the first form. How can I access the comment_pk of the form which is submitted instead of getting the comment_pk of the first form?
html template
{% for comment in object_list %}
<h3>{{comment.comment}} by {{comment.username}}</h3>
<form class="score-form">
<input type="submit" value="Up" name="up" class="Up" data-comment-pk="{{comment.pk}}" />
<input type="submit" value="Down" name="down" />
</form>
{% endfor %}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>
<script>
$(".score-form").submit(function (e) {
e.preventDefault();
var comment_pk = $(".Up").attr("data-comment-pk");
var url = comment_pk + "/vote";
console.log(url)
$.ajax({
type: 'GET',
url: url,
data: { "up": 'UP' },
success: function (response) {
if (response["valid"]) {
alert(comment_pk);
}
},
error: function (response) {
console.log(response)
}
})
})
</script>
models.py
class CommentModel(VoteModel, models.Model):
comment = models.TextField()
username = models.ForeignKey(User, on_delete=models.CASCADE)
views.py
class CommentView(ListView):
model = CommentModel
def comment_vote(request, comment_id):
if request.is_ajax and request.method == "GET":
# do some stuff
return JsonResponse({"valid": True}, status=200)
Here is the solution to this problem :
var comment_pk = $(".Up", this ).attr("data-comment-pk");
Using this will return the current HTML element.
try: add "this" to before .Up in the comment_pk.
let me know if it works.
this- will get the currect form that have been submit and get the .Up Class
<script>
$(".score-form").submit(function (e) {
e.preventDefault();
var comment_pk = $("this .Up").attr("data-comment-pk");
var url = comment_pk + "/vote";
console.log(url)
$.ajax({
type: 'GET',
url: url,
data: { "up": 'UP' },
success: function (response) {
if (response["valid"]) {
alert(comment_pk);
}
},
error: function (response) {
console.log(response)
}
})
})
</script>
I am making a django app that displays a progress bar. So far I have got it working to display a progress bar using this library and the following code which they suggested.
<div class='progress-wrapper'>
<div id='progress-bar' class='progress-bar' style="background-color: #68a9ef; width:
0%;"> </div>
</div>
<div id="progress-bar-message">Waiting for progress to start...</div>
<script src="{% static 'celery_progress/celery_progress.js' %}"></script>
<script>
// vanilla JS version
document.addEventListener("DOMContentLoaded", function () {
var progressUrl =
"{%
try:
url 'celery_progress:task_status' task_id
catch:
pprint("PHEW")
%}";
CeleryProgressBar.initProgressBar(progressUrl);
});
</script>
However, how might i integrate the above code with the code below to get it to display success or error:
function customSuccess(progressBarElement, progressBarMessageElement) {
progressBarElement.innerHTML = (
'<figure class="image"><img src="/static/projects/images/aww-yeah.jpg"></figure>'
)
progressBarElement.style.backgroundColor = '#fff';
progressBarMessageElement.innerHTML = 'success!'
}
function customError(progressBarElement, progressBarMessageElement) {
progressBarElement.innerHTML = (
'<figure class="image"><img src="/static/projects/images/okay-guy.jpg"></figure>'
)
progressBarElement.style.backgroundColor = '#fff';
progressBarMessageElement.innerHTML = 'shucks.'
}
CeleryProgressBar.initProgressBar(taskUrl, {
onSuccess: customSuccess,
onError: customError,
});
just change the script in your html with this one:
<script>
function customSuccess(progressBarElement,
progressBarMessageElement) {
progressBarElement.innerHTML = (
'<figure class="image"><img src="/static/projects/images/aww-yeah.jpg"></figure>'
)
progressBarElement.style.backgroundColor = '#fff';
progressBarMessageElement.innerHTML = 'success!'
}
function customError(progressBarElement, progressBarMessageElement) {
progressBarElement.innerHTML = (
'<figure class="image"><img src="/static/projects/images/okay-guy.jpg"></figure>'
)
progressBarElement.style.backgroundColor = '#fff';
progressBarMessageElement.innerHTML = 'shucks.'
}
document.addEventListener("DOMContentLoaded", function () {
var progressUrl = "{% url 'celery_progress:task_status' task_id %}";
CeleryProgressBar.initProgressBar(progressUrl, {
onSuccess: customSuccess,
onError: customError,
});
});
</script>
i tried it with the same app. it works! :)
don't forget to change this one to a valid url:
<img src="/static/projects/images/aww-yeah.jpg">)
I was trying to implement on keyup search with django and jquery following this video
but when I try the code everytime it returns forbidden 403!
the html page:
<div class="search-input">
<form>
{% csrf_token %}
<button>بحـث</button>
<input
type="text"
name="q"
id="search"
placeholder="Est: Game of thrones, Vikings or Deadpool"
/>
</form>
</div>
<div class="search-results"></div>
urls.py:
path('search/', views.search_titles, name='search')
views.py:
def search_titles(request):
if request.method == 'POST':
search_text = request.POST['search_text']
else:
search_text = ''
search_results = Media.objects.filter(
is_published=True, title__contains=search_text)[:5]
context = {
'search_results': search_results
}
return render(request, 'partials/_search_results.html', context)
the jquery file:
$("#search").on("keyup", function() {
$.ajax({
type: "POST",
url: "/search/",
data: {
search_text: $("#search").val(),
csrfmiddlewaretoken: $("input[name=csrfmiddlewaretoken]").val()
},
success: searchSuccess,
dataType: "html"
});
});
function searchSuccess(data, textStatus, jqXHR) {
$("search-results").html(data);
}
});
search_results.html ( that i don't even know the reason of )
{% if search_results.count > 0 %} {% for result in search_results %}
<li>
{{ result.title }}
</li>
{% endfor %} {% else %}
<li>Nothing to show</li>
{% endif %}
This is likely happening because you are not properly setting up AJAX to pass your CSRF token. The Django docs have a great section on how to set this up. Here's the short story.
First, you'll need to acquire the token:
Here's how to do it if CSRF_USE_SESSIONS and CSRF_COOKIE_HTTPONLY in your settings are False:
// using jQuery
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie !== '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
var csrftoken = getCookie('csrftoken');
// using jQuery
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie !== '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
var csrftoken = getCookie('csrftoken');
OR, Here's how to do it if CSRF_USE_SESSIONS or CSRF_COOKIE_HTTPONLY in your settings are True:
{% csrf_token %}
<script type="text/javascript">
// using jQuery
var csrftoken = jQuery("[name=csrfmiddlewaretoken]").val();
</script>
IN BOTH CASES, you'll also need to set up the token on your AJAX request:
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});