diff --git a/news/migrations/0002_auto_20200816_0901.py b/news/migrations/0002_auto_20200816_0901.py new file mode 100644 index 0000000..f5c2759 --- /dev/null +++ b/news/migrations/0002_auto_20200816_0901.py @@ -0,0 +1,24 @@ +# Generated by Django 3.1 on 2020-08-16 13:01 + +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('news', '0001_initial'), + ] + + operations = [ + migrations.RemoveField( + model_name='article', + name='likes', + ), + migrations.AddField( + model_name='article', + name='likes', + field=models.ManyToManyField(related_name='article_likes', to=settings.AUTH_USER_MODEL), + ), + ] diff --git a/news/models.py b/news/models.py index 8515a99..3a7e79b 100644 --- a/news/models.py +++ b/news/models.py @@ -28,7 +28,7 @@ class Article(models.Model): content = RichTextField(blank=True, null=True) date_published = models.DateTimeField(auto_now_add=True) author = models.ForeignKey(User, on_delete=models.CASCADE) - likes = models.IntegerField(default=0) + likes = models.ManyToManyField(User, related_name="article_likes") header = models.ImageField(null=True, blank=True, default='default-header.jpg', upload_to='article-headers') header_caption = models.CharField(max_length=100, default="") tag = models.CharField(max_length=19,choices=POLITICAL_CHOICES,default=L_L) @@ -36,6 +36,9 @@ class Article(models.Model): def __str__(self): return f"{self.headline} by {self.author}" + def total_likes(self): + return self.likes.count(); + def get_absolute_url(self): return reverse('article-detail', kwargs={'pk': self.pk}) diff --git a/news/templates/news/article_detail.html b/news/templates/news/article_detail.html index 654b16e..b3f97e8 100644 --- a/news/templates/news/article_detail.html +++ b/news/templates/news/article_detail.html @@ -19,8 +19,13 @@ <a class="btn btn-danger btn-sm mt-1 mb-1" href="{% url 'article-delete' object.id %}">Delete article</a> </div> {% endif %} + <form action="{% url 'like_article' article.pk %}" method="post"> + {% csrf_token %} + <button type="submit" name="article_id" value="{{ article.id }}" class="btn btn-primary btn-small">Like</button> - {{ total_likes }} + </form> </div> <p class="article-content font-weight-light">{{ article.content|safe }}</p> + </div> </article> {% endblock content %} diff --git a/news/templates/news/home.html b/news/templates/news/home.html index ef298bd..78cde44 100644 --- a/news/templates/news/home.html +++ b/news/templates/news/home.html @@ -6,10 +6,14 @@ <div class="col-lg-4 col-sm-6 mb-4" style="margin-top: 2%"> <div class="card shadow border-0 h-100"><a href=""> <img src="{{ article.header.url }}" alt="..." class="img-fluid card-img-top"></a> - <div class="card-body"><a href="{% url 'article-detail' article.id %}" class="text-uppercase text-muted text-sm letter-spacing-2">{{ article.tag }} </a> + <div class="card-body"><!-- <a href="{% url 'article-detail' article.id %}" class="text-uppercase text-muted text-sm letter-spacing-2">{{ article.tag }} </a> --> <h5 class="my-2"><a href="{% url 'article-detail' article.id %}" class="nounderline text-dark">{{ article.headline }}</a></h5> <a href="{% url 'user-articles' article.author.username %}">{{ article.author.get_full_name }}<small class="text-muted"> · @{{ article.author }} · {{ article.date_published }}</small></a> <p class="my-2 text-muted text-sm">{{ article.content|safe|truncatechars_html:70|linebreaks }}</p> + <form action="{% url 'like_article' article.pk %}" method="post"> + {% csrf_token %} + <button type="submit" name="article_id" value="{{ article.id }}" class="btn btn-primary btn-small">Like</button> - {{ article.total_likes }} + </form> </div> </div> </div> diff --git a/news/urls.py b/news/urls.py index a3be455..b5b46a2 100644 --- a/news/urls.py +++ b/news/urls.py @@ -6,6 +6,7 @@ from .views import ( ArticleUpdateView, ArticleDeleteView, UserArticleListView, + LikeView, ) from . import views @@ -20,4 +21,5 @@ urlpatterns = [ path('article/new/', ArticleCreateView.as_view(), name='article-create'), path('article/<int:pk>/update/', ArticleUpdateView.as_view(), name='article-update'), path('article/<int:pk>/delete/', ArticleDeleteView.as_view(), name='article-delete'), + path('like/<int:pk>', LikeView, name='like_article') ] diff --git a/news/views.py b/news/views.py index a97b94e..37b94c7 100644 --- a/news/views.py +++ b/news/views.py @@ -10,6 +10,9 @@ from django.views.generic import ( DeleteView, ) +from django.http import HttpResponseRedirect +from django.urls import reverse_lazy, reverse + from .models import Article from users.models import Profile @@ -112,6 +115,13 @@ class UserArticleListView(ListView): class ArticleDetailView(DetailView): model = Article + def get_context_data(self, *args, **kwargs): + context = super(ArticleDetailView, self).get_context_data(**kwargs) + article = get_object_or_404(Article, id=self.kwargs['pk']) + total_likes = article.total_likes + context["total_likes"] = total_likes + return context + class ArticleCreateView(LoginRequiredMixin, CreateView): model = Article fields=['headline','header','header_caption','content','tag'] @@ -140,6 +150,12 @@ class ArticleDeleteView(LoginRequiredMixin, UserPassesTestMixin, DeleteView): article = self.get_object() return self.request.user == article.author + +def LikeView (request, pk): + article = get_object_or_404(Article, id=request.POST.get('article_id')) + article.likes.add(request.user) + return HttpResponseRedirect(reverse('article-detail', args=[str(pk)])) + def createProfileIfNotExist (request): if request.user.is_authenticated and Profile.objects.filter(user=request.user).count() < 1: Profile.objects.create(user=request.user).save()