0

私はこの1年で進化しているdjangoベースのウェブショップを持っています。現在、同じコードベースに加えてAPIを実行している国固有のショップが約8つあり、まもなくB2B Webサイトが作成され、さらにいくつかの国がリストに追加されます。

モデル構造には、特に住所モデルや勘定モデルなどのフィールドの周りにバリエーションが必要です。

さらに複雑なことに、サイトはマルチデータベースを実行しており、各ショップインスタンスは別々のデータベースにあります。したがって、ベース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をハックして、ミドルウェアに設定する代わりに国のdbを渡すことができない限り、syncdbを完全に破壊し、南には適していません。

  2. 散らかっているようです。countrysettings.country == "xx"の場合はこれだけです:コードがうそをついている、そして非常に多くのサブクラス化されたモデル。

そのため、代わりにdjango-eavを使用することを考えていましたが、管理者、特にフィールドの順序に問題があると予想しています。django-eavがeavフィールドを含む管理者用のモデルフォームを作成することは知っていますが、理想的には、国に関連してこれらを表示または非表示にする必要があります。

また、Addressなどの抽象化されていない基本クラスを用意し、必要に応じて国固有のバリエーションを作成することも検討しました(Model Table Inheritanceなど)。しかし、その後、各モデルバリアントに対してone2oneフィールドでベースモデルが過負荷になると予測します。しかし、それは管理者の問題を解決するでしょう。

別のオプションとして、追加のデータフィールドを用意し、追加のフィールドをjsonやcsvなどにシリアル化して、このフィールドに保存することもできます。

4

2 に答える 2

2

私はあなたの問題を攻撃する他のいくつかの方法について考えることができます。オプション1またはオプション2が最適だと思いますが、オプション3を選択することもできます。

オプション1:1つのコードベース、1つのdb、1つのdjangoインスタンス、サイトフレームワーク: ストアごとに個別のデータベースが実際に必要ない場合は、すべてのテーブルやすべての可能なフィールドを作成し、condourフィールドフィールドにサイトフレームワークをスマートに使用しますおよびモデル。例:アドレスごとにaddress_typeフィールドなどを保持し、サイトごとに同じデータベースで異なるフィールド(およびテーブル)を使用します。これにより、コードはより複雑になりますが、ITは大幅に簡素化されます。サイト間でのコード変更がごくわずかな場合に使用します。(ところで-jsonシリアル化はアドレスに適したオプションです)。

オプション2:1つのコードベース、多くのDB、多くのdjangoインスタンス: 同じコードベースで多くのサイトを設定しますが、Pythonの条件付き設定と動的機能を慎重に使用して、サイトごとに異なるモデルを生成します。各サイトには独自の設定(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 script/manage.pyスクリプトでアプリのカスタムpythonpathを作成します。を使用します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作業が必要です。とにかく、多くのデータベースと多くのサーバー(および多くの開発者?)を計画している場合は、これが役立つ場合があります。

別のオプション:1つのDB、サイトフレームワークなしのインスタンスごとに多くの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)

ここでそれを使用する方法:

アドレス属性を作成するときは、それらが属する国も指定する必要があります。

これで、新しいAddressオブジェクト自体を作成し(たとえばadminで)、保存してから編集に戻ると、オブジェクトの国に一致する追加の国固有の属性が表示されます。

お役に立てれば。

于 2012-02-28T10:33:24.817 に答える