10 сайтов через одну и ту же кодовую базу Django MTI, ABC или EAV - PullRequest
0 голосов
/ 26 июня 2011

У меня есть интернет-магазин на основе 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 и кодом страны, который также соответствует ключу в настройках. Базы данных, настраиваются обработчиком промежуточного программного обеспечения геолокации. Таким образом, выбирается правильная база данных, и конкретные отклонения модели отражаются в базе данных каждой страны.

Но у этого подхода есть проблемы:

  1. Он полностью нарушает syncdb и не годится для юга, если только я не взломаю ./manage.py, чтобы я мог передать db страны, вместо того, чтобы требовать промежуточное программное обеспечение для его установки.

  2. Кажется грязным. Так много, если countrysettings.country == "xx": код лежит и так много подклассов.

Так что я думал об использовании django-eav вместо этого, но я предвижу проблемы в админе, и в частности упорядочение полей. Я знаю, что django-eav создаст модель модели для администратора, которая включает поля eav, но в идеале я бы хотел, чтобы они отображались или скрывались в зависимости от страны.

Также я подумал о том, чтобы иметь не абстрактный базовый класс, например Адрес, а затем, при необходимости, создайте специфические для страны варианты (например, наследование таблицы моделей). Но затем я предвижу, что базовые модели будут перегружены полями one2one для каждого варианта модели. Но это решит проблемы с админом.

Другой вариант может состоять в том, чтобы иметь дополнительное поле данных и сериализовать дополнительные поля в json или csv или что-то еще и сохранять их в этом поле.

Ответы [ 2 ]

2 голосов
/ 27 июня 2011

Я могу подумать о нескольких других способах решения вашей проблемы.Я считаю, что вариант 1 или вариант 2 являются лучшими, но можно выбрать вариант 3.

Вариант 1: одна база кода, один дБ, один экземпляр django, фреймворк сайтов: Если вы это сделаетена самом деле не требуется отдельная база данных для каждого магазина, создайте все таблицы и / или все возможные поля и разумно используйте инфраструктуру sites для полей и моделей полей condour.Например: сохраните для каждого адреса поле address_type и т. Д. И используйте разные поля (и таблицы) в одном и том же БД для каждого сайта.Это усложняет ваш код, но значительно упрощает его.Используйте это, если изменения кода между сайтами очень минимальны.(кстати, сериализация json - хороший вариант для адресации)условные настройки и динамические возможности 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)

Другие возможные хитрости для этого метода: включить / отключить приложения через настройки;Создание пользовательских pythonpath для приложений в скрипте wsgi script / manage.py;используйте 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: параллельные ветви кода, много БД, много экземпляров django: Используйте git, чтобы сохранить несколько веток вашего кода и перебазировать их друг с другом.Требует гораздо больше ИТ-усилий.Если вы планируете иметь много БД и много серверов (и много разработчиков?), В любом случае, вы можете найти это полезным.

Другие варианты: одна БД, много экземпляров django пользовательские настройки.py за экземпляр без каркаса сайтов.

1 голос
/ 28 февраля 2012

На самом деле EAV может решить вашу проблему. Фактически вы можете использовать EAV для отображения полей, которые относятся к атрибуту страны текущего объекта. Вот пример

</p> <pre><code>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), сохраняете, а затем возвращаетесь к его редактированию, вы видите дополнительные специфичные для страны атрибуты, которые соответствуют объектам country.

Надеюсь, это поможет.

...