I have a blogost, comment and like model. The like model has a genericforeignkey field so I can link likes to blogposts and comments.
The view is working correctly however I am having trouble passing the parameters in the ajax request
urls.py
urlpatterns =[
url(r'^$',views.home, name = 'home'),
url(r'^blog/(?P<year>[0-9]{4})/(?P<month>[0-9]{1,2})/(?P<day>[0-9]{1,2})/(?P<slug>[-\w]+)/$',
views.blog,
name = 'view_blogpost_with_pk'),
url(r'^blog/(?P<year>[0-9]{4})/(?P<month>[0-9]{1,2})/(?P<day>[0-9]{1,2})/(?P<slug>[-\w]+)/ajax/like/$',VotesView.as_view(model=BlogPost, vote_type=Like.LIKE),
name='blog_like'),
url(r'^blog/(?P<year>[0-9]{4})/(?P<month>[0-9]{1,2})/(?P<day>[0-9]{1,2})/(?P<slug>[-\w]+)/ajax/dislike/$', VotesView.as_view(model=BlogPost, vote_type=Like.DISLIKE),
name='blog_dislike'),
]
blog.html
<ul>
<li data-id="{{ like_obj.id }}" data-type="blog" data-action="like" title="Like">
<span class="glyphicon glyphicon-thumbs-up"></span>
<span data-count="like">{{ like_obj.votes.likes.count }}</span>
</li>
<li data-id="{{ like_obj.id }}" data-type="blog" data-action="dislike" title="Dislike">
<span class="glyphicon glyphicon-thumbs-down"></span>
<span data-count="dislike">{{ like_obj.votes.dislikes.count }}</span>
</li>
</ul>
And the javascript. Just including dislike, like is very similar
<script>
function dislike()
{
var dislike = $(this);
var type = dislike.data('type');
var pk = dislike.data('id');
var action = dislike.data('action');
var like = dislike.prev();
$.ajax({
url : '/home/blog/2017/10/1/git/ajax/dislike/',
method : 'POST',
data : { 'obj' : pk },
success : function (json) {
dislike.find("[data-count='dislike']").text(json.dislike_count);
like.find("[data-count='like']").text(json.like_count);
}
});
return false;
}
<script>
$(function() {
$('[data-action="like"]').click(like);
$('[data-action="dislike"]').click(dislike);
});
</script>
So at the moment this working great except when i replace url with
url: '{% url "home:blog_dislike" year=obj.year month=obj.month day=obj.date
slug=obj.slug %}'
I get
django.urls.exceptions.NoReverseMatch: Reverse for 'blog_like' with keyword
arguments '{'year': '', 'month': '', 'day': '', 'slug': ''}' not found. 1
pattern(s) tried: ['home/blog/(?P<year>[0-9]{4})/(?P<month>[0-9]{1,2})/(?
P<day>[0-9]{1,2})/(?P<slug>[-\\w]+)/ajax/like/$']
views.py
def blog(request,year,month,day,slug):
if request.method == 'GET':
blogpost = BlogPost.objects.get(date__year=year, date__month=month, date__day=day,slug=slug)
form = BlogPostForm()
comments = Comment.objects.filter(comment_body_id=blogpost).order_by('-date') #Link comments to blogpost // comment_body is foreignkey to blogpost model
c = comments.count()
args = {'bpost': blogpost,'form':form,'comments':comments,'c':c}
return render(request,'home/blog.html',args)
if request.method == 'POST':
blogpost = BlogPost.objects.get(date__year=year, date__month=month, date__day=day,slug=slug)
form = BlogPostForm(request.POST)
if form.is_valid():
comment = form.save(commit = False)
comment.comment_body = blogpost
comment.save()
text = form.cleaned_data['comment']
form = BlogPostForm()
return redirect(request.build_absolute_uri())
else:
form = BlogPostForm()
args = {'form':form,'text':text}
return render(request, 'home/blog.html', args)
class VotesView(View):
model = None
vote_type = None
def post(self,request, year, month, day, slug):
obj = self.model.objects.get(date__year=year, date__month=month, date__day=day,slug=slug)
try:
x = Like.objects.get(content_type=ContentType.objects.get_for_model(obj), object_id=obj.id, user=request.user)
if x.vote is not self.vote_type:
x.vote = self.vote_type
x.save(update_fields = ['vote'])
result = True
else:
x.delete()
result = False
except Like.DoesNotExist:
obj.votes.create(user=request.user, vote=self.vote_type)
result = True
return HttpResponse(
json.dumps({
"result": result,
"like_count": obj.votes.likes().count(),
"dislike_count": obj.votes.dislikes().count(),
"sum_rating": obj.votes.sum_rating()
}),
content_type="application/json"
)
Thank you for any help
Related
i am trying to create a function that allows me to change my chart.js data based on what i have selected on a drop down menu. There has not been much tutorials on chart.js x django rest framework and i manage to piece together these based off parts and pieces from articles online.
The idea is to call a function within the AJAX function such that i am able to change the data array that goes into the model itself , however i've been facing some difficulty in doing so.
This is my api class :
class ChartData(APIView):
authentication_classes = [SessionAuthentication, BasicAuthentication]
permission_classes = [IsAuthenticated]
def get(self, request, format=None):
current_user = request.user
print(current_user.id)
sales_rev_data = Sales_project.objects.values_list('sales_project_est_rev').filter(sales_project_status = 'p4').filter(sales_extras = current_user.id)
sales_project_closing_date_data = Sales_project.objects.values_list('sales_project_closing_date').filter(sales_project_status = 'p4')
conversion_data = Sales_project.objects.all().filter(sales_project_status = 'p4').filter(sales_extras = current_user.id).count()
notconverted_data = Sales_project.objects.all().filter(sales_extras = current_user.id).count() - conversion_data
cost_data_per_unit = Sales_project.objects.values_list('material_costs').filter(sales_project_status = 'p4').filter(sales_extras = current_user.id)
moq_data = Customer_requirement.objects.values_list('moq').filter(sales_project__sales_project_status__contains= 'p4')
cost_data = np.array(list(moq_data)) * np.array(list(cost_data_per_unit))
profit_data = np.array(list(sales_rev_data))- cost_data
data = {
"sales_rev": sales_rev_data,
"sales_time_axis": sales_project_closing_date_data,
"conversion_label": ['Converted','Not Converted'],
"conversion_data": [conversion_data,notconverted_data],
"profit_data_per_project": profit_data
}
return Response(data)
This is the api end point:
HTTP 200 OK
Allow: GET, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept
{
"sales_rev": [
[
100000
],
[
125000
],
[
123000
]
],
"sales_time_axis": [
[
"2019-12-29T10:42:25Z"
],
[
"2019-12-23T03:13:03Z"
],
[
"2019-12-23T02:50:51Z"
]
],
"conversion_label": [
"Converted",
"Not Converted"
],
"conversion_data": [
3,
1
],
"profit_data_per_project": [
[],
[],
[]
]
}
This is my ajax function:
endpoint = 'api/chart/data'
$.ajax({
type: "GET",
url: endpoint,
success: function(data){
console.log(data)
sales_time = data.sales_time_axis
sales_rev = data.sales_rev
conversion_label = data.conversion_label
conversion_data= data.conversion_data
profit_data_per_project= data.profit_data_per_project
createChart()
change(sales_rev)
},
error: function(error_data){
console.log('error')
console.log(error_data)
}
})
Here is the change function definition :
function change(data){
var val = "Hi";
console.log(val)
data.pop()
console.log(data)
}
here is my HTML:
<div class="card-body" id="card_body">
<select class="text_select" id="chart-select" onchange="change()" name="select">
<option value="All">All Time</option>
<option value="3" id = 'hello'>Last 3 Months</option>
<option value="6">Last 6 Months</option>
<option value="12">Last Year</option>
<option value="24">Last 2 Years</option>
</select>
<canvas id="myChart"></canvas>
</div>
but i am receiving this error in my console:
{sales_rev: Array(3), sales_time_axis: Array(3), conversion_label: Array(2), conversion_data: Array(2), profit_data_per_project: Array(3)}
(index):166 Hi
(index):168 (2) [Array(1), Array(1), _chartjs: {…}, push: ƒ, pop: ƒ, shift: ƒ, splice: ƒ, …]
favicon.ico:1 GET http://127.0.0.1:8000/favicon.ico 404 (Not Found)
(index):166 Hi
(index):167 Uncaught TypeError: Cannot read property 'pop' of undefined
at change ((index):167)
at HTMLSelectElement.onchange ((index):80)
change # (index):167
onchange # (index):80
I will really appreciate anyone's input!
Hello im trying to fill the field "amount" that cointains the price of the payment_plan, and the payment_plan is part of the client information. I've been searching and the way to do it is implementing Ajax, but i have not found an example with django forms, every solution is really diferent from mine.
this is the model:
class Payment_Plans(models.Model):
name = models.CharField(max_length=20, primary_key=True)
price = models.IntegerField(default='0')
def __unicode__(self):
return self.name
class Clients(models.Model):
id = models.IntegerField(max_length=10, primary_key=True, default=0)
payment_plan = models.ForeignKey(Payment_Plans, null=True)
def __unicode__(self):
return self.id
class Payments(models.Model):
client = models.ForeignKey(Clients)
month_from = models.DateField(default='1111-01-01')
month_to = models.DateField(default='1111-01-01')
amount = models.IntegerField(default='0')
def __unicode__(self):
return self.month_from.strftime('%Y-%m-%d')
this is my payment form:
class PaymentsForm(forms.ModelForm):
month_from = forms.DateField(widget=DateTimePicker(options={"format": "YYYY-MM-DD", "pickTime": False}), label="Mes desde")
month_to = forms.DateField(widget=DateTimePicker(options={"format": "YYYY-MM-DD", "pickTime": False}), label="Mes Hasta")
amount = forms.IntegerField(label="Monto")
client = forms.ModelChoiceField(queryset=Clients.objects.all(), label="Cliente")
class Meta:
model=Payments
fields = ('month_from', 'month_to', 'amount', 'client')
This is the template:
{% extends 'base.html' %}
{% load bootstrap %}
{% block titulo %}Realizar Pago{% endblock%}
{% block encabezado %}
<h1>Realizar Pago</h1>
<!-- Para el datepicker -->
{{ form.media }}
{% endblock%}
{% block contenido %}
<form id='form' method='POST' action=''>{% csrf_token %}
<div class="col-sm-4">
</div>
<div class="col-sm-4">
{{ form.client|bootstrap }}
{{ form.month_from|bootstrap }}
{{ form.month_to|bootstrap }}
{{ form.amount|bootstrap }}
{{ form.days_left|bootstrap }}
<input type='submit' name='submit' value='Pagar' class="btn btn-default"/>
</div>
</form>
{% endblock%}
this should work like this:
1) the user selects the Client (right now its just a select box, in future autocomplete field)
2) the form should look into the client's payment_plan and then into the payment_plan price.
3) field should be filled with the price
how can i achive this? is it possible with django forms? shall i write manually the template instead of ussing tags like {{forms.client}}? if thats the case, how do i get the Clients?
You can use AJAX, you just need to know the fields' ids. Set an onchange (or .change() if you're using jquery) event on the 'client' field that sends the client id to a view, for instance, '/client-price' that will use it to query for the other price. Something like:
$( "#client" ).change(function() {
clientID = $(this).val();
$.ajax({
type: "GET", // if you choose to use a get, could be a post
url: "/client-price/?id=" + clientID,
success: function(data) {
$( "#amount" ).val(data.price);
});
The view/url would take the id. This post shows how you'd want to format your view to send back a json response.
Thanks onyeka! after some research with ajax and json the code looks like this:
view: (remember to import from django.http import JsonResponse)
def amount(request):
if request.method == 'GET':
total_amount = model.amount
response_data ={}
response_data['amount'] = total_amount
return JsonResponse(response_data)
ajax.js:
$(document).ready(function() {
$('#id_client').change(function(){
var query = $(this).val();
console.log(query);
$.ajax({
url : "/amount/",
type : "GET",
dataType: "json",
data : {
client_response : query
},
success: function(json) {
document.getElementById('id_amount').value=json.amount;
},
failure: function(json) {
alert('Got an error dude');
}
});
});
});
url.py
add corresponding line:
url(r'^amount/$', 'main.views.amount', name='amount'),
I am not getting a clear picture regarding the Model (Like) object is not iterable.
Error
liked, created = Like.objects.create(question=create_id)
TypeError: 'Like' object is not iterable
model.py
class Question(models.Model):
user = models.ForeignKey(User)
title = models.CharField(max_length= 200)
description = models.TextField()
location = models.CharField(max_length=150)
tags = TaggableManager()
time = models.DateTimeField(auto_now_add=True)
def __unicode__(self):
return self.title
class Like(models.Model):
user = models.ManyToManyField(User, related_name='likes')
question = models.ForeignKey(Question)
date = models.DateTimeField(auto_now_add=True)
likecount = models.IntegerField(default=0)
urls.py
url(r'^like/$', 'apps.question.views.like', name='like'),
views.py
def like(request):
vars = {}
if request.method == 'POST':
user = request.user
tutorial_id = request.POST.get('tutorial_id', None)
create_id = get_object_or_404(Question, id=tutorial_id)
liked, created = Like.objects.create(question=create_id)
try:
user_liked = Like.objects.get(question=create_id, user=user)
except:
user_liked = None
if user_liked:
user_liked.likecount -= 1
liked.user.remove(request.user)
user_liked.save()
else:
liked.user.add(request.user)
liked.likecount += 1
liked.save()
return HttpResponse(simplejson.dumps(vars, user),
mimetype='application/javascript')
template
<button type="button" class="btn btn-request" name="{{question.id}}" id="like">Request</button>
<script>
$('#like').click(function(){
$.ajax({
type: "POST",
url: "{% url 'like' %}",
data: {'tutorial_id': $(this).attr('name'), 'csrfmiddlewaretoken': '{{csrf_token}}'},
dataType: "text",
success: function(response) {
alert('You liked this')
},
error: function(rs, e) {
alert(rs.responseText);
}
});
})
</script>
What I am missing here, can anyone explain me?
Thanks!
Like.objects.create(question=create_id)
Returns a single object (a Like).
So, doing like, created = Like.objects.create(question=create_id) doesn't work because there's only one item on the right, so it can't be unpacked (like if you did like, created = 1).
The method that returns the object and a created boolean object is get_or_create:
like, created = Like.objects.get_or_create(question=create_id)
This is totally weird because I don't know why is returning this error when I replicated the same code for one section to another, only change the title of some generic views (UpdateView) and never execute the get function for return my form for edit a single customer, that's the code:
urls
from django.conf.urls import patterns, include, url
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
from . import views
from . import forms
from . import invoice
urlpatterns = patterns('',
url(r'^pedidos/',views.PedidosListView.as_view(),name="pedidos_list"),
url(r'^pedidos/add',views.add_pedido, name="pedido_add"),
url(r'^pedidos/edit/(?P<pedido_id>\d+)',views.edit_pedido, name="pedido_edit"),
url(r'^pedidos/delete/(?P<pedido_id>\d+)',views.delete_pedido, name="pedido_delete"),
url(r'^pedido/(?P<pk>\d+)',forms.DetailPedido.as_view(), name="pedido_detail"),
url(r'^pedido-pdf/(?P<pk>\d+)',invoice.detalle_pedido_pdf, name="pedido_detail_pdf"),
url(r'^clientes/',views.ClientesListView.as_view(),name="clientes_list"),
url(r'^clientes/edit/(?P<pk>\d+)$',forms.ClienteUpdateView.as_view(), name="clientes_edit"),
url(r'^empleados/edit/(?P<pk>\d+)$',forms.EmpleadoUpdateView.as_view(),name="edit"),
url(r'^empleados/',views.EmpleadoListView.as_view(),name="list"),
)
forms
class ClienteUpdateView(UpdateView):
form_class = ClienteModelForm
model = Cliente
template_name = 'ventas/form.html'
def get(self, request, **kwargs):
self.object = Cliente.objects.get(pk=self.kwargs['pk'])
form_class = self.get_form_class()
form = self.get_form(form_class)
context = self.get_context_data(object=self.object, form=form)
return self.render_to_response(context)
def form_valid(self, form):
self.object = form.save(commit=False)
self.object.save()
return HttpResponseRedirect('ventas/clientes_list.html')
def form_invalid(self,form):
if self.request.is_ajax():
return HttpResponseBadRequest(json.dumps(form.errors),
mimetype="application/json")
javascript
$(".edit").click(function(ev){
ev.preventDefault();
var url = $(this).data('form');
$.ajax({
url: url,
success: function(data, status){
$('body').append($('<div id="myModal" class="modal hide fade">' + data + '</div>').modal());
$("#myModal").find(".datePicker" ).datepicker({ dateFormat: "dd/mm/yy" });
},
error: function (xhr, ajaxOptions, thrownError) {
console.log(xhr.status);
console.log(xhr.responseText);
console.log(thrownError);
}
})
return false; // prevent the click propagation
});
html
<button data-form="{% url 'ventas:clientes_edit' c.id %}" class="edit btn btn-mini btn-info">
If in ajax url change the value for 'ventas/empleados/edit/someid' (the same that I replicated for do ClienteUpdateView, I can retrieve the form for employee edit but I can't do the same for customer, I'm missing something that I'm not able now to notice? It's driving my nuts! Any ideas?
Regards!
Ok, so I'm trying to call the function
def user_timetable(request, userid):
user = get_object_or_404(TwobooksUser,id = userid)
timeSlots = TimeSlot.objects.filter(user = request.user)
rawtimeslots = []
for timeSlot in timeSlots:
newSlot = {
'userid': timeSlot.user.id,
'startTime': str(timeSlot.startTime),
'endTime': str(timeSlot.endTime),
}
rawtimeslots.append(newSlot)
return HttpResponse(simplejson.dumps(rawtimeslots))
through the javascript in
{% include 'elements/header.html' %}
<script type='text/javascript'>
$(document).ready(function() {
$.get('/books/personal{{ user.id }}/timetable/', {}, function(data) {
data = JSON.parse(data);
var events = new Array();
for (var i in data) {
events.push({
id: data[i].id,
title: '{{ request.user.name }}',
start: Date.parse(data[i].startTime, "yyyy-MM-dd HH:mm:ss"),
end: Date.parse(data[i].endTime, "yyyy-MM-dd HH:mm:ss"),
allDay: false
});
}
where the above exists in a template that's being rendered (I think correctly).
The url conf that calls the function user_timetable is
url(r'^books/personal/(?P<userid>\d+)/timetable/$',twobooks.ajax.views.user_timetable),
But, user_timetable isn't being called for some reason.
Can anyone help?
EDIT-
Ok the original problem was that the template was not being rendered correctly, as the url in firebug comes to '/books/personalNone/timetable/' , which is incorrect.
I'm rendering the template like this -
def renderTimetableTemplate(request):
#if request.POST['action'] == "personalTimetable":
user = request.user
return render_to_response(
'books/personal.html',
{
'user': user,
},
context_instance = RequestContext(request)
)
Is there a mistake with this?
There is a slash missing after "personal"
$.get('/books/personal{{ user.id }}/timetable/', {}, function(data) {
should be
$.get('/books/personal/{{ user.id }}/timetable/', {}, function(data) {
Btw. you should use the {% url %} template tag.
There is a mismatch between the data you're converting to JSON and passing to the script, and the data that the script is expecting. You are passing a userId element in each timeslot, whereas the script is expecting just id.
This error should have shown up in your browser's Javascript console, and would be even easier to see in Firebug (or Chrome's built-in Developer Tools).