Question

I've been using django-relationships to allow users to follow each other. If Bob follows Joe. Bob will be able to see all of Joe's photos. However if Bob blocks John, John will not be Bob's photos.

My problem is that I don't know how to restrict content from a blocked user. I've seen the examples but I still can't seem to find a solution.

Assume Photographer is a FK to User

Here is my FollowingPhoto resource (this resources returns all photos that belong to the people that the user is following):

FollowingPhoto(ModelResource):
     photographer = fields.ForeignKey(PhotographerResource, 'photographer', full=True)
     class Meta:
          queryset = Photo.objects.all().order_by('-postTime')
          resource_name = 'following'
          fields = ['id', 'title', 'url', 'likes','postTime','photographer', 'location_id', 'location_name']
          authentication = BasicAuthentication()
          authorization = DjangoAuthorization()
          serializer = Serializer(formats=['json'])
          include_resource_uri = False
          filtering = {
                 'postTime': ALL,
                 'photographer' : ALL_WITH_RELATIONS,


         }

     def get_object_list(self, request):
             return super(FollowingPhoto, self).get_object_list(request).filter(photographer__user__in = request.user.relationships.following())

Now as you may have noticed with my get_object_list, it returns all the content from the users I am following. How can prevent users who are blocked from showing up on this list?

The Django-relationships app generates two tables in postgresql, the table below is the relationships_relationships table:

    id       from_user    to_user_id   status_id            created
[PK] serial   integer      integer                         timestamp
    6            1            5           1         2012-10-05 20:10:29.848667+00"
    7            1            3           1         2012-10-05 20:11:23.319961+00"

And the other table is the relationships_relationshipstatus table:

    id          name          verb         from_slug        login_required   private
[PK] serial   character     character   character varying      boolean       boolean
    1         Following      follow         friends             FALSE         FALSE
    2         Blocking        block         !                   TRUE          TRUE

Below I have added a link to Django-relationships models.py so that you may get further clarification:

models.py

Was it helpful?

Solution

It looks to me like you just need a .exclude clause - something like:

def get_object_list(self, request):
     return super(FollowingPhoto, self).get_object_list(request).filter(photographer__user__in = request.user.relationships.following()).exclude(photographer__user__in=request.user.relationships.blocking())

That will prevent Bob from seeing John's photos if Bob is blocking John. Given that Bob only sees John's photos if Bob is following John, it will do nothing unless Bob is both following and blocking John, which seems odd to me - do you maybe want Bob to not see John's photos if John is blocking Bob instead? If so:

def get_object_list(self, request):
    return super(FollowingPhoto, self).get_object_list(request).filter(photographer__user__in = request.user.relationships.following()).exclude(photographer__user__in=request.user.relationships.blockers())

OTHER TIPS

Create a custom manager. Depending on whether you are selecting all photos that a user can see or all users whose photos you are allowed to see makes a difference on whether you want a RelationshipManager or PhotosManager. I'm assuming you want a feed of photos - you can adapt this to limit users pretty easily w/ a bit of sql.

PhotosManager(models.Manager):
    def get_unblocked(self, user):
        sql = """SELECT myapp_photo.* 
            FROM myapp_photo
            INNER JOIN auth_user
                ON myapp_photo.user_id = auth_user.id
            WHERE auth_user.id != %d /*DO NOT SHOW YOUR OWN PHOTOS*/
            AND myapp_photo.user_id NOT IN(
                SELECT myapp_blocked.blocked_user_id
                FROM myapp_blocked
                WHERE myapp_blocked.user_id = %d
            )""" % (user.pk, user.pk)

        return self.model.objects.raw(sql)

Apologies for the horrible sql, I don't know your table structure I'm just trying to illustrate a point

Then in your Photo model add objects = PhotosManager()

And you can now get a list of photos that are not blocked in your view:

Photos.objects.get_unblocked(request.user)

EDIT:

I just realized my code only takes into account blocked users and not followers. Again w/o knowing your table structure I'd just be guessing. You can add another AND myapp_photo.user_id IN( clause to allow only photos from users that are following. Also, you could write better sql for sure, this was a quick and dirty example. my solution: write a manager, the actual provided sql is just for illustrative purposes.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top