Django models 正在查找Django自定义字段,该字段通过在列中存储ID列表来模拟ManyToManyField
我希望使用多对多关系将MyModel链接到AnotherModel,而不实际使用SQL关系:相反,我希望在MyModel的列中存储AnotherModel PK的列表,并使用自定义字段处理到QuerySet(或实例列表)的转换以及AnotherModel到MyModel的反向关系 你知道有谁已经这样做了吗,或者你有没有简单的方法来做的建议?我已经开始自己实现它,但是我开始意识到完全实现一个多域的行为是多么复杂:我对Django还是相当陌生,正确地实现它需要对框架的内部工作有一些熟悉 到目前为止,我得到了这个:Django models 正在查找Django自定义字段,该字段通过在列中存储ID列表来模拟ManyToManyField,django-models,custom-fields,Django Models,Custom Fields,我希望使用多对多关系将MyModel链接到AnotherModel,而不实际使用SQL关系:相反,我希望在MyModel的列中存储AnotherModel PK的列表,并使用自定义字段处理到QuerySet(或实例列表)的转换以及AnotherModel到MyModel的反向关系 你知道有谁已经这样做了吗,或者你有没有简单的方法来做的建议?我已经开始自己实现它,但是我开始意识到完全实现一个多域的行为是多么复杂:我对Django还是相当陌生,正确地实现它需要对框架的内部工作有一些熟悉 到目前为止,
class InlineManyToManyField(models.CharField):
__metaclass__ = models.SubfieldBase
def __init__(self, other_model, *args, **kwargs):
try:
assert not other_model._meta.abstract, "{0} cannot define a relation with abstract class {0}".format(
self.__class__.__name__, to._meta.object_name)
except AttributeError:
assert isinstance(other_model, basestring), "{0}({1}) is invalid. First parameter to InlineManyToManyField must be either a model, a model name, or the string self".format(
self.__class__.__name__,unicode(other_model))
kwargs['max_length'] = kwargs.get('max_length', 255)
kwargs['blank'] = kwargs.get('blank', True)
self.other_model = other_model
self.token = kwargs.pop('token', ' ')
super(InlineManyToManyField, self).__init__(*args, **kwargs)
def to_python(self, value):
if not value: return
if isinstance(value, basestring):
pk_list = value.split(self.token)
pk_list.pop(0)
pk_list.pop()
value = self.other_model._default_manager.filter(pk__in=pk_list)
return value
def get_db_prep_value(self, value, connection, prepared=False):
if not value: return
pk_list = [item.pk for item in value]
pk_list.sort()
return self.token + self.token.join(unicode(pk) for pk in pk_list) + self.token
def contribute_to_class(self, cls, name):
super(InlineManyToManyField, self).contribute_to_class(cls, name)
if isinstance(self.other_model, basestring):
def resolve_through_model(field, model, cls):
field.other_model = model
add_lazy_relation(cls, self, self.other_model, resolve_through_model)
def value_to_string(self, obj):
value = self._get_val_from_obj(obj)
return self.get_db_prep_value(value)
def get_db_prep_lookup(self, lookup_type, value, connection, prepared=False):
if lookup_type in ('contains', 'icontains'):
if isinstance(value, self.other_model):
value = value.pk
return ["%{0}{1}{0}%".format(self.token, connection.ops.prep_for_like_query(value))]
return super(InlineManyToManyField, self).get_db_prep_lookup(
lookup_type, value, connection=connection, prepared=prepared)
下面是我如何使用它:
class MyModel(models.Model):
anotherlist = InlineManyToManyField(AnotherModel, token=':')
如果mymodel表包含一行pk=1和另一行=“:1:2:3:”,我可以这样做:
>>> m = MyModel.objects.get(pk=1)
>>> m.anotherlist
[<AnotherModel: 1>, <AnotherModel: 2>, <AnotherModel: 3>]
>>> MyModel.objects.filter(anotherlist__contains=2)
[<MyModel: 2>]
>m=MyModel.objects.get(pk=1)
>>>m.另一个名单
[, ]
>>>MyModel.objects.filter(另一个列表包含=2)
[]
接下来我想添加的是相反的关系:我希望在AnotherModel实例上设置mymodel_,例如使用上面的“contains”代码,但我很难理解
django/db/models/fields/related.py中的一切工作原理:)
所以,在我花几天时间写这本书之前,你有没有在任何地方偶然发现类似的东西,或者你自己也写过类似的东西?嗯。。。为什么?和。。不要!
所有流行的sql数据库都可以很好地扩展。你不应该害怕内心的联结!。。他们很好
你想做的有点痛苦。。。撇开这一点不谈,如果删除AnotherModel实例,您会怎么做?是否扫描所有MyModel表以查找字符串id?当Django 5.6.6.1出现并且某些内容不兼容时会发生什么情况?重写?还要考虑管理模块和影响/更改
不要从一开始就过度投入到最微小的性能上!如果损坏则修复,如果未损坏则测试
在应用程序的架构上投入更多的时间,你会很好的
回答你们的问题:不,我也想过类似的事情,搜索一下,但并没有发现任何有用的东西 你不可能以你想要的方式倒车。相反,您只需向AnotherModel添加一个属性函数:
class AnotherModel(models.Model):
// set up model here
def mymodels(self):
return MyModel.objects.filter(anotherlist__contains=self.pk)
那应该行。只是好奇;你为什么要这么做?我有一个交易卡游戏。假设我有500000个用户,每个用户平均有20个甲板。每副牌包含大约90张牌。使用常规的ManyToManyField,我的关系表将有近十亿个条目。。。这太过分了,我宁愿每副牌有一行,在VARCHAR中有“内联”的牌列表。我想只要你不打算按牌搜索玩家(即,哪些玩家拥有或使用给定的牌),就可以了。就我个人而言,我觉得数据就是数据;无论是存储在单个字段中还是存储在一组行中,其数量都是相同的。您为服务器购买ssd。。。多个服务器:)。