Skip to content

Commit

Permalink
Add likes for images
Browse files Browse the repository at this point in the history
  • Loading branch information
gruy committed Dec 19, 2023
1 parent 8018aaa commit 39789d7
Show file tree
Hide file tree
Showing 9 changed files with 188 additions and 1 deletion.
31 changes: 31 additions & 0 deletions djangocms_picture/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
from django.contrib import admin
from django.db.models import Count
from django.template.response import TemplateResponse
from django.urls import path

from filer.models import Image

from .models import ImageLike


class ImageLikeAdmin(admin.ModelAdmin):
def get_urls(self):
urls = super().get_urls()
prefix = f'{self.model._meta.app_label}_{self.model._meta.model_name}'
extra_urls = [path('likes/', self.admin_site.admin_view(self.likes), name=f'{prefix}_likes')]
return extra_urls + urls

def likes(self, request):
context = self.admin_site.each_context(request)
likes = {
like['image_id']: like['cnt']
for like in ImageLike.objects.values('image_id').annotate(cnt=Count('image_id')).order_by('-cnt')
}
images = Image.objects.filter(id__in=likes.keys())
for image in images:
image.likes_count = likes[image.id]
context['images'] = sorted(images, key=lambda x: x.likes_count, reverse=True)
return TemplateResponse(request, 'djangocms_picture/admin/likes.html', context)


admin.site.register(ImageLike, ImageLikeAdmin)
1 change: 1 addition & 0 deletions djangocms_picture/cms_plugins.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ class PicturePlugin(CMSPluginBase):
'dark_inverse',
'external_picture',
'is_lightbox',
'use_likes',
)
}),
('Подпись', {
Expand Down
38 changes: 38 additions & 0 deletions djangocms_picture/migrations/0018_likes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Generated by Django 3.2.23 on 2023-12-18 12:30

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


class Migration(migrations.Migration):

dependencies = [
migrations.swappable_dependency(settings.FILER_IMAGE_MODEL),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('djangocms_picture', '0017_title'),
]

operations = [
migrations.AddField(
model_name='picture',
name='use_likes',
field=models.BooleanField(default=False, verbose_name='включить "лайки"'),
),
migrations.CreateModel(
name='ImageLike',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('uuid', models.UUIDField(default=uuid.uuid4, editable=False)),
('created_at', models.DateTimeField(auto_now_add=True, verbose_name='дата')),
('image', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.FILER_IMAGE_MODEL)),
('user', models.ForeignKey(blank=True, editable=False, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL)),
],
options={
'verbose_name': 'лайки изображений',
'verbose_name_plural': 'лайк изображения',
'ordering': ('-created_at',),
},
),
]
21 changes: 20 additions & 1 deletion djangocms_picture/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
Enables the user to add an "Image" plugin that displays an image
using the HTML <img> tag.
"""
import uuid

from cms.models import CMSPlugin
from cms.models.fields import PageField
from django.conf import settings
Expand All @@ -13,7 +15,7 @@
from djangocms_attributes_field.fields import AttributesField
from easy_thumbnails.files import get_thumbnailer
from filer.fields.image import FilerImageField
from filer.models import ThumbnailOption
from filer.models import Image, ThumbnailOption


# add setting for picture alignment, renders a class or inline styles
Expand Down Expand Up @@ -233,6 +235,8 @@ class AbstractPicture(CMSPlugin):
title = models.CharField('Заголовок', max_length=255, blank=True)
text = models.TextField('Тело подписи', max_length=2048, blank=True)

use_likes = models.BooleanField('включить "лайки"', default=False)

class Meta:
abstract = True

Expand Down Expand Up @@ -474,3 +478,18 @@ class Picture(AbstractPicture):

class Meta:
abstract = False


class ImageLike(models.Model):
image = models.ForeignKey(Image, on_delete=models.CASCADE)
user = models.ForeignKey(settings.AUTH_USER_MODEL, editable=False, blank=True, null=True, on_delete=models.SET_NULL)
uuid = models.UUIDField(default=uuid.uuid4, editable=False)
created_at = models.DateTimeField('дата', auto_now_add=True)

class Meta:
verbose_name_plural = 'лайк изображения'
verbose_name = _('лайки изображений')
ordering = ('-created_at',)

def __str__(self):
return f'{self.image}'
25 changes: 25 additions & 0 deletions djangocms_picture/templates/djangocms_picture/admin/likes.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{% extends 'admin/base_site.html' %}


{% load i18n %}


{% block breadcrumbs %}
<div class="breadcrumbs">
<a href="{% url 'admin:index' %}">{% translate 'Home' %}</a>
&rsaquo;
Статистика понравившихся изображений
</div>
{% endblock %}


{% block content %}
<table>
{% for image in images %}
<tr>
<td><img src="{{ image.icons.64 }}" /></td>
<td><h2>{{ image.likes_count }}</h2></td>
</tr>
{% endfor %}
</table>
{% endblock %}
Empty file.
24 changes: 24 additions & 0 deletions djangocms_picture/templatetags/djangocms_picture_tags.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import uuid

from django import template

from ..models import ImageLike

register = template.Library()


@register.simple_tag()
def image_has_like(request, image):
cookie_name = 'djangocms_picture_like'
flt = {}

if request.user.is_authenticated:
flt['user'] = request.user
else:
flt['uuid'] = request.COOKIES.get(cookie_name, uuid.uuid4())

try:
ImageLike.objects.get(image=image, **flt)
return True
except ImageLike.DoesNotExist:
return False
7 changes: 7 additions & 0 deletions djangocms_picture/urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from django.urls import path

from .views import LikeView

urlpatterns = [
path('like/<int:pk>/', LikeView.as_view(), name='djangocmspicture-like'),
]
42 changes: 42 additions & 0 deletions djangocms_picture/views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import uuid

from filer.models import Image

from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
from django.views.generic.detail import BaseDetailView

from .models import ImageLike


class LikeView(BaseDetailView):
model = Image

@csrf_exempt
def dispatch(self, request, *args, **kwargs):
return super().dispatch(request, *args, **kwargs)

def post(self, request, *args, **kwargs):
image = self.get_object()
flt = {}
cookie_name = 'djangocms_picture_like'

if request.user.is_authenticated:
flt['user'] = request.user
else:
flt['uuid'] = request.COOKIES.get(cookie_name, uuid.uuid4())

try:
like = ImageLike.objects.get(image=image, **flt)
like.delete()
result = 'deleted'
except ImageLike.DoesNotExist:
like = ImageLike.objects.create(image=image, **flt)
result = 'created'

response = JsonResponse({'result': result, 'like_id': like.id})

if 'uuid' in flt:
response.set_cookie(cookie_name, flt['uuid'])

return response

0 comments on commit 39789d7

Please sign in to comment.