Closed DasUnicorn closed 9 months ago
So... Here's the deal. The current Version deals with votes for threads and comment separately, which results in a lot of duplicate code. I tried my hands on a VoteMixin, but run into "TypeError: Cannot create a consistent method resolution order (MRO) for bases Model, VoteMixin", I wasn't able to solve. It would be create to maybe try this again later, if I have time.
Leaving my mixin code here for future-me:
from django.db import models
from django.contrib.auth.models import User
from django.db.models import F
from taggit.managers import TaggableManager
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
from django.conf import settings
from django.utils.text import slugify
STATUS = ((0, "Draft"), (1, "Published"))
class VoteMixin(models.Model):
votes = models.IntegerField(default=0)
def up_vote(self, user):
# Check if the user has already voted for the thread or comment
if not self.vote_set.filter(user=user).exists():
self.votes = F('votes') + 1
self.save()
self.vote_set.create(user=user, value=1)
def down_vote(self, user):
# Check if the user has already voted for the thread or comment
if not self.vote_set.filter(user=user).exists():
self.votes = F('votes') - 1
self.save()
self.vote_set.create(user=user, value=-1)
class Meta:
abstract = True # This ensures that VoteMixin is not a model itself
class Thread(models.Model, VoteMixin):
title = models.CharField(max_length=200, unique=True)
slug = models.SlugField(max_length=200, unique=True)
author = models.ForeignKey(settings.AUTH_USER_MODEL,
on_delete=models.CASCADE, related_name="posts")
content = models.TextField()
created_on = models.DateTimeField(auto_now_add=True)
status = models.IntegerField(choices=STATUS, default=0)
tags = TaggableManager()
class Meta:
ordering = ["-created_on"]
def __str__(self):
return f"The title of this thread is {self.title}"
# Creating the slug
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.title)
super().save(*args, **kwargs)
class Comment(models.Model, VoteMixin):
thread = models.ForeignKey(Thread, on_delete=models.CASCADE, related_name="comments")
author = models.ForeignKey(settings.AUTH_USER_MODEL,
on_delete=models.CASCADE, related_name="commenter")
body = models.TextField()
created_on = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ["created_on"]
def __str__(self):
return f"Comment {self.body} by {self.author}"
class Vote(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
created_on = models.DateTimeField(auto_now_add=True)
value = models.SmallIntegerField()
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey('content_type', 'object_id')
Testing:
Possible future updates:
Dependencies: none
Description Of Service Or Screen: Implement Vote Model. By just having a counter that counts up and down, there is no way to determine which votes have to be deleted when a user deletes their account. So a model that connects users, votes and posts is needed.
* Fallback option: Just count up and down on a button.
User Objective: As a user, I want to vote on posts, so that
Acceptance Criteria: