Search code examples
pythondjangodjango-modelsdjango-querysetdjango-generic-relations

How to link 3rd party model and view with own model in Django


I successfully implemented django-contrib-comments to my project and starting to adjust it step by step to make it 100% suitable to my project. Now I have the following issue which I cannot solve:

I have a model Poller which offers two possible votes for any user stored in the model Vote. Now if a user comments on a poller I would like to return his individual vote for this specific poller to the rendered comment in the template.

Since I don't wanna touch the 3rd partie's architecture by any means, I would prefer to get the required queryset in my view.

Comment model of django-contrib-comments package

class CommentAbstractModel(BaseCommentAbstractModel):

    user = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name=_('user'),
                
    [..]             

My Poller, Vote and Account/User models

class Poller(models.Model):
    poller_id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    created_on = models.DateTimeField(auto_now_add=True)
    created_by = models.ForeignKey(Account, on_delete=models.CASCADE)
[..]

class Vote(models.Model):
    poller = models.ForeignKey(Poller, on_delete=models.CASCADE, related_name='vote')
    user = models.ForeignKey(Account, on_delete=models.CASCADE)
    created_on = models.DateTimeField(auto_now_add=True)
    poller_choice_one_vote = models.BooleanField(default=False)
    poller_choice_two_vote = models.BooleanField(default=False)
[..]

class Account(AbstractBaseUser):

    username = models.CharField(max_length=40, unique=True)
[..]

To make a long story short, how can I access the Vote Model for each user who posted a comment to determine which vote he picked? Maybe by subclassing the CommentAbstractModel and add a foreign key to the Vote model?

@require_GET
def single_poller(request, poller_id):
    """
    renders a specific poller with prepopulated meta according to previous
    user interaction, e.g. votes and likes
    """

    # Retrieve the item via get
    poller = Poller.objects.get(poller_id=poller_id)
    
    [..] # how to go on here?

Solution

  • You can define a GenericRelation on the Poller model to get all the comments to a specific poll. With that we can then have access to the users, and filter votes based on that:

    from django.contrib.contenttypes.fields import GenericRelation
    
    
    class Poller(models.Model):
        ...
        comments = GenericRelation(MyCommentModel) # Change MyCommentModel to the comment model you used
    
    poller = Poller.objects.get(poller_id=poller_id)
    
    votes = Vote.objects.filter(
        poller=poller,
        user__in=poller.comments.all().values('user')
    )
    

    EDIT:

    It seems django comments uses a different name for the object_id field. To fix that we need to add object_id_field and set it to object_pk in the GenericRelation (object_pk is what django-comments seems to be using, no need to migrate when adding this):

    class Poller(models.Model):
        comments = GenericRelation(
            Comment,
            object_id_field='object_pk', # <-- Add this
        )