Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

My Own Like Button: Django + Ajax -- How?

So I've been having trouble turning this view into an Ajax call:

def company_single(request, slug):
    company = get_object_or_404(CompanyProfile, slug=slug)
    company_list = CompanyProfile.objects.get(slug=slug)

    try:
        tcompany = CompanyLikes.objects.get(company=company_list)
        total_likes = tcompany.likes
        user_liked = CompanyLikes.objects.get(user=request.user)
    except:
        total_likes = 0


    instance, created = CompanyLikes.objects.get_or_create(company=company_list)
    likes_form = CompanyLikesForm(request.POST or None, instance=instance)

    if likes_form.is_valid():
        this = likes_form.save(commit=False)
        try:    
            if user_liked:
                this.likes -=1
                this.user.remove(request.user)
        except:
            this.user.add(request.user)
            this.likes += 1
        this.save()

    return render_to_response('company.html', locals(), context_instance=RequestContext(request))

I think I need jQuery and JSON, but I'm not sure how to implement it here to make my own "like button" for my site. Any thoughts/suggestions?

like image 860
jmitchel3 Avatar asked Dec 22 '12 23:12

jmitchel3


People also ask

How do I make likes and dislikes in Django?

1= like. 2=dislike. The fourth field, just to have more meta data, is the date field, to know when the user liked or disliked the post. Just to make likes or dislikes more readable in the Django admin, I use the __str__ function to show the user, post, and value, instead of just Preference objects.

Can I use AJAX in Django?

Using Ajax in Django can be done by directly using an Ajax library like JQuery or others. Let's say you want to use JQuery, then you need to download and serve the library on your server through Apache or others. Then use it in your template, just like you might do while developing any Ajax-based application.

How send data from AJAX to Django?

To send and receive data to and from a web server, AJAX uses the following steps: Create an XMLHttpRequest object. Use the XMLHttpRequest object to exchange data asynchronously between the client and the server. Use JavaScript and the DOM to process the data.


2 Answers

I will give you an example. You just learn from it and make changes accordingly.

myapp.models.py (simplified company model):

from django.db import models
from django.contrib.auth.models import User
from django.template.defaultfilters import slugify


class Company(models.Model):
    name = models.CharField(max_length=255)
    slug = models.SlugField()
    likes = models.ManyToManyField(User, related_name='likes')

    @property
    def total_likes(self):
        """
        Likes for the company
        :return: Integer: Likes for the company
        """
        return self.likes.count()

    def save(self, *args, **kwargs):
        self.slug = slugify(self.name)
        super(Company, self).save(*args, **kwargs)

myapp.urls.py (URL for a view):

url(r'^like/$', 'myapp.views.like', name='like'),

myapp.views.py (View):

from django.http import HttpResponse
try:
    from django.utils import simplejson as json
except ImportError:
    import json
from django.shortcuts import get_object_or_404
from django.contrib.auth.decorators import login_required
from django.views.decorators.http import require_POST

from myapp.models import Company


@login_required
@require_POST
def like(request):
    if request.method == 'POST':
        user = request.user
        slug = request.POST.get('slug', None)
        company = get_object_or_404(Company, slug=slug)

        if company.likes.filter(id=user.id).exists():
            # user has already liked this company
            # remove like/user
            company.likes.remove(user)
            message = 'You disliked this'
        else:
            # add a new like for a company
            company.likes.add(user)
            message = 'You liked this'

    ctx = {'likes_count': company.total_likes, 'message': message}
    # use mimetype instead of content_type if django < 5
    return HttpResponse(json.dumps(ctx), content_type='application/json')

The template:

<input type="button" id="like" name="{{ company_slug }}" value="Like" />

<script>
$('#like').click(function(){
      $.ajax({
               type: "POST",
               url: "{% url 'like' %}",
               data: {'slug': $(this).attr('name'), 'csrfmiddlewaretoken': '{{ csrf_token }}'},
               dataType: "json",
               success: function(response) {
                      alert(response.message);
                      alert('Company likes count is now ' + response.likes_count);
                },
                error: function(rs, e) {
                       alert(rs.responseText);
                }
          }); 
    })
</script>

Some instructions for using The url tag in template:

  • If Django < 1.3 use url tag without quotes around URL name like this {% url like %}
  • If Django > 1.3 and < 1.5 then you should add {% load url from future %} at top level of your template and enclosed your URL name with quotes as I have done in my answer
  • If Django >= 1.5 then simply remove {% load url from future %} and enclosed URL name with quotes as {% load url from future %} is marked as to be deprecated and will be removed in Django 1.9
like image 85
Aamir Rind Avatar answered Oct 04 '22 17:10

Aamir Rind


Writing this here since I don't have enough reputation to comment and edits have to be at least 6 characters. In new versions of Django, you need to pass the path to the view function or the name of the url to the url template tag as a string. Therefore line 7 of above template would be:

url: "{% url 'like' %}",

Here is the part of the documentation that backs this up.

like image 35
maahd Avatar answered Oct 04 '22 16:10

maahd