Last active
April 5, 2016 21:55
-
-
Save kbussell/1fae1a58aa5d427e458007583e5229a1 to your computer and use it in GitHub Desktop.
This file contains 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
from django.db import models | |
from django.utils.functional import curry | |
class PrivateFieldDescriptor(object): | |
def __init__(self, field): | |
self.field = field | |
def __get__(self, instance, type=None): | |
if instance is None: | |
raise AttributeError('Can only be accessed via an instance.') | |
return self.field.get_value(instance) | |
def __set__(self, instance, value): | |
if self.field.name in instance.__dict__: | |
raise AttributeError( | |
'Direct {0} modification is not allowed'.format(self.field.name)) | |
self.field.set_value(instance, value) | |
def field_setter_func(instance, value, field): | |
return field.set_value(instance, value) | |
class PrivateFieldMixin(object): | |
descriptor_class = PrivateFieldDescriptor | |
def get_value(self, instance): | |
return instance.__dict__[self.name] | |
def set_value(self, instance, state): | |
instance.__dict__[self.name] = state | |
def contribute_to_class(self, cls, name, virtual_only=False): | |
self.base_cls = cls | |
super(PrivateFieldMixin, self).contribute_to_class(cls, name, virtual_only=virtual_only) | |
setattr(cls, self.name, self.descriptor_class(self)) | |
setattr(cls, 'set_' + self.name, curry(field_setter_func, field=self)) | |
class PrivateCharField(PrivateFieldMixin, models.CharField): | |
pass | |
class SomeModel(models.Model): | |
private_field = PrivateCharField(max_length=64) | |
def do_something(self, pub, priv): | |
self.set_private_field(priv) | |
self.save() |
This file contains 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
from django.test import TestCase | |
from django_private_field.private_field.models import SomeModel | |
class ModelTest(TestCase): | |
def test_set(self): | |
m = SomeModel() | |
m.set_private_field('private!!') | |
m.save() | |
m = SomeModel.objects.first() | |
self.assertEqual(m.private_field, 'private!!') | |
def test_direct_set(self): | |
m = SomeModel() | |
with self.assertRaises(AttributeError): | |
m.private_field = 'Fail' |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment