python 类继承list_关于python:你将如何继承并覆盖django模型类来创建listOfStringsField?...

我想为django模型创建一个新类型的字段,它基本上是一个ListOfStrings。因此,在您的模型代码中,您将拥有以下内容:

models.py:

from django.db import models

class ListOfStringsField(???):

???

class myDjangoModelClass():

myName = models.CharField(max_length=64)

myFriends = ListOfStringsField() #

other.py:

myclass = myDjangoModelClass()

myclass.myName ="bob"

myclass.myFriends = ["me","myself","and I"]

myclass.save()

id = myclass.id

loadedmyclass = myDjangoModelClass.objects.filter(id__exact=id)

myFriendsList = loadedclass.myFriends

# myFriendsList is a list and should equal ["me","myself","and I"]

您将如何编写此字段类型,并遵循以下规定?

我们不想创建一个只将所有字符串组合在一起的字段,并在一个字段中用一个标记将它们分开。在某些情况下,这是一个很好的解决方案,但我们希望保持字符串数据的标准化,以便django以外的工具可以查询数据。

该字段应自动创建存储字符串数据所需的任何辅助表。

理想情况下,辅助表应该只包含每个唯一字符串的一个副本。这是可选的,但是很高兴。

看看Django代码看起来我想做类似于ForeignKey正在做的事情,但文档很稀疏。

这导致以下问题:

可以这样做吗?

它已经完成(如果是这样的话)?

关于如何扩展和覆盖他们的模型类,特别是他们的关系类,是否有关于Django的文档?我没有看到很多关于他们代码方面的文档,但是有这个。

这是来自这个问题。

这绝对是可能的,虽然我不知道具体细节。 我说阅读他们的邮件列表并查看文档,但最终你可能不得不深入挖掘Django源代码。

我现在正在挖掘源头。 如果我真的设法提出一些有用的东西,我会尝试在这里发布。

在下面发表我的尝试,似乎有效。

