diff --git a/.gitignore b/.gitignore index a204982..ec7b198 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +.idea *.pyc build/ dist/ diff --git a/favit/admin.py b/favit/admin.py index f87ae59..88091a3 100644 --- a/favit/admin.py +++ b/favit/admin.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- + from django.contrib import admin from .models import Favorite diff --git a/favit/managers.py b/favit/managers.py index b954f87..977e9de 100644 --- a/favit/managers.py +++ b/favit/managers.py @@ -1,18 +1,16 @@ -# -*- coding: utf-8 -*- + from django.contrib.contenttypes.models import ContentType from django.db import models +from django.apps import apps +from builtins import str +from builtins import int -try: - from django.db.models import get_model -except ImportError: - from django.apps import apps - get_model = apps.get_model 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 @@ -44,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) @@ -65,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) diff --git a/favit/migrations/0001_initial.py b/favit/migrations/0001_initial.py new file mode 100644 index 0000000..d0aa4fd --- /dev/null +++ b/favit/migrations/0001_initial.py @@ -0,0 +1,36 @@ + + + +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(on_delete=models.deletion.CASCADE, to='contenttypes.ContentType')), + ('user', models.ForeignKey(on_delete=models.deletion.CASCADE, 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')]), + ), + ] diff --git a/favit/migrations/__init__.py b/favit/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/favit/models.py b/favit/models.py index 2cb6c28..b3270b6 100644 --- a/favit/models.py +++ b/favit/models.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- + try: from django.contrib.contenttypes.generic import GenericForeignKey except ImportError: @@ -16,8 +16,8 @@ class Favorite(models.Model): """ """ - user = models.ForeignKey(getattr(settings, 'AUTH_USER_MODEL', 'auth.User')) - target_content_type = models.ForeignKey(ContentType) + user = models.ForeignKey(getattr(settings, 'AUTH_USER_MODEL', 'auth.User'), on_delete=models.CASCADE) + target_content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE) target_object_id = models.PositiveIntegerField() target = GenericForeignKey('target_content_type', 'target_object_id') timestamp = models.DateTimeField(auto_now_add=True, db_index=True) diff --git a/favit/static/favit/css/favorite.css b/favit/static/favit/css/favorite.css index 223a5e6..22cad30 100644 --- a/favit/static/favit/css/favorite.css +++ b/favit/static/favit/css/favorite.css @@ -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; diff --git a/favit/static/favit/js/favorite.js b/favit/static/favit/js/favorite.js index c3bd14d..6dcaf7e 100644 --- a/favit/static/favit/js/favorite.js +++ b/favit/static/favit/js/favorite.js @@ -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); + } + }); }); - }); }); diff --git a/favit/templates/favit/button.html b/favit/templates/favit/button.html index 4ddffe4..d2b7062 100644 --- a/favit/templates/favit/button.html +++ b/favit/templates/favit/button.html @@ -1,6 +1,6 @@