ИМ
Nov. 30, 2018, 11:42 a.m.
Игорь Максимов

Доброго времени суток форум. Год назад начал ваять проект под свои нужды и так вышло что забил на него немного. Вот решил продолжить и остановился на лайках.

Имею такие модели:

class LikeDislikeManager(models.Manager):
	use_for_related_fields = True
 
	def likes(self):
		return self.get_queryset().filter(vote__gt=0)
 
	def dislikes(self):
		return self.get_queryset().filter(vote__lt=0)
 
	def sum_rating(self):
		return self.get_queryset().aggregate(Sum('vote')).get('vote__sum') or 0

	def movies(self):
		return self.get_queryset().filter(content_type__model='movie').order_by('-movies__pub_date')

class LikeDislike(models.Model):
	class Meta():
		db_table = 'LikeDislike'

	LIKE = 1
	DISLIKE = -1
 
	VOTES = (
		(DISLIKE, 'Не нравится'),
		(LIKE, 'Нравится')
	)

	vote = models.SmallIntegerField('Голос', choices=VOTES)
	user = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name="Пользователь")
	content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
	object_id = models.PositiveIntegerField()
	content_object = GenericForeignKey()
	objects = LikeDislikeManager()

Урлы:

    path('movie/<pk>/like/',
         login_required(views.VotesView.as_view(model=Movie, vote_type=LikeDislike.LIKE)),
        name='movie_like'),
    path('movie/<pk>/dislike/',
        login_required(views.VotesView.as_view(model=Movie, vote_type=LikeDislike.DISLIKE)),
        name='movie_dislike'),

Вьюха:

class VotesView(View):
    model = None    # Модель данных - Статьи или Комментарии
    vote_type = None # Тип комментария Like/Dislike

    def movie(self, request, pk):
        obj = self.model.objects.get(pk=pk)
        # GenericForeignKey не поддерживает метод get_or_create
        try:
            likedislike = LikeDislike.objects.get(content_type=ContentType.objects.get_for_model(obj), object_id=obj.id, user=request.email)
            if likedislike.vote is not self.vote_type:
                likedislike.vote = self.vote_type
                likedislike.save(update_fields=['vote'])
                result = True
            else:
                likedislike.delete()
                result = False
        except LikeDislike.DoesNotExist:
            obj.votes.create(user=request.email, 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"
        )

Шаблон:

<ul>
    <li data-id="{{ like_obj.id }}" data-type="movie" data-action="like" title="Нравится">
        <span style="cursor: pointer" class="fa fa-thumbs-up"></span>
        <span data-count="like">{{ like_obj.votes.likes.count }}</span>
    </li>
    <li data-id="{{ like_obj.id }}" data-type="movie" data-action="dislike" title="Не нравится">
        <span style="cursor: pointer" class="fa fa-thumbs-down"></span>
        <span data-count="dislike">{{ like_obj.votes.dislikes.count }}</span>
    </li>
</ul>

Ну и javascript:

// Получение переменной cookie по имени
function getCookie(name) {
    var cookieValue = null;
    if (document.cookie && document.cookie !== '') {
        var cookies = document.cookie.split(';');
        for (var i = 0; i < cookies.length; i++) {
            var cookie = jQuery.trim(cookies[i]);
            // Does this cookie string begin with the name we want?
            if (cookie.substring(0, name.length + 1) === (name + '=')) {
                cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                break;
            }
        }
    }
    return cookieValue;
}

// Настройка AJAX
$(function () {
    $.ajaxSetup({
        headers: { "X-CSRFToken": getCookie("csrftoken") }
    });
});


function like()
{
    var like = $(this);
    var type = like.data('type');
    var pk = like.data('id');
    var action = like.data('action');
    var dislike = like.next();

    $.ajax({
        url : "/" + type +"/" + pk + "/" + action + "/",
        type : 'POST',
        data : { 'obj' : pk },

        success : function (json) {
            like.find("[data-count='like']").text(json.like_count);
            dislike.find("[data-count='dislike']").text(json.dislike_count);
        }
    });

    return false;
}

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 : "/" + type +"/" + pk + "/" + action + "/",
        type : '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;
}

// Подключение обработчиков
$(function() {
    $('[data-action="like"]').click(like);
    $('[data-action="dislike"]').click(dislike);
});

При нажатии на лайк-дизлайк в консоле браузера получаю:

Прошу помощи в настройке сабжа.


