In my app I made a favorite list that a user can populate using AJAX.
Is it working perfectly but I am not sure if I did it the right way and I would like to know how to do it the proper way. Or maybe somehow I did it right.
My html:
<div class='sub_button'>
<form class="add_btn" method='post'>{% csrf_token %}
<button class='added btn' value= '{{product.id }} {{ sub_product.id }}' ><i class=' fas fa-save'></i></button>
</div>
My AJAX:
$(".row").on('click', ".added", function(event) {
let addedBtn = $(this);
console.log(addedBtn)
event.preventDefault();
var product = $(this).val();
var url = '/finder/add/';
$.ajax({
url: url,
type: "POST",
data:{
'product': product,
'csrfmiddlewaretoken': $('input[name=csrfmiddlewaretoken]').val()
},
datatype:'json',
success: function(data) {
if (data['success'])
addedBtn.hide();
}
});
});
My views.py
def add(request):
data = {'success': False}
if request.method=='POST':
product = request.POST.get('product')
user = request.user
splitted = product.split(' ')
sub_product = Product.objects.get(pk=(splitted[1]))
original_product = Product.objects.get(pk=(splitted[0]))
p = SavedProduct(username= user, sub_product=sub_product, original_product = original_product)
p.save()
data['success'] = True
return JsonResponse(data)
What is bugging me is the way I passed '{{product.id }} {{ sub_product.id }}'. Because I've made it after some tinkering.
There is a better way to do this.
ie, if you have only one product.id and sub_product.id in this page instance. Then in a script tag at the end of the HTML template for this page you add the following:
<script>
var product_id = {{ product.id }}
var sub_product_id = {{ sub_product.id }}
</script>
Then you can link the external JS file in which you have AJAX to this HTML template with another script tag.
Now your product_id and sub_product_id will be available in your external JS script file in which you have the AJAX code.
So that way, you don't have to pass it through the value attribute of the button tag and things look more clean.
Related
I'm making a like button for a post in django. What I need is that when the like button is clicked, the function is executed, but I need the page not to be reloaded (To later use javascript). To do that I return a jsonresponse() instead of a return render. But the real problem is that it redirects me to the page that I show in the photo. The page is not reloaded. as I want it. but I don't want it to show me the blank page with the jsonresponse data (like this photo).I want to stay in the same page without reload.
My view function:
def liking (request, pk):
posts = get_object_or_404(Post, id = pk)
if request.user in posts.likes.all():
posts.likes.remove(request.user)
else:
posts.likes.add(request.user.id)
likes_count = posts.likes.all().count()
print(f'likes_count = {likes_count}')
data= {
'likes_count': likes_count,
}
#return redirect ('index')# This is commented
return JsonResponse(data, safe=False, status=200 )
You can use AJAX. Simply place the code below in the template and trigger it with buttons.
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.1/jquery.min.js"></script>
<script>
function get_likes(pk){
$.ajax({
url: '{% url "url-name" pk %}',
type: 'GET',
success: function (res) {
var likes = JSON.parse(res);
return likes["likes_count"]
}
});
}
</script>
If you need to post any data, you can use the lines below.
function get_likes(pk){
$.ajax({
url: '{% url "url-name" pk %}',
type: 'POST',
data: {
csrfmiddlewaretoken: "{{ csrf_token }}",
data1:"data",
data2:"data"
},
success: function (res) {
var likes = JSON.parse(res);
return likes["likes_count"]
}
});
}
You can add the following lines in your function to use the posted data on the django side.
data1 = request.POST.get("data1")
data2 = request.POST.get("data2")
After trying for a while, I found the problem. It had nothing to do with the ajax request or a fetch, which is what I ended up using. It was simply that I had the url of the views.py function in the href="" and for this reason the white screen came out with the jsonresponse() data:
I had to change:
<a class="btn btn-dark like" id="like_button" href="{% url 'liking' post.id %}"> Like</a>
So:
<a class="btn btn-dark like" id="like_button" href="#"> Like</a>
Thanks for all the answers!
Nothing will ne happened when I submit product in the the cart. I want to use AJAX without refreshing page.
When I submit the console message will be displayed.
I'm trying to use AJAX first.
Trying to add product in the cart without refreshing page.
I need help please :)
Views Django
def add_cart(request, product_id):
cart = Cart(request)
product = get_object_or_404(Product, id=product_id)
form = CartProductForm(request.POST)
if form.is_valid():
cd = form.cleaned_data
cart.add(product=product,
quantity=cd['quantity'],
update_quantity=cd['update_qt']
)
return JsonResponse({'status': 'success'})
Form
from django import forms
from django.core.validators import MinValueValidator, MaxValueValidator
class CartProductForm(forms.Form):
quantity = forms.IntegerField(initial=1)
update_qt = forms.BooleanField(required=False, initial=False, widget=forms.HiddenInput)
HTML Code
<form action="{% url "..." %}" method="post" data-id="{{ ... }}" class="form-order" id="form">
{{ cart_product_form }}
{% csrf_token %}
<a data-id="{{ ... }}" class="buy-product"><button>BUY</button></a>
</form>
JS Code
$(".buy-product").on('click', function(e){
e.preventDefault();
var product_id = $(this).attr('data-id')
var quantity = 1
console.log(product_id)
console.log(quantity)
data = {
'product_id': product_id,
'quantity': quantity
}
var point='/cart/add/'+product_id+'/'
$.ajax({
headers:{
'Content-Type':'application/json',
'X-CSRFToken':csrftoken,
},
url: point,
type: 'POST',
data: data,
success: function(data){
console.log('success')
console.log(csrftoken)
}
})
})
You need to add csrftoken in data: {csrfmiddlewaretoken':csrftoken}. Also I don't see when you initialize your variables, but I think is just example. Check this answer for more: link
You can prevent form from refreshig the page and then do whatever you need with your JS code:
<form action="{% url "..." %}" method="post" data-id="{{ ... }}" class="form-order" id="form" onsubmit="myFunction(event)">
...
</form>
<script>
function myFunction(event){
event.preventDefault();
}
</script>
I am building a simple flask blog and there I am trying to implement like functionality using ajax and jquery. It works without ajax but the page reloads. So I need to use the ajax but when I am using ajax then I got my site redirected to the JSON file which is not expected. Please Help me with this. The code is
<div class="likers" id = 'result{{ slide.id }}'>
{% if current_user.has_liked_slide(slide) %}
<a class="unlike" id="unlike_{{slide.id}}" href="{{ url_for('like_action', slide_id=slide.id, action='unlike') }}">unlike</a>
{% else %}
<a class="like" id="like_{{slide.id}}" href="{{ url_for('like_action', slide_id=slide.id, action='like') }}">like</a>
{% endif %}
<div id = 'like-count'>
{{ slide.likes | count }}
</div>
</div>
#app.route('/like/<int:slide_id>/<action>', methods = ['GET', 'POST'])
#login_required
def like_action(slide_id, action):
slide = Slide.query.filter_by(id=slide_id).first_or_404()
if action == 'like':
current_user.like_slide(slide)
db.session.commit()
return jsonify({'slide_id': slide_id, 'action': action})
if action == 'unlike':
current_user.unlike_slide(slide)
db.session.commit()
return jsonify({'slide_id': slide_id, 'action': action})
$(document).ready(function(event) {
$('.like, .unlike').click(function(){
var id = this.id;
var split_id = id.split('_');
var text = split_id[0];
var slide_id = split_id[1];
$.ajax({
url: '/like/<int:slide_id>/<action>',
type: 'post',
data : {slide_id:slide_id, action:text},
dataType:'html',
success: function(data){
$("like_" + slide_id).html(data);
$('unlikes_' + slide_id).html(data);
}
});
});
});
I am trying to display a User's name on top of a box where they enter their Employee # in a form, without having to refresh the page.
For example, they enter their # and then after they click/tab onto the next field, it renders their name on top, which comes from the database, so the user knows they've entered the correct info. This name is stored in a separate model, so I try to retrieve it using the "id/number".
I am not too familiar with AJAX but after reading a few similar questions it seems like an AJAX request would be the most appropriate way to achieve this. I tried to make a function get_employee_name that returns the name of the person based on the way I saw another ajax request worked, but I'm not sure how to implement this so it displays after the # is entered.
My page currently loads, but there is never a call to the function/url that searches for the name to display it on the page (because there isn't one). I'm not sure where I might be missing the part that connects these two areas of the code or how to connect these, as I am not too familiar with html and Django, most of this has been trial and error.
models.py
class EmployeeWorkAreaLog(TimeStampedModel, SoftDeleteModel, models.Model):
employee_number = models.ForeignKey(Salesman, on_delete=models.SET_NULL, help_text="Employee #", null=True, blank=False)
work_area = models.ForeignKey(WorkArea, on_delete=models.SET_NULL, null=True, blank=False)
station_number = models.ForeignKey(StationNumber, on_delete=models.SET_NULL, null=True, blank=True)
This is the model where the name is stored
alldata/models.py
class Salesman(models.Model):
slsmn_name = models.CharField(max_length=25)
id = models.IntegerField(db_column='number', primary_key=True)
I was reading I can add to the "attrs" in the widget an 'onchange' part, but I am not too familiar with how to approach this and tying it to the ajax request from forms and not the html.
forms.py
class WarehouseForm(AppsModelForm):
class Meta:
model = EmployeeWorkAreaLog
widgets = {
'employee_number': ForeignKeyRawIdWidget(EmployeeWorkAreaLog._meta.get_field('employee_number').remote_field, site, attrs={'id':'employee_number_field'}),
}
fields = ('employee_number', 'work_area', 'station_number')
views.py
def enter_exit_area(request):
form = WarehouseForm(request.POST or None)
if form.is_valid():
# Submission stuff/rules
return render(request, "operations/enter_exit_area.html", {
'form': form,
})
def get_employee_name(request):
employee_number = request.GET.get('employee_number')
try:
employee = Salesman.objects.get(id=employee_number)
except Salesman.DoesNotExist:
return JsonResponse({'error': 'Employee not found'}, status=404)
employee_name = employee.slsmn_name
return JsonResponse({'employee_name': employee_name})
urls.py
urlpatterns = [
url(r'enter-exit-area/$', EnterExitArea.as_view(), name='enter_exit_area'),
path('get-employee-name/', views.get_employee_name, name='get_employee_name'),
]
The ajax request I tried to create is at the end of this html. I modified a similar request I found, but it does not actually display anything on the screen, not sure if I'm missing an area where the request is actually never being called, as I am not too familiar with how these types of requests work.
enter_exit_area.html
{% extends "base.html" %}
{% block main %}
<form id="warehouseForm" action="" method="POST" novalidate >
{% csrf_token %}
<div>
<div>
<!-- Here is where I would want the name to render after the user enters their number and tabs out -->
{{ form.employee_number.help_text }}
{{ form.employee_number }}
</div>
<div>
{{ form.work_area.help_text }}
{{ form.work_area }}
</div>
</div>
<div>
<div>
<button type="submit" name="enter_area" value="Enter">Enter Area</button>
</div>
</div>
</form>
<script>
$("#id_employee_number").change(function () {
var employee_number = $(this).val();
var url = $("#warehouseForm").data("employee-name");
$.ajax({
url: url,
type:'GET',
data: {
'id': employee_number
},
success: function (data) {
var employee_name = data['employee_name'];
$('#employee_name').text(employee_name);
},
error : function (data) {
var error_message = data['error'];
$('#employee_name').text(error_message);
}
});
});
</script>
{% endblock main %}
How can I call the function from the HTML? Could I do it in such a way that when the user enters 6 numbers it checks? (All employee numbers are 6 digits)
The url has to be the endpoint url which you defined in your url.py file
<script>
$("#id_employee_number").change(function (e) {
e.preventDefault();
var employee_number = $(this).val();
var url = $("#warehouseForm").data("employee-name");
$.ajax({
url: "/get_employee_name", // Here
type:'GET',
data: {
'id': employee_number
},
success: function (data) {
var employee_name = data['employee_name'];
$('#employee_name').text(employee_name);
},
error : function (data) {
var error_message = data['error'];
$('#employee_name').text(error_message);
}
});
});
</script>
You can append to your GET request a url parameter like: /get-employee-name/<your employee number here>
I recommend taking a look at URL Dispatcher to create url parameters within your django url definitions
I also recommend using underscores NOT dashes in your url definitions.
So a pseudo working config would be
urls.py
urlpatterns = [
url(r'enter-exit-area/$', EnterExitArea.as_view(), name='enter_exit_area'),
path('get_employee_name/<int:employeeNum>', views.get_employee_name, name='get_employee_name'),
]
views.py
def get_employee_name(request, employeeNum): #You get the employeeNum variable from urls.py
try:
employee = Salesman.objects.get(id=employee_number)
except Salesman.DoesNotExist:
return JsonResponse({'error': 'Employee not found'}, status=404)
employee_name = employee.slsmn_name
return JsonResponse({'employee_name': employee_name})
script
<script>
$("#id_employee_number").change(function () {
var employee_number = $(this).val();
var employeeNum = $("#warehouseForm").data("employee-name");
$.ajax({
url: `/get_employee_name/${employeeNum}`,
type:'GET',
success: function (data) {
var employee_name = data['employee_name'];
$('#employee_name').text(employee_name);
},
error : function (data) {
var error_message = data['error'];
$('#employee_name').text(error_message);
}
});
});
</script>
I have a form that pops up in a modal when the user clicks a button in the search results of a query. This form has three input fields and a few other fields that are being appended to it once the submit button is being clicked using ajax. As this is apart of a Django app, I am catching the values in the view on the server-side. I'm successfully able to get the data from the input fields of the form, but I'm not able to get the data from the appended fields.
I'm fairly new to using ajax so its likely that I'm doing something wrong but it seems like the data should be getting sent to the server. What could be the problem?
Here is the code for the ajax call and the modal form:
<script type="text/javascript">
$("#mform").submit(function(){
var c = getCookie('csrftoken');
//var data1 = $().attr("");
var extraData = [];
extraData['venue'] = $("#invite").data("venue");
extraData['artist'] = $("#invite").data("artist");
extraData['f_date'] = $("#invite").data("formatted_date");
extraData['uf_date'] = $("#invite").data("date");
extraData['ticket_url'] = $("#invite").data("ticket_url");
extraData['city'] = $("#invite").data("city");
extraData['region'] = $("#invite").data("region");
extraData['artist'] = $("#invite").data("artist");
var PostData = {csrfmiddlewaretoken: c, additionalValues:extraData}
$ajax({
//context:this,
type : 'POST',
dataType: 'json',
url: '/artistsearch/',
data: JSON.stringify(PostData),
success: function(response){}
});
});
EDIT:
HTML containing data to be sent
<ul class= 'list-group'>
{% for ticket in data %}
<li class = 'list-group-item' >
Title: {{ticket.title}}
Location: {{ticket.formatted_location}}
Venue: {{ticket.venue.name}}
Date: {{ticket.formatted_datetime}}
tickets status: {{ticket.ticket_status}}<br>
<a href = {{ticket.ticket_url}}> ticket url</a>
{% if user.is_authenticated %}
<button id = 'invite' type='button' class= 'btn btn-info btn-lg' data-toggle = 'modal' data-target='#myModal' data-artist = {{ticket.artists.name}} data-venue={{ticket.venue.name}} data-date = {{ticket.datetime}} data-formatted_date = {{ticket.formatted_datetime}} data-city= {{ticket.venue.city}} data-region = {{ticket.venue.region}} data-ticket_url={{ticket.ticket_url}} > Invite a friend </button>
<button id = 'save' type = 'button' class = 'btn btn-primary-outline'> Save Concert </button>
{% endif %}
</li>
{% endfor %}
</ul>
You have missed the # selector for id invite of button it should be like $("#invite"). Use attribute like data-artist instead of just artist and get it like $("#invite").data("artist) or $("#invite").attr("data-artist).
And then post it like ....
var postData = {
csrfmiddlewaretoken: c,
additionalValues: extraData
}
Then post data like
$.ajax({
type: 'post',
url: 'URL here',
data:JSON.stringify(PostData),
// .......
// Other code here
)};