'private' models, default query sets, and chaining methods

I have a privateboolean flag in my model and a user manager that overrides the get_query_set method, with a filter, removing private = True:

class myManager(models.Manager):
    def get_query_set(self):
        qs = super(myManager, self).get_query_set()
        qs = qs.filter(private=False)
        return qs

class myModel(models.Model):
    private = models.BooleanField(default=False)
    owner = models.ForeignKey('Profile', related_name="owned")
    #...etc...

    objects = myManager()

I want the default query to exclude default private models as a security measure to prevent accidental use of a model showing private models.

Sometimes, however, I want to show private models, so I have the following in the manager:

def for_user(self, user):
    if user and not user.is_authenticated():
        return self.get_query_set()
    qs = super(myManager, self).get_query_set()
    qs = qs.filter(Q(owner=user, private=True) | Q(private=False))
    return qs

This works fine, with the restriction that I cannot bind a filter. This becomes a problem when I have fk indicating myModel and using otherModel.mymodel_set. otherModel.mymodel_set.for_user (user) does not work because mymodel_set returns a QuerySet object, not a manager.

, for_user() QuerySet, , ( , get_query_set) QuerySet , ( super(), .)

?

- , , djangoy/DRY, . , , .

manji , , , , . , , ?

+3
3

QuerySet ( ):

class MyQuerySet(models.query.QuerySet):

    def public(self):
        return self.filter(private=False)

    def for_user(self, user):
        if user and not user.is_authenticated():
            return self.public()
        return self.filter(Q(owner=user, private=True) | Q(private=False))

, MyQuerySet (MyQuerySet , [ __getattr__]):

# A Custom Manager accepting custom QuerySet
class MyManager(models.Manager):

    use_for_related_fields = True

    def __init__(self, qs_class=models.query.QuerySet):
        self.queryset_class = qs_class
        super(QuerySetManager, self).__init__()

    def get_query_set(self):
        return self.queryset_class(self.model).public()

    def __getattr__(self, attr, *args):
        try:
            return getattr(self.__class__, attr, *args)
        except AttributeError:
            return getattr(self.get_query_set(), attr, *args) 

:

class MyModel(models.Model):
    private = models.BooleanField(default=False)
    owner = models.ForeignKey('Profile', related_name="owned")
    #...etc...

    objects = myManager(MyQuerySet)

:

  :

    MyModel.objects.filter(..

  for_user:

    MyModel.objects.for_user(user1).filter(..

- (use_for_related_fields = True), . , :

  :

    otherModel.mymodel_set.filter(..

  for_user :

    otherModel.mymodel_set.for_user(user).filter(..


: Django QuerySets ( django)

+2

, get_query_set for_user QuerySet.

, .

class CustomQuerySet(models.query.QuerySet):
    def for_user(self):
        return super(CustomQuerySet, self).filter(*args, **kwargs).filter(private=False)

class CustomManager(models.Manager):
    def get_query_set(self):
        return CustomQuerySet(self.model, using=self._db)
0

"reset", QuerySet ( reset). , , , filter/exclude etc reset. , , .

manji .

, manji, "model"."private" = False ("model"."owner_id" = 2 AND "model"."private" = True ) OR "model"."private" = False ). where query , . WhereNode, where, node . as_sql node, , , :


from django.db import connection
qn = connection.ops.quote_name
q = myModel.objects.all()
print q.query.where.children[0].as_sql(qn, connection)

- :


('"model"."private" = ?', [False])

, , , , Django, , , API-.

My recommendation would be to use two managers . One that can access everything (escape hatch sorting), and the other with default filtering. The default manager is the first, so you need to play around with the order depending on what you need to do. Then rebuild your code to find out which one to use, so you have no problem with having extra private = False in it.

0
source

All Articles