Skip to content

Commit

Permalink
Added ForUserFlexQuery
Browse files Browse the repository at this point in the history
  • Loading branch information
Robert Schindler committed Aug 8, 2019
1 parent 0ed3e53 commit 3dd4c82
Show file tree
Hide file tree
Showing 7 changed files with 98 additions and 1 deletion.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0


## 2.1.0 - Unreleased
### Added
* Added `django_flexquery.contrib.for_user.ForUserFlexQuery`
### Changed
* Changed directory structure of unittests

Expand Down
Empty file.
45 changes: 45 additions & 0 deletions django_flexquery/contrib/for_user.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
"""
FlexQuery variant that filters the base QuerySet for a given user.
"""

from django.http import HttpRequest

from ..flexquery import FlexQuery
from ..q import Q


__all__ = ["ForUserFlexQuery"]


class ForUserFlexQuery(FlexQuery):
"""
This is a slightly modified ``FlexQuery`` implementation, accepting either
a ``django.http.HttpRequest`` or a user object as argument for the custom
function and passing the user through. When no user (or ``None``) is given,
the default behavior is to hide all objects. This can be changed by setting the
``none_if_no_user`` attribute to ``True``.
Because it can handle an ``HttpRequest`` directly, instances of this ``FlexQuery``
may also be used in conjunction with the django_filters library as the ``queryset``
parameter of filters.
"""

none_if_no_user = False

def call_bound(self, user, *args, **kwargs): # pylint: disable=arguments-differ
"""Calls the custom function with a user, followed by the remaining arguments.
:param user: User to filter the queryset for
:type user: django.contrib.auth.models.User | django.http.HttpRequest | None
:returns Q:
"""
try:
user = user.user if isinstance(user, HttpRequest) else user
except AttributeError:
user = None
if user is None:
if self.none_if_no_user:
return Q(pk__in=self.base.none())
return Q()

return super().call_bound(user, *args, **kwargs)
7 changes: 7 additions & 0 deletions docs/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,10 @@ API Documentation

.. automodule:: django_flexquery
:members:


``contrib.for_user``
--------------------

.. automodule:: django_flexquery.contrib.for_user
:members:
6 changes: 5 additions & 1 deletion tests/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,9 @@

SECRET_KEY = "om-l3b3%$jutfygk%pyg#i0hp@g$v4b=-jcsa_)+%^7nig@up4"
DEBUG = True
INSTALLED_APPS = ["django_flexquery_tests"]
INSTALLED_APPS = [
"django.contrib.auth",
"django.contrib.contenttypes",
"django_flexquery_tests",
]
DATABASES = {"default": {"ENGINE": "django.db.backends.sqlite3", "NAME": ":memory:"}}
Empty file.
39 changes: 39 additions & 0 deletions tests/testsuite/contrib/test_for_user.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
from django.contrib.auth.models import AnonymousUser
from django.test import RequestFactory, TestCase

from django_flexquery import *
from django_flexquery.contrib.for_user import *
from django_flexquery_tests.models import *


class ForUserFlexQueryTestCase(TestCase):
def setUp(self):
class Man(Manager):
@ForUserFlexQuery.from_q
def fq(base, user):
assert isinstance(user, AnonymousUser)
return Q(a=42)

self.man = Man()
self.man.model = AModel
self.req = RequestFactory().get("/")

AModel.objects.create(a=24)
AModel.objects.create(a=42)

def test_user(self):
self.assertEqual(self.man.fq(AnonymousUser()).count(), 1)

def test_request(self):
self.req.user = AnonymousUser()
self.assertEqual(self.man.fq(self.req).count(), 1)

def test_request_no_user(self):
self.assertEqual(self.man.fq(self.req).count(), 2)

def test_no_user_all(self):
self.assertEqual(self.man.fq(None).count(), 2)

def test_no_user_none(self):
self.man.fq.__class__.none_if_no_user = True
self.assertEqual(self.man.fq(None).count(), 0)

0 comments on commit 3dd4c82

Please sign in to comment.