Created
February 2, 2012 15:57
-
-
Save vmihailenco/1724187 to your computer and use it in GitHub Desktop.
Model update for Django <= 1.3
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import operator | |
| from django.db.models.expressions import F, ExpressionNode | |
| EXPRESSION_NODE_CALLBACKS = { | |
| ExpressionNode.ADD: operator.add, | |
| ExpressionNode.SUB: operator.sub, | |
| ExpressionNode.MUL: operator.mul, | |
| ExpressionNode.DIV: operator.div, | |
| ExpressionNode.MOD: operator.mod, | |
| ExpressionNode.AND: operator.and_, | |
| ExpressionNode.OR: operator.or_, | |
| } | |
| class CannotResolve(Exception): | |
| pass | |
| def _resolve(instance, node): | |
| if isinstance(node, F): | |
| return getattr(instance, node.name) | |
| elif isinstance(node, ExpressionNode): | |
| return _resolve(instance, node) | |
| return node | |
| def resolve_expression_node(instance, node): | |
| op = EXPRESSION_NODE_CALLBACKS.get(node.connector, None) | |
| if not op: | |
| raise CannotResolve | |
| runner = _resolve(instance, node.children[0]) | |
| for n in node.children[1:]: | |
| runner = op(runner, _resolve(instance, n)) | |
| return runner | |
| def update(instance, **kwargs): | |
| "Atomically update instance, setting field/value pairs from kwargs" | |
| if instance.pk is None: | |
| raise TypeError('Can not update instance without pk.') | |
| # fields that use auto_now=True should be updated corrected, too! | |
| for field in instance._meta.fields: | |
| if hasattr(field, 'auto_now') and \ | |
| field.auto_now and field.name not in kwargs: | |
| kwargs[field.name] = field.pre_save(instance, False) | |
| rows_affected = instance.__class__._default_manager \ | |
| .filter(pk=instance.pk) \ | |
| .update(**kwargs) | |
| # apply the updated args to the instance to mimic the change | |
| # note that these might slightly differ from the true database values | |
| # as the DB could have been updated by another thread. callers should | |
| # retrieve a new copy of the object if up-to-date values are required | |
| for k, v in kwargs.iteritems(): | |
| if isinstance(v, ExpressionNode): | |
| v = resolve_expression_node(instance, v) | |
| setattr(instance, k, v) | |
| return rows_affected |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment