一尘不染

在Django模型中存储列表的最有效方法是什么?

django

目前,我的代码中有很多类似于以下内容的python对象:

class MyClass():
  def __init__(self, name, friends):
      self.myName = name
      self.myFriends = [str(x) for x in friends]

现在,我想将其转换为Django模型,其中self.myName是字符串字段,而self.myFriends是字符串列表。

from django.db import models

class myDjangoModelClass():
    myName = models.CharField(max_length=64)
    myFriends = ??? # what goes here?

由于列表是python中如此常见的数据结构,因此,我希望其中有一个Django模型字段。我知道我可以使用ManyToMany或OneToMany关系,但是我希望避免代码中的额外间接访问。


阅读 1068

收藏
2020-03-27

共2个答案

一尘不染

将这种关系更好地表示为Friends表的一对多外键关系吗?我知道这myFriends只是字符串,但我认为更好的设计是创建一个Friend模型,并MyClass在结果表中包含外键。

2020-03-27
一尘不染

“过早的优化是万恶之源。”
牢记这一点,让我们开始吧!一旦你的应用达到特定点,对数据进行非规范化就非常普遍。如果做得正确,它可以节省大量昂贵的数据库查找,但要多花一些工夫。

要返回list朋友名称,我们需要创建一个自定义Django Field类,该类在访问时将返回一个列表。

David Cramer在他的博客上发布了有关创建SeperatedValueField的指南。这是代码:

from django.db import models

class SeparatedValuesField(models.TextField):
    __metaclass__ = models.SubfieldBase

    def __init__(self, *args, **kwargs):
        self.token = kwargs.pop('token', ',')
        super(SeparatedValuesField, self).__init__(*args, **kwargs)

    def to_python(self, value):
        if not value: return
        if isinstance(value, list):
            return value
        return value.split(self.token)

    def get_db_prep_value(self, value):
        if not value: return
        assert(isinstance(value, list) or isinstance(value, tuple))
        return self.token.join([unicode(s) for s in value])

    def value_to_string(self, obj):
        value = self._get_val_from_obj(obj)
        return self.get_db_prep_value(value)

此代码的逻辑处理从数据库到Python的序列化和反序列化值,反之亦然。现在,你可以轻松地导入并使用模型类中的自定义字段:

from django.db import models
from custom.fields import SeparatedValuesField 

class Person(models.Model):
    name = models.CharField(max_length=64)
    friends = SeparatedValuesField()
2020-03-27