mno*_*tka 3 python database django orm
django核心代码片段:
class ForeignKey(RelatedField, Field):
...
def db_type(self, connection):
rel_field = self.rel.get_related_field()
if (isinstance(rel_field, AutoField) or
(not connection.features.related_fields_match_type and
isinstance(rel_field, (PositiveIntegerField,
PositiveSmallIntegerField)))):
return IntegerField().db_type(connection=connection)
return rel_field.db_type(connection=connection)
Run Code Online (Sandbox Code Playgroud)
这段代码非常糟糕,因为如果我定义了一个继承自的自定义字段AutoField,那么我的db_type方法将被忽略.
我想做的是隐藏我的类是一个实例的事实AutoField.在C++中,我会通过私有继承来实现.
有没有办法欺骗isinstance返回False或隐藏继承?
我的cutom字段代码:
class MyAutoField(models.AutoField):
def __init__(self, length, *args, **kwargs):
self.length = length
super(MyAutoField, self).__init__(*args, **kwargs)
def db_type(self, connection):
if connection.vendor == 'oracle':
return 'NUMBER(%s,0)' % (self.length)
if connection.vendor == 'postgresql':
if self.length <= 4:
return 'smallint'
if self.length <= 9:
return 'integer'
return 'bigint'
return super(MyAutoField, self).db_type(connection)
Run Code Online (Sandbox Code Playgroud)
所以我有办法做到这一点,但它通过"猴子补丁".您无法使用,ABCMeta因为这需要您覆盖基类的元类.
您可以"更改"实例如下.重要的是"补丁"只能导入一次,我只会这样做,如果没有别的办法.
patches.py
import django.models
import mymodel
import __builtin__
def _isinstance(instance, clz):
if clz is models.AutoField and isinstance_orig(instance, MyAutoField):
return False
return isinstance_orig(instance, clz)
__builtin__.isinstance_orig = __builtin__.isinstance
__builtin__.isinstance = _isinstance
Run Code Online (Sandbox Code Playgroud)
然后你的测试程序:
class MyAutoField(models.AutoField): pass
x = MyAutoField()
print(isinstance(x, models.AutoField))
print(isinstance(x, models.MyAutoField))
Run Code Online (Sandbox Code Playgroud)
介绍抽象基类: PEP-3119.以下是一个抽象的例子......
class ABCMeta(type):
def __instancecheck__(cls, inst):
"""Implement isinstance(inst, cls)."""
return any(cls.__subclasscheck__(c)
for c in {type(inst), inst.__class__})
def __subclasscheck__(cls, sub):
"""Implement issubclass(sub, cls)."""
candidates = cls.__dict__.get("__subclass__", set()) | {cls}
return any(c in candidates for c in sub.mro())
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
846 次 |
| 最近记录: |