Oct. 19, 2018, 11:26 a.m.
Евгений Легоцкой

Добрый день, Уважаемые Пользователи EVILEG!

Повестка дня следующая.

Планирую внедрить на сайте уведомления о лайках.

В личном профиле пользователя будут настройки для отключения уведомлений. Всего предполагается две настройки:

  1. Получать уведомления о лайках в личном кабинете
  2. Получать уведомления о лайках по почте

На сайте также присутствуют и дислайки. Поэтому вопрос повестки следующий, делать ли уведомления для дислайков? или оставить только лайки?

April 30, 2017, 4:17 p.m.

Django

Like, Django, GenericRelation, Dislike, GenericForeignKey

In the article on creating a system of bookmarks on Django, an example was considered with the use of an abstract model for several types of bookmarks, namely for articles and comments on articles. Attention was also drawn to the fact that the model fields that had foreign keys to different models should have the same names to support the possibility of creating a single interface for adding bookmarks. This is made possible by the so-called "duck typing", which implies that objects that do not have a single inheritance hierarchy can be used in the same scenario if there are interfaces (methods) that have the same signature.

Literally the principle of duck typing sounds like this:

If it looks like a duck, swims like a duck and quacks like a duck, then it probably is a duck.

That is, having methods with the same signature, we can use objects that are not associated with an inheritance hierarchy, in the same context.

In the same article, let's consider the variant when using the Like Dislike system, not two different tables for articles and comments are used, and not even one that will contain a foreign key for an article or comment (that is, two columns, One of the columns, depending on what type of content the user activity is related to), and one table that will contain:

  • content_type - The content type to which the record belongs
  • object_id - Record ID
    • content_object - The generated foreign key to write, in fact the content object
  • Other additional fields
Last comments
June 24, 2019, 10:23 a.m.
Евгений Легоцкой

Хорошо, ну будут проблемы помимо того, что касается статей, то не стесняйтесь задавать вопросы на форуме.
МБ
June 24, 2019, 10:21 a.m.
Михаил Булатов

Извиняюсь, все работает(из-за невнимательности).
June 24, 2019, 9:52 a.m.
Евгений Легоцкой

Придётся делать ещё сигнал в дочернем qml и пробрасывать через коннекты и обработчики. А вообще нужно смотреть конкретный код и что вы пытаетесь сделать. Так что лучше будет, если вы зад...
June 21, 2019, 8:31 a.m.
Ruslan Polupan

Вот моя строка по которой все отлично сработало %cqtdeployer% -bin c:/CentralMposKeys/CentalMposKeys.exe -qmake c:/Qt/5.12.2/mingw73_64/bin/qmake.exe
June 21, 2019, 8:24 a.m.
Андрей Янкович

Возможно кому то пригодится сqtdeployer для windows работает точно так же как и для Linux разница лишь в команде запуска Linux: cqtdeployer Windows: %cqtdeployer...
Now discuss on the forum
June 24, 2019, 2:36 p.m.
Михаиллл

Нашел проект подключения к вебсокету.Но по моему адресу не могу подключиться.Нужно ли для этого использовать библиотеки?Вы не знаете адрес вебсокета, на котором можно проверить с...
June 24, 2019, 2:07 p.m.
Евгений Легоцкой

Я пока даже не знаю, а какой код самого подключения? использовали ожидание на подключение? Так делали? socket->connectToServer("market");if (socket->waitForConnected(1000)) ...
June 24, 2019, 1:19 p.m.
IscanderChe

// widget.cpp#include "widget.h"#include <QTableView>#include <QVBoxLayout>#include "checkboxdelegate.h"#include "comboboxdelegate.h"#include "mytableview.h"#include <QSqlD...
June 24, 2019, 11:16 a.m.
BlinCT

Хорошо, с этим понятно. Вот есть такой набор каких то кнопок. Цифры отображают в каком порядке должен менятся фокус.1. Как правильнее сделать отображение активного обьекта...
e
June 24, 2019, 10:58 a.m.
evgenm27

Спасибо за ответ, буду пробовать
Looking for a Job?
10,000.00 руб. - 15,000.00 руб.
Нужен помощник для создания API.
Moscow, Moscow, Russia
25,000.00 руб. - 30,000.00 руб.
Разработчик Qt/C++
Barnaul, Altai Krai, Russia

For registered users on the site there is a minimum amount of advertising

EVILEG
About
Services
Join us
© EVILEG 2015-2019
Recommend hosting TIMEWEB