Search code examples
djangodatabasedjango-modelsdjango-rest-frameworksignals

A question app that the user must give coins to ask a question and the answerer will get the coins


enter code hereI am creating a kind of a question and answer web application. I want the user asking the question to compulsorily give coins. The choices are already there. Then the user that answers the question gets the coins given by the other user. I am using Django signals, but the user that ask the question got his coins deducted but the answerer didn't get any coin it is given me an error. This is the model for the question and answer. I already have the user model with the user default coin as 5000 error message

class Question(models.Model):
    COINS_CHOICES = (
        (10, 10),
        (20, 20),
        (30, 30),
        (40, 40),
        (50, 50),
        (60, 60),
        (70, 70),
        (80, 80),
        (90, 90),
        (100, 100),

    )
    label = models.CharField(max_length=5000)
    image = models.ImageField()
    #slug = models.SlugField()
    timestamp = models.DateTimeField(auto_now_add=True)
    updated_on = models.DateTimeField(auto_now_add=True)
    subject = models.ForeignKey(Subject, on_delete=models.CASCADE)
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    coins_given = models.PositiveSmallIntegerField(choices=COINS_CHOICES, blank=False, null=True)

    def __str__(self):
        return self.label
    
class Answer(models.Model):
    label = models.CharField(max_length=5000)
    image = models.ImageField()
    timestamp = models.DateTimeField(auto_now_add=True)
    updated_on = models.DateTimeField(auto_now_add=True)
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    clap = models.ManyToManyField(settings.AUTH_USER_MODEL, related_name="answers")
    
    
    def __str__(self):
        return self.label
    
    
    def number_of_clap(self):
        return self.clap.count()
    
    
class Comment(models.Model):
    text = models.TextField()
    timestamp = models.DateTimeField(auto_now_add=True)
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    answer = models.ForeignKey(Answer, on_delete=models.CASCADE)

@receiver(post_save, sender=Question)    
def subtract_coins_from_user(sender, instance, created, **kwargs):
    if created:
        profile = instance.user
        profile.coin -= instance.coins_given
        profile.save()
        
    
@receiver(post_save, sender=Answer)
def add_coins_to_user(sender, instance, created, **kwargs):
    if created:
        profile = instance.user
        profile.coin += instance.coins_given
        profile.save()
    

Solution

  • An Answer model has no field coins_given, the related question has, so you obtain the coins_given of the .question of the instance with:

    @receiver(post_save, sender=Answer)
    def add_coins_to_user(sender, instance, created, **kwargs):
        if created:
            profile = instance.user
            profile.coin += instance.question.coins_given
            profile.save()

    That being said, I'm not sure that using signals is a good idea: signals can be circumvented, and can have unwanted side-effects and make it less predictable what a .save() will do.