Как получить результат из внешнего ключа с тремя ссылками?

У меня есть модели, которые выглядят следующим образом

class Tweets(models.Model):
    description = models.TextField(blank=True, null=False, default="", max_length=255)
    createdAt = models.DateTimeField(auto_now_add=True, null=True, blank=True)
    updatedAt = models.DateTimeField(auto_now=True)

    owner = models.ForeignKey(
        settings.AUTH_USER_MODEL, blank=True, null=True, on_delete=models.SET_NULL
    )


class TweetsLike(models.Model):
    tweetId = models.ForeignKey(
        Tweets, on_delete=models.SET_NULL, null=True, blank=True
    )
    owner = models.ForeignKey(
        settings.AUTH_USER_MODEL, blank=True, null=True, on_delete=models.SET_NULL
    )

    createdAt = models.DateTimeField(auto_now_add=True, null=True, blank=True)
    updatedAt = models.DateTimeField(auto_now=True)    

Твит может быть лайкнут только одним UserModel один раз, и я хотел бы отобразить кнопку отмены лайка, если человек лайкнул, как я могу сделать это в ListView?

Текущий CBV ListView с Form Mixin:

class ListWithForm(ListView, ModelFormMixin):
    model = Tweets
    ordering = ["-createdAt"]
    paginate_by = 5
    form_class = TweetForm

    def get(self, request, *args, **kwargs):
        self.object = None
        self.form = self.get_form(self.form_class)
        # Explicitly states what get to call:
        # return HttpResponseRedirect("/")
        return ListView.get(self, request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        # When the form is submitted, it will enter here
        self.object = None
        form = TweetForm(request.POST)

        if form.is_valid():

            newTweet = form.save(commit=False)
            newTweet.owner = request.user
            newTweet.save()
            # Here ou may consider creating a new instance of form_class(),
            # so that the form will come clean.

        # Whether the form validates or not, the view will be rendered by get()
        return self.get(request, *args, **kwargs)

    def get_context_data(self, *args, **kwargs):
        # Just include the form
        context = super(ListWithForm, self).get_context_data(*args, **kwargs)
        context["form"] = self.form
        return context

Я пробовал редактировать шаблоны и отказался от этого, потому что

  1. Это не лучшая практика, я полагаю, так как это рендеринг из Frontend.
  2. Я просто не знаю, как это сделать даже из Frontend.

Я просто хотел добавить likable как True или False в контексте.

---- edit ----

Я понимаю, что, добавив likedBy с ManyToManyField на Tweets и я могу легко добиться желаемого, но является ли это предпочтительным стилем? Есть ли другой способ достичь того, что я хочу? Я в основном работаю с MongoDB, это первый раз, когда я работаю с РСУБД, не уверен, что логика здесь не работает.

Я бы предложил изменить дизайн базы данных.

Если у вас есть UserModel :

class YourUserModel:
... 
    likes = models.ManyToMany(Tweets, ...)

И измените свою Tweets модель:

class TweetModel: 
    <same_fields_taht_you_now_have> + 
    likes = models.IntegerField(default=0)

При такой реализации вам не нужна модель TweetsLike.

Теперь, в вашем шаблоне/FE фреймворке, вы можете показать количество лайков для конкретного твита по свойству likes модели Tweet.

Затем создайте 2 конечные точки, которые будут достигаться, когда пользователю нравится/не нравится твит. Вы можете передать понравившиеся экземпляры Tweet в FE для request.user и посмотреть, есть ли текущий/отдаваемый твит в этом списке. Если да, сгенерируйте кнопку "не нравится" и наоборот, если его нет в списке, сгенерируйте кнопку "нравится"

Вот пример jquery, который будет запрашивать API like

$(document).on('click', '#like-button', function(e){
  var articleID = $(this).data('id');
  var csrftoken = jQuery("[name=csrfmiddlewaretoken]").val();
  $.ajax
  ({
    method: 'POST',
    url: END_POINT_LIKE.replace("0", articleID),
    beforeSend: function (xhr){
      xhr.setRequestHeader('X-CSRFToken', csrftoken);
    },
    success: function(data)
    {
      $('#' + articleID).html(data.currentLikes);
    }
  });
});

Как видите, при успехе он возвращает обновленный список понравившихся статей.

Вернуться на верх