Как получить результат из внешнего ключа с тремя ссылками?
У меня есть модели, которые выглядят следующим образом
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
Я пробовал редактировать шаблоны и отказался от этого, потому что
- Это не лучшая практика, я полагаю, так как это рендеринг из Frontend.
- Я просто не знаю, как это сделать даже из 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);
}
});
});
Как видите, при успехе он возвращает обновленный список понравившихся статей.