Our views are slow because of `LDPPermissions`
LDPPermissions are certainly the biggest reason why our views are slower than DRF
What do we have?
- on the container,
filter_user_permsis called on the parent and child model, to filter the queryset (resolving model permissions for each) - when each object in the queryset is serialized, the full permissions are serialized (including object and backend permissions), which is more expensive & involves database hits
The MR open for the issue (!175 (merged) ) replaces filter_user_perms with prefilter_query_set, which essentially does the same thing but earlier in the get_queryset, and at the cost that developers need to override prefilter_query_set in their own permissions classes (or those they install). The cache speeds up permissions hits on repeat requests, avoiding database hits by spending memory
Ignoring the ugliness/bugginess of LDPPermissions in general (in this issue), I should note that DRF avoids analysing object permissions in the queryset at all, explicitly for performance reasons, and requires that developers override filter_queryset or provide custom FilterBackends to achieve this functionality
What do we want?
To achieve good performance we need:
- remove the behaviour of automatically filtering values in
LDPSerializer.to_representation - remove the auto-generation of the Web-ACLs for retrieved resources (unless requested explicitly?), meaning these are only serialized for the container
To achieve good usability I think we want:
- to filter values in
LDPViewSetin a way that's efficient and easily extensible - to render WebACLs dynamically so that these can be returned
- to override/extend filters easily on viewsets for custom models
- a simpler system for overriding
LDPPermissions(another issue)
with nested fields, we need:
- values to be filtered when they are a nested property in another (parent) model's viewset
- the filters from my custom viewset on this model, universally(?) also need to be applied in the nested field of the parent viewset (e.g.
circles/x/members/is theCircleViewSet)
What are we going to do?
What can be automatically filtered (in filter_queryset or in a FilterBackend)?
- we can easily and efficiently check model permissions. This is "yes" or "no" information, it tells us to start with the whole queryset or with none of them
- we can use Django-Guardian's
get_objects_for_userto apply object and group-level permissions
rendering WebACLs dynamically (['permissions']: ... on the serialized resource)..
- is this required by LDP? When do we use it? Could it be skipped in the list view? @matthieu @balessan
override/extend filters easily on viewsets or custom models
- easy as adding a
FilterBackendfor the direct viewset.. but the nested viewset is a question mark!
@balessan context for this morning