app/django/db/models/query_utils.py
author Daniel Diniz <ajaksu@gmail.com>
Fri, 03 Jul 2009 14:35:03 +0200
changeset 2502 2e096acc8720
parent 323 ff1a9aa48cfd
permissions -rw-r--r--
Surveys can now have required questions and comments can be turned on/off. Storing comments is now working. However some issues arise when form errors occur, like missing context and the errors also trigger before a form has been submitted. Reviewed by: Lennard de Rijk

"""
Various data structures used in query construction.

Factored out from django.db.models.query so that they can also be used by other
modules without getting into circular import difficulties.
"""

from copy import deepcopy

from django.utils import tree

class QueryWrapper(object):
    """
    A type that indicates the contents are an SQL fragment and the associate
    parameters. Can be used to pass opaque data to a where-clause, for example.
    """
    def __init__(self, sql, params):
        self.data = sql, params

class Q(tree.Node):
    """
    Encapsulates filters as objects that can then be combined logically (using
    & and |).
    """
    # Connection types
    AND = 'AND'
    OR = 'OR'
    default = AND

    def __init__(self, *args, **kwargs):
        super(Q, self).__init__(children=list(args) + kwargs.items())

    def _combine(self, other, conn):
        if not isinstance(other, Q):
            raise TypeError(other)
        obj = deepcopy(self)
        obj.add(other, conn)
        return obj

    def __or__(self, other):
        return self._combine(other, self.OR)

    def __and__(self, other):
        return self._combine(other, self.AND)

    def __invert__(self):
        obj = deepcopy(self)
        obj.negate()
        return obj

def select_related_descend(field, restricted, requested):
    """
    Returns True if this field should be used to descend deeper for
    select_related() purposes. Used by both the query construction code
    (sql.query.fill_related_selections()) and the model instance creation code
    (query.get_cached_row()).
    """
    if not field.rel:
        return False
    if field.rel.parent_link:
        return False
    if restricted and field.name not in requested:
        return False
    if not restricted and field.null:
        return False
    return True