model_helpers.py
def cached_model_property(model_method=None, readonly=True, cache_timeout=None):
    """
    cached_model_property is a decorator for model functions that takes no arguments
    The function is converted into a property that support caching out of the box

    :param readonly: set readonly parameter False to make the property writeable
    :type readonly: bool
    :param cache_timeout: number of seconds before cache expires
    :type cache_timeout: int

    Sample usage:

    class Team(models.Model):

        @cached_model_property
        def points(self):
            # Do complex DB queries
            return result

        @cached_model_property(readonly=False)
        def editable_points(self):
            # get result
            return result

    Now try
    team = Team.objects.first()
    team.points  <-- complex DB queries will happen, result will be returned
    team.points  <-- this time result is returned from cache (points function is not called at all!
    del team.points <-- points value has been removed from cache
    team.points  <-- complex DB queries will happen, result will be returned

    set readonly parameter False to make the property writeable
    team.editable_points = 88
    in this case the assigned value will replace the value stored in the cache
    team.editable_points
    returns 88
    """

    def func(f):
        def _get_cache_key(obj):
            """
            :type obj: django.db.models.Model
            :rtype: six.string_types
            """
            # getattr(obj, "_meta") is same as obj._meta but avoid the warning about accessing protected property
            model_name = getattr(obj, "_meta").db_table
            method_name = f.__name__
            return "%s.%s.%s" % (model_name, obj.pk, method_name)

        def get_x(obj):
            # Try to get the cache key for that method
            cache_key = _get_cache_key(obj)
            result = cache.get(cache_key)
            # If not cached, call the actual method and cache the result
            if result is None:
                result = f(obj)
                set_x(obj, result)
            return result

        def del_x(obj):
            """
            Remove that property from the cache
            :param obj:
            :return: None
            """
            cache_key = _get_cache_key(obj)
            # Remove that key from the cache
            cache.delete(cache_key)

        def set_x(obj, value):
            """
            Set the cache value of that property
            :param obj:
            :return: None
            """
            cache_key = _get_cache_key(obj)
            # Save that key in the cache
            if cache_timeout is None:
                cache.set(cache_key, value)
            else:
                cache.set(cache_key, value, cache_timeout)

        if readonly:
            return property(fget=get_x, fdel=del_x)
        else:
            return property(fget=get_x, fset=set_x, fdel=del_x)

    # model_method is passed when using @cached_model_property
    if model_method:
        return func(model_method)
    # model_method is not passed when using @cached_model_property(readonly=True) or even @cached_model_property()
    return func

    cached_model_property is a decorator for model functions that takes no arguments
    The function is converted into a property that support caching out of the box

    :param readonly: set readonly parameter False to make the property writeable
    :type readonly: bool
    :param cache_timeout: number of seconds before cache expires
    :type cache_timeout: int

    Sample usage:

    class Team(models.Model):

        @cached_model_property
        def points(self):
            # Do complex DB queries
            return result

        @cached_model_property(readonly=False)
        def editable_points(self):
            # get result
            return result

    Now try
    team = Team.objects.first()
    team.points  <-- complex DB queries will happen, result will be returned
    team.points  <-- this time result is returned from cache (points function is not called at all!
    del team.points <-- points value has been removed from cache
    team.points  <-- complex DB queries will happen, result will be returned

    set readonly parameter False to make the property writeable
    team.editable_points = 88
    in this case the assigned value will replace the value stored in the cache
    team.editable_points
    returns 88
    
cached_model_property is a decorator for model functions that takes no arguments
The function is converted into a property that support caching out of the box
cached_model_property is a decorator for model functions that takes no arguments The function is converted into a property that support caching out of the box
def cached_model_property(model_method=None, readonly=True, cache_timeout=None):
    def func(f):
        def _get_cache_key(obj):
            model_name = getattr(obj, "_meta").db_table
            method_name = f.__name__
            return "%s.%s.%s" % (model_name, obj.pk, method_name)
        def get_x(obj):
            cache_key = _get_cache_key(obj)
            result = cache.get(cache_key)
            if result is None:
                result = f(obj)
                set_x(obj, result)
            return result
        def del_x(obj):
            cache_key = _get_cache_key(obj)
            cache.delete(cache_key)
        def set_x(obj, value):
            cache_key = _get_cache_key(obj)
            if cache_timeout is None:
                cache.set(cache_key, value)
            else:
                cache.set(cache_key, value, cache_timeout)
        if readonly:
            return property(fget=get_x, fdel=del_x)
        else:
            return property(fget=get_x, fset=set_x, fdel=del_x)
    if model_method:
        return func(model_method)
    return func
def cached_model_property ( model_method = None , readonly = True , cache_timeout = None ) : def func ( f ) : def _get_cache_key ( obj ) : """
            :type obj: django.db.models.Model
            :rtype: six.string_types
            """ model_name = getattr ( obj , "_meta" ) . db_table method_name = f . __name__ return "%s.%s.%s" % ( model_name , obj . pk , method_name ) def get_x ( obj ) : cache_key = _get_cache_key ( obj ) result = cache . get ( cache_key ) if result is None : result = f ( obj ) set_x ( obj , result ) return result def del_x ( obj ) : """
            Remove that property from the cache
            :param obj:
            :return: None
            """ cache_key = _get_cache_key ( obj ) cache . delete ( cache_key ) def set_x ( obj , value ) : """
            Set the cache value of that property
            :param obj:
            :return: None
            """ cache_key = _get_cache_key ( obj ) if cache_timeout is None : cache . set ( cache_key , value ) else : cache . set ( cache_key , value , cache_timeout ) if readonly : return property ( fget = get_x , fdel = del_x ) else : return property ( fget = get_x , fset = set_x , fdel = del_x ) if model_method : return func ( model_method ) return func
cached_model_property is a decorator for model functions that takes no arguments
The function is converted into a property that support caching out of the box
cached_model_property is a decorator for model functions that takes no arguments The function is converted into a property that support caching out of the box
"""
    cached_model_property is a decorator for model functions that takes no arguments
    The function is converted into a property that support caching out of the box

    :param readonly: set readonly parameter False to make the property writeable
    :type readonly: bool
    :param cache_timeout: number of seconds before cache expires
    :type cache_timeout: int

    Sample usage:

    class Team(models.Model):

        @cached_model_property
        def points(self):
            # Do complex DB queries
            return result

        @cached_model_property(readonly=False)
        def editable_points(self):
            # get result
            return result

    Now try
    team = Team.objects.first()
    team.points  <-- complex DB queries will happen, result will be returned
    team.points  <-- this time result is returned from cache (points function is not called at all!
    del team.points <-- points value has been removed from cache
    team.points  <-- complex DB queries will happen, result will be returned

    set readonly parameter False to make the property writeable
    team.editable_points = 88
    in this case the assigned value will replace the value stored in the cache
    team.editable_points
    returns 88
    """ """
            :type obj: django.db.models.Model
            :rtype: six.string_types
            """ # getattr(obj, "_meta") is same as obj._meta but avoid the warning about accessing protected property # Try to get the cache key for that method # If not cached, call the actual method and cache the result """
            Remove that property from the cache
            :param obj:
            :return: None
            """ # Remove that key from the cache """
            Set the cache value of that property
            :param obj:
            :return: None
            """ # Save that key in the cache # model_method is passed when using @cached_model_property # model_method is not passed when using @cached_model_property(readonly=True) or even @cached_model_property()
model_method
readonly
set readonly parameter False to make the property writeable
set readonly parameter False to make the property writeable
cache_timeout
number of seconds before cache expires
number of seconds before cache expires