carribeiro / vdeli

Video Delivery Network
2 stars 0 forks source link

Videofile grid contains files from all users, not only the one logged on #23

Closed carribeiro closed 13 years ago

carribeiro commented 13 years ago

Grid view should be filtered by the current user. As it is now, every user sees the video from all users.

carribeiro commented 13 years ago

Implementing a solution using the request.user information, and traversing the relationships: VideoFile -> VideoProject -> User, to select all projects from a given user.

>>> from videorepo.models import VideoFile
>>> from django.contrib.auth.models import User
>>> from django.db.models import Q
>>> VideoFile.objects.select_related().filter(~Q(project__user__id=2), project__isnull=False)
[<VideoFile: VideoFile /home/cribeiro/work/vdeli/cdnmanager/cdnmanager/cdn/uploads/cribeiro/myproject/test_data_03 (1024000 bytes)> ...

I'm not sure if it will work because of the way Ajax works, and also due to the way the jqGrid class works. The ProjectGrid class have to be "recreated" and that will require a class factory. The class does not use a constructor (it's a purely declarative class). The basic code is as follows:

def ProjectGrid(user_id=None)
    """ Class factory"""

    class ProjectGrid(JqGrid):
        if user_id is None:
            model = VideoFile
        else:
            model = VideoFile.objects.select_related().filter(~Q(project__user__id=user_id), project__isnull=False)

...
carribeiro commented 13 years ago

This bug was MUCH harder to solve than expected, thanks to a few idiosyncrasies and at least one bug in the jqgrid.py module. Importante notes:

1) In the grid definition, one has to explicitly tell if the grid will show a Model or a QuerySet. In our case the code is:

        if user is None:
            model = VideoFile
        else:
            queryset = VideoFile.objects.select_related().filter(
                        project__user__id=user.id, 
                        project__isnull=False
                        )

2) In the jqgrid.py module, we had to fix the get_queryset method:

    def get_queryset(self, request):
        if hasattr(self, 'queryset') and self.queryset is not None:
            # Fix the problem where the queryset wasn't being converted to a ValueQuerySet
            # and so couldn't be iterated over
            #queryset = self.queryset._clone()
            queryset = self.queryset.values(*self.get_field_names())

The problem was that when the grid used a Model, it was converting to a ValueQuerySet; in this case all the entries are in memory and can be filtered/sorted very efficiently, at the cost of memory. When the grid used a QuerySet, the result was not expressed as a ValueQuerySet but as a plain QuerySet, which is not iterable in the same way (the ValueQuerySet is just a list of dicts and is iterable on both levels).

NOTE: This fix should be contributed to the original project.