0

我有一个基于 django 的网上商店,在过去的一年里一直在发展。目前大约有 8 个国家特定的商店运行相同的代码库,外加一个 API,很快就会有一个 B2B 网站,还有一些国家要添加到列表中。

模型结构需要变化,特别是地址模型、帐户模型等中的字段。

让事情变得更复杂一些,该站点正在运行 multidb,每个商店实例都在一个单独的数据库中。所以我有一种情况,我可能有一个基本的 ABC 模型,例如:

class Address(models.Model):
    class Meta:
        abstract=True

class Address_UK(Address):
    class Meta:
        db_table="shop_address"

class Address_IT(Address):
    class Meta:
        db_table="shop_address"
[etc]

然后在整个应用程序中编码以选择正确的模型,例如

if countrysettings.country == "UK":
    address = Address_UK()
elif countrysettings.country == "IT":
    address = Address_IT()

countrysettings.country 实际上是一个单独的设置类,它是 threading.local 的子类,并且国家代码也对应于 settings.DATABASES 中的一个键,由地理定位中间件处理程序配置。因此选择了正确的数据库,并且模型特定的变化反映在每个国家的数据库中。

但是这种方法存在问题:

  1. 它完全破坏了同步数据库并且对南方没有好处,除非我破解 ./manage.py 以便我可以通过国家数据库,而不是需要中间件来设置它。

  2. 看起来很乱。如果 countrysettings.country == "xx": 代码就这么多,还有很多子类模型。

所以我想改用 django-eav,但我预见到管理中的问题,特别是字段排序。我知道 django-eav 将为管理员构建一个模型表单,其中包含 eav 字段,但我理想情况下希望这些与国家相关的显示或隐藏。

我还考虑过使用非抽象基类,例如地址,然后在需要时创建特定于国家/地区的变体(例如模型表继承)。但后来我预见到基本模型会因每个模型变体的 one2one 字段而过载。但它会解决管理员的问题。

另一种选择可能是有一个额外的数据字段,并将其他字段序列化为 json 或 csv 或其他内容并将它们存储在此字段中。

4

2 回答 2

2

我可以考虑其他一些方法来解决您的问题。我相信选项 1 或选项 2 是最好的,但可能会选择选项 3。

选项 1:一个代码库、一个数据库、一个 django 实例、站点框架: 如果您实际上不需要为每个商店使用不同的数据库,请创建所有表和/或所有可能的字段,并巧妙地将站点框架用于 condour 字段字段和模型。例如:为每个地址保留一个 address_type 字段等,并在每个站点的同一数据库上使用不同的字段(和表)。这使您的代码更加复杂,但大大简化了您的 IT。如果站点之间的代码更改非常少,请使用此选项。(顺便说一句 - json 序列化是地址的一个不错的选择)。

选项2:一个代码库,许多数据库,许多django实例: 使用相同的代码库设置许多站点,但要小心使用python的条件设置和动态特性来为每个站点生成不同的模型。每个站点都有自己的 settings-uk.py、settings-us.py 等,并且将拥有自己的数据库和使用动态模型的模型。例如:

from django.conf import settings
# ...
class Address(models.Model):
     name = models.CharField(max_length=100)
     if settings.country == "US":
        state = models.CharField(max_length=2)
     else:
        country = models.CharField(max_length=100)

此方法的其他可能技巧:通过设置启用/禁用应用程序;在 wsgi 脚本/manage.py 脚本中为应用程序制作自定义 python 路径;使用if settings.country=='us': import uk_x as x else: import us_x as x. 另见:http ://code.flickr.com/blog/2009/12/02/flipping-out/

选项 3:并行代码分支、许多 DB、许多 django 实例: 使用 git 保留代码的一些分支并相互重新设置它们的基础。需要更多的 IT 工作。如果您打算拥有许多数据库和许多服务器,(以及许多开发人员?)无论如何,您可能会发现这很有用。

另一种选择:一个数据库,许多 django 实例自定义 settings.py 每个实例没有站点框架。

于 2011-06-26T23:04:30.180 回答
1

其实EAV可以解决你的问题。实际上,您可以使用 EAV 显示特定于当前对象的国家属性的字段。这是一个例子

class Country(models.Model):
    name = models.CharField(_("country"), max_length=50

class Address(eav.models.BaseEntity):
    country = models.ForeignKey(Country, related_name="country_attrs")

    # EAV specific staff
    @classmethod
    def get_schemata_for_model(self):
        # When creating object, country field is still not set
        # So we do not return any country-specific attributes
        return AddressEAVSchema.objects.filter(pk=-1).all()

    def get_schemata_for_instance(self, qs):
        # For specific instance, return only country-specific attributes if any
        try:
            return AdressEAVSchema.objects.filter(country=self.country).all()
        except:
            return qs

# Attributes now can be marked as belonging to specific country
class AdressEAVSchema(eav.models.BaseSchema)
    country = models.ForeignKey(Country, related_name="country_attrs")

# Rest of the standard EAV stuff    
class AdressEAVChoice(eav.models.BaseChoice):
    schema = models.ForeignKey(AdressEAVSchema, related_name='choices')

class AddressEAVAttribute(eav.models.BaseAttribute):
    schema = models.ForeignKey(AdressEAVSchema, related_name='attrs')
    choice = models.ForeignKey(AdressEAVChoice, blank=True, null=True)

这里如何使用它:

当您创建地址属性时,您现在还必须指定它们所属的国家/地区。

现在,当您创建新的地址对象本身时(例如在管理员中),保存,然后返回编辑它,您会看到与对象国家/地区匹配的其他特定于国家/地区的属性。

希望这可以帮助。

于 2012-02-28T10:33:24.817 回答