所以下面我的尝试确实有效,但是非常脆弱且容易出错。:(

这里有一些关于创建自定义字段的非常好的文档。

但是,我认为你是在思考这个问题。听起来你实际上只是想要一个标准的外键,但是能够将所有元素作为单个列表检索。所以最简单的方法就是使用ForeignKey,并在模型上定义一个get_myfield_as_list方法:

class Friends(model.Model):

name = models.CharField(max_length=100)

my_items = models.ForeignKey(MyModel)

class MyModel(models.Model):

...

def get_my_friends_as_list(self):

return ', '.join(self.friends_set.values_list('name', flat=True))

现在,在MyModel实例上调用get_my_friends_as_list()将根据需要返回字符串列表。

我原以为ForeignKey属于Friends类。我错过了什么吗?是的,我可能在想这个,但是如果我能创造这个领域,我想我认为它通常是有用的。

对不起,你是对的,我已经更新了代码。

我认为FK也是去这里的方式。 +1用于添加检索朋友列表的方法。

你所描述的对我来说听起来与标签非常相似。

那么,为什么不使用django标记呢?

它就像一个魅力,你可以独立于你的应用程序安装它,它的API非常容易使用。

此外,如果它不像OP想要的那样工作,那么很容易看到它是如何在那里完成的,并根据他的需要进行改变。

太好了!我将不得不进一步研究这个问题。

我也认为你这是错误的做法。试图让Django字段创建一个辅助数据库表几乎肯定是错误的方法。如果你试图使你的解决方案普遍有用,那将很难做到,并且可能会使第三方开发人员感到困惑。

如果你试图在一个列中存储非规范化的blob数据,我会采用类似于你链接的方法,序列化Python数据结构并将其存储在TextField中。如果您希望Django以外的工具能够对数据进行操作,那么您可以序列化为JSON(或其他一些具有广泛语言支持的格式):

from django.db import models

from django.utils import simplejson

class JSONDataField(models.TextField):

__metaclass__ = models.SubfieldBase

def to_python(self, value):

if value is None:

return None

if not isinstance(value, basestring):

return value

return simplejson.loads(value)

def get_db_prep_save(self, value):

if value is None:

return None

return simplejson.dumps(value)

如果您只想要一个类似django Manager的描述符,它允许您操作与模型关联的字符串列表,那么您可以手动创建连接表并使用描述符来管理关系。这不完全是你需要的,但这段代码应该让你开始。

我有机会看看你发布的链接。我认为它比我现在所做的实施方式更接近于我所做的。谢谢!

如果它用于非规范化,则仅使用此方法+1!否则,正常化!

请注意,get_db_prep_save现在需要4个参数(从django 1.5开始)

感谢所有回答的人。即使我没有直接使用你的答案,例子和链接也让我朝着正确的方向前进。

我不确定这是否已准备就绪,但到目前为止它似乎在我的所有测试中都有效。

class ListValueDescriptor(object):

def __init__(self, lvd_parent, lvd_model_name, lvd_value_type, lvd_unique, **kwargs):

"""

This descriptor object acts like a django field, but it will accept

a list of values, instead a single value.

For example:

# define our model

class Person(models.Model):

name = models.CharField(max_length=120)

friends = ListValueDescriptor("Person","Friend","CharField", True, max_length=120)

# Later in the code we can do this

p = Person("John")

p.save() # we have to have an id

p.friends = ["Jerry","Jimmy","Jamail"]

...

p = Person.objects.get(name="John")

friends = p.friends

# and now friends is a list.

lvd_parent - The name of our parent class

lvd_model_name - The name of our new model

lvd_value_type - The value type of the value in our new model

This has to be the name of one of the valid django

model field types such as 'CharField', 'FloatField',

or a valid custom field name.

lvd_unique - Set this to true if you want the values in the list to

be unique in the table they are stored in. For

example if you are storing a list of strings and

the strings are always"foo","bar", and"baz", your

data table would only have those three strings listed in

it in the database.

kwargs - These are passed to the value field.

"""

self.related_set_name = lvd_model_name.lower() +"_set"

self.model_name = lvd_model_name

self.parent = lvd_parent

self.unique = lvd_unique

# only set this to true if they have not already set it.

# this helps speed up the searchs when unique is true.

kwargs['db_index'] = kwargs.get('db_index', True)

filter = ["lvd_parent","lvd_model_name","lvd_value_type","lvd_unique"]

evalStr ="""class %s (models.Model):

""" % (self.model_name)

evalStr +="""    value = models.%s(""" % (lvd_value_type)

evalStr += self._params_from_kwargs(filter, **kwargs)

evalStr +=")

"

if self.unique:

evalStr +="""    parent = models.ManyToManyField('%s')

""" % (self.parent)

else:

evalStr +="""    parent = models.ForeignKey('%s')

""" % (self.parent)

evalStr +="

"

evalStr +="""self.innerClass = %s

""" % (self.model_name)

print evalStr

exec (evalStr) # build the inner class

def __get__(self, instance, owner):

value_set = instance.__getattribute__(self.related_set_name)

l = []

for x in value_set.all():

l.append(x.value)

return l

def __set__(self, instance, values):

value_set = instance.__getattribute__(self.related_set_name)

for x in values:

value_set.add(self._get_or_create_value(x))

def __delete__(self, instance):

pass # I should probably try and do something here.

def _get_or_create_value(self, x):

if self.unique:

# Try and find an existing value

try:

return self.innerClass.objects.get(value=x)

except django.core.exceptions.ObjectDoesNotExist:

pass

v = self.innerClass(value=x)

v.save() # we have to save to create the id.

return v

def _params_from_kwargs(self, filter, **kwargs):

"""Given a dictionary of arguments, build a string which

represents it as a parameter list, and filter out any

keywords in filter."""

params =""

for key in kwargs:

if key not in filter:

value = kwargs[key]

params +="%s=%s," % (key, value.__repr__())

return params[:-2] # chop off the last ', '

class Person(models.Model):

name = models.CharField(max_length=120)

friends = ListValueDescriptor("Person","Friend","CharField", True, max_length=120)

最终,我认为如果将其深入到django代码中并且更像ManyToManyField或ForeignKey,它仍然会更好。

我注意到这个类,你必须在添加之前保存,因为在你保存之前ID不存在。我认为这可以修复/纠正,如果这继承自RelatedField和Field,但我仍然试图绕过那段代码。

经过更多的实验,结果证明是有效的,但是非常脆弱,特别是在命名空间方面,它必须存在于models.py中。我将继续努力,并希望开发一个更清洁的版本。

我想你想要的是一个自定义模型领域。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值