更新我现在认为 是定义get_prep_value()
的理由,这样做可以改善Django对该字段的使用。我也能够摆脱包装类。所有这一切,最终使我能够经常消除__getattribute__ implementation with the data model, which was annoying. So, apart from Django calling
to_python()`super,我现在已经很好了。的 /更新
一天早上,你醒来后发现自己在Python 2.6.8上使用Django 1.4.2和DjangoRESTFramework 2.1.2。嘿,事情肯定会更糟。这个Django管理员魔术为您提供了易于指定的关系数据模型的表单,使您能够很好地维护数据库的编辑部分。 RESTful URL背后的业务逻辑可以访问编辑数据和特定数据库表以满足他们的需求,甚至那些都显示在Django管理员中,部分原因是它很容易完成并且很好用,部分原因是一些自动生成的记录需要一个迷你工作流程
但是等等。您仍然没有将这些二进制字段实现为BINARY。他们是VARCHARS 。您已将其放在待办事项列表中以供日后使用。后来现在。
好的,有一些一次写入多次读取的情况,表格尺寸很小,优化不一定会付出代价。但在另一种情况下,由于表中的频繁INSERT和DELETE会变大,你会浪费存储和性能。
那么你想拥有什么? DB和Django之间的清晰映射,其中DB存储BINARY和Django处理长度为两倍的十六进制字符串。不可能难以实现,可以吗?
你搜索网络并找到想要CHAR而不是VARCHAR的人,其他人想要BLOB,而且每个人似乎都有点不同。最后,你最终到了Writing custom model fields,其中VARCHAR - > CHAR案件正式处理。所以你决定使用这些信息。
从__init__()
,db_type()
和to_python()
开始,您会注意到很少调用to_python()
并添加__metaclass__ = models.SubfieldBase
只是为了表明Django现在调用{{ 1}}即使之前已经这样做了。页面上的其他建议突然开始对你更有意义,所以你要将你的数据包装在一个类中,这样你就可以防止它重复调用to_python()
。您还应遵循to_python()
的建议并实施Put a __str__() or __unicode__() method on the class you're wrapping up as a field
。
虽然生成的代码没有达到您的预期,但您注意到的一件事是到目前为止 get_prep_value()
永远不会被调用,因此您暂时将其删除。您做的结果是 Django始终从数据库中获得get_prep_value()
,从管理员获得str
,这很酷,并且结束这样的事情(归结为必需品,真的)。
unicode
而且......它不会起作用。当然,原因在于,当您找到一种可靠的方法从包括Django本身在内的所有来源创建class MyHexWrappeer(object):
def __init__(self, hexstr):
self.hexstr = hexstr
def __len__(self):
return len(self.hexstr)
def __str__(self):
return self.hexstr
class MyHexField(models.CharField):
__metaclass__ = models.SubfieldBase
def __init__(self, max_length, *args, **kwargs):
assert(max_length % 2 == 0)
self.max_length = max_length
super(MyHexField, self).__init__(max_length=max_length, *args, **kwargs)
def db_type(self, connection):
return 'binary(%s)' % (self.max_length // 2)
def to_python(self, data):
if isinstance(data, MyHexWrapper): # protect object
return data
if isinstance(data, str): # binary string from DB side
return MyHexWrapper(binascii.b2a_hex(data))
if isinstance(data, unicode): # unicode hex string from admin
return MyHexWrapper(data)
对象时,显然缺少向后的路径。从上面的评论中,您认为Django在数据库的方向上调用了MyHexWrapper
或str()
来管理员和unicode()
。但是,如果你在上面添加get_prep_value()
,它将永远不会被调用,而你就会被卡住。
那不可能,对吗?所以你不愿意轻易放弃。突然间,你得到了这个令人讨厌的想法,而你正在进行测试,而且它有效。你不知道你应该笑还是哭。
所以现在你尝试这种修改,不管你信不信,它只是有效。
get_prep_value()
它有效吗?好吧,如果你在代码中使用这样的字段,比如RESTful URL,那么你必须确保你有正确的字符串类型;这是一个纪律问题。
但是,它仍然只能在大多数情况下起作用。因为当你将这样的字段作为主键时,Django会调用class MyHexWrapper(object):
def __init__(self, hexstr):
self.hexstr = hexstr
def __len__(self):
return len(self.hexstr)
def __str__(self): # called on its way to the DB
return binascii.a2b_hex(self.hexstr)
def __unicode__(self): # called on its way to the admin
return self.hexstr
,而我发现有一个消息来源声称quote(getattr())
“nowdays”将使用getattr()
我无法确认。但是,一旦你走到这一步,这不是一个严重的障碍,嗯?
unicode()
像魅力一样工作。但是,现在您向后倾斜并整体查看您的解决方案。并且您无法确定它是从您引用的文档中转移出来,使用您未想要的未记录或内部行为特征,以及由于您必须实现和遵守的内容有点分散,因此容易出错且显示开发人员的可用性差。
那么如何以更清洁的方式实现目标呢? Django中是否存在另一个带有挂钩和魔法的关卡,应该找到这个映射?
感谢您的时间。