Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes and changes... #43

Open
wants to merge 19 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
.idea
*.pyc
build/
dist/
Expand Down
18 changes: 10 additions & 8 deletions favit/managers.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
# -*- coding: utf-8 -*-
from django.contrib.contenttypes.models import ContentType
from django.db import models
from django.db.models import get_model
from django.apps import apps
from builtins import str
from builtins import int


def _get_content_type_and_obj(obj, model=None):
if isinstance(model, basestring):
model = get_model(*model.split("."))
if isinstance(model, str):
model = apps.get_model(*model.split("."))

if isinstance(obj, (int, long)):
if isinstance(obj, int):
obj = model.objects.get(pk=obj)

return ContentType.objects.get_for_model(type(obj)), obj
Expand Down Expand Up @@ -40,8 +42,8 @@ def for_user(self, user, model=None):
qs = self.get_query_set().filter(user=user)

if model:
if isinstance(model, basestring):
model = get_model(*model.split("."))
if isinstance(model, str):
model = apps.get_model(*model.split("."))

content_type = ContentType.objects.get_for_model(model)
qs = qs.filter(target_content_type=content_type)
Expand All @@ -61,8 +63,8 @@ def for_model(self, model):
"""

# if model is an app_label.model string make it a Model class
if isinstance(model, basestring):
model = get_model(*model.split("."))
if isinstance(model, str):
model = apps.get_model(*model.split("."))

content_type = ContentType.objects.get_for_model(model)

Expand Down
36 changes: 36 additions & 0 deletions favit/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import migrations, models
from django.conf import settings


class Migration(migrations.Migration):

dependencies = [
('contenttypes', '0002_remove_content_type_name'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]

operations = [
migrations.CreateModel(
name='Favorite',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('target_object_id', models.PositiveIntegerField()),
('timestamp', models.DateTimeField(auto_now_add=True, db_index=True)),
('target_content_type', models.ForeignKey(to='contenttypes.ContentType')),
('user', models.ForeignKey(to=settings.AUTH_USER_MODEL)),
],
options={
'ordering': ['-timestamp'],
'get_latest_by': 'timestamp',
'verbose_name': 'favorite',
'verbose_name_plural': 'favorites',
},
),
migrations.AlterUniqueTogether(
name='favorite',
unique_together=set([('user', 'target_content_type', 'target_object_id')]),
),
]
Empty file added favit/migrations/__init__.py
Empty file.
4 changes: 2 additions & 2 deletions favit/models.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
from django.contrib.contenttypes import generic
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
from django.db import models
from django.conf import settings
Expand All @@ -15,7 +15,7 @@ class Favorite(models.Model):
user = models.ForeignKey(getattr(settings, 'AUTH_USER_MODEL', 'auth.User'))
target_content_type = models.ForeignKey(ContentType)
target_object_id = models.PositiveIntegerField()
target = generic.GenericForeignKey('target_content_type', 'target_object_id')
target = GenericForeignKey('target_content_type', 'target_object_id')
timestamp = models.DateTimeField(auto_now_add=True, db_index=True)

objects = FavoriteManager()
Expand Down
8 changes: 8 additions & 0 deletions favit/static/favit/css/favorite.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
.favit i.fa-heart {
color: #CB3D3D;
}

.favit.fa-heart-o {
color: black;
}

.fav-count {
font-size: .8em;
padding: 2px 5px 2px 4px;
Expand Down
96 changes: 56 additions & 40 deletions favit/static/favit/js/favorite.js
Original file line number Diff line number Diff line change
@@ -1,43 +1,59 @@
$(document).ready(function() {
$('.btn.favorite').click(function() {
var $obj = $(this);
var target_id = $obj.attr('id').split('_')[1];
$obj.prop('disabled', true);
$.ajax({
url: $obj.attr('href'),
type: 'POST',
data: {target_model: $obj.attr('model'),
target_object_id: target_id},
success: function(response) {
if (response.status == 'added') {
$obj.children().removeClass('icon-heart-empty').addClass('icon-heart');}
else {
$obj.children().removeClass('icon-heart').addClass('icon-heart-empty');
}
$obj.parent('.favit').children('.fav-count').text(response.fav_count);
$obj.prop('disabled', false);
}
});
});
jQuery(document).ready(function ($) {
$('.btn.favorite').click(function () {
var $obj = $(this);
var target_id = $obj.attr('id').split('_')[1];

$('.btn.unfave').click(function() {
var $obj = $(this);
$obj.prop('disabled', true);
$.ajax({
url: $obj.attr('href'),
type: 'POST',
data: {
target_model: $obj.data('model'),
target_object_id: $obj.data('id')
},
success: function(response) {
if (response.status == 'deleted') {
$obj.parent().remove();
}
},
complete: function(response) {
$obj.prop('disabled', false);
}
var add_fav_icon = $obj.attr('data-add-fav-icon') || "fa-heart-o";
var remove_fav_icon = $obj.attr('data-remove-fav-icon') || "fa-heart";

var add_fav_title = $obj.attr('data-add-fav-title') || "Add to Favourites";
var remove_fav_title = $obj.attr('data-remove-fav-title') || "Remove from Favourites";

$obj.prop('disabled', true);
$.ajax({
url: $obj.attr('href'),
type: 'POST',
data: {
target_model: $obj.attr('model'),
target_object_id: target_id
},
success: function (response) {
if (response.status == 'added') {
$obj.children().removeClass(add_fav_icon).addClass(remove_fav_icon);
if ($obj.attr('title') && $obj.attr('title') === add_fav_title) {
$obj.attr('title', remove_fav_title);
}
}
else {
$obj.children().removeClass(remove_fav_icon).addClass(add_fav_icon);
if ($obj.attr('title') && $obj.attr('title') === remove_fav_title) {
$obj.attr('title', add_fav_title);
}
}
//$obj.parent('.favit').children('.fav-count').text(response.fav_count);
$obj.prop('disabled', false);
}
});
});

$('.btn.unfave').click(function () {
var $obj = $(this);
$obj.prop('disabled', true);
$.ajax({
url: $obj.attr('href'),
type: 'POST',
data: {
target_model: $obj.data('model'),
target_object_id: $obj.data('id')
},
success: function (response) {
if (response.status == 'deleted') {
$obj.parent().remove();
}
},
complete: function (response) {
$obj.prop('disabled', false);
}
});
});
});
});
2 changes: 1 addition & 1 deletion favit/templates/favit/button.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<div class="favit">
<button class="btn favorite" href="{% url 'favit.views.add_or_remove' %}" model="{{ target_model }}" id="target_{{ target_object_id }}">
<i class="icon-heart{% if not undo %}-empty{% endif %}"></i>
<i class="fa-heart{% if not undo %}-o{% endif %}"></i>
</button>
<span class="fav-count">{{ fav_count }}</span>
</div>
32 changes: 16 additions & 16 deletions favit/templatetags/favit_tags.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
# -*- coding: utf-8 -*-
from django import template
from django.db.models import get_model
from django.template.loader import render_to_string

from classytags.utils import flatten_context
from ..models import Favorite


Expand All @@ -25,14 +24,15 @@ def favorite_button(context, target):
if Favorite.objects.get_favorite(user, target):
undo = True

return render_to_string(
'favit/button.html', {
'target_model': target_model,
'target_object_id': target.id,
'undo': undo,
'fav_count': Favorite.objects.for_object(target).count()
}
)
context = flatten_context(context)
context.update({
'target_model': target_model,
'target_object_id': target.id,
'undo': undo,
'fav_count': Favorite.objects.for_object(target).count()
})

return render_to_string('favit/button.html', context)


@register.simple_tag(takes_context=True)
Expand All @@ -48,12 +48,12 @@ def unfave_button(context, target):

target_model = '.'.join((target._meta.app_label, target._meta.object_name))

return render_to_string(
'favit/unfave-button.html', {
'target_model': target_model,
'target_object_id': target.id,
}
)
context = flatten_context(context)
context.update({
'target_model': target_model,
'target_object_id': target.id,
})
return render_to_string('favit/unfave-button.html', context)


@register.filter
Expand Down
11 changes: 6 additions & 5 deletions favit/urls.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
from django.conf.urls import patterns, url
from django.conf.urls import url
from favit.views import *


urlpatterns = patterns('favit.views',
url(r'^add-or-remove$', 'add_or_remove'),
url(r'^remove$', 'remove'),
)
urlpatterns = [
url(r'^add-or-remove$', add_or_remove, name='favit.views.add_or_remove'),
url(r'^remove$', remove, name='favit.views.remove'),
]
6 changes: 3 additions & 3 deletions favit/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
def add_or_remove(request):

if not request.is_ajax():
return HttpResponseNotAllowed()
return HttpResponseNotAllowed([])

user = request.user

Expand All @@ -37,15 +37,15 @@ def add_or_remove(request):

return HttpResponse(
json.dumps(response, ensure_ascii=False),
mimetype='application/json'
content_type='application/json'
)


@login_required
def remove(request):

if not request.is_ajax():
return HttpResponseNotAllowed()
return HttpResponseNotAllowed([])

user = request.user

Expand Down