Ситуация
У нас есть несколько различных приложений, которые используют билеты из системы поддержки билетов для различных видов функциональности.
Прежде всего, у нас есть приложение, в котором есть несколько моделей, которые представляют модели нашей системы поддержки билетов Kayako. Это приложение не должно знать ничего о других приложениях, которые его используют, и должны оставаться как можно более универсальными. Поскольку это приложение использует существующие таблицы Kayako, мы запускаем его в одной базе данных. Позвоните в это приложение kayakodb
.
Одно приложение связывает клиентов из нашей клиентской базы с билетами в системе поддержки билетов. Ранее эта система имела собственное представление билетов внутри нашей системы поддержки билетов, запрашивая билеты, используя API, предоставленный kayakodb
. Затем он использовал это представление билетов для связи клиентов и доменов. Однако это было слишком сложно и не очень логично. Поэтому мы решили переключить его на прокси-модель и переместить модели, представляющие ссылки на клиентов и домены, на kayakodb
. Позвоните в это приложение sidebar
.
Другое новое приложение показывает билеты из системы поддержки билетов в четком обзоре наряду с звонками, поэтому наш отдел поддержки может легко увидеть, какие звонки и билеты связаны с теми клиентами. Эта система имеет прокси-модель для прокси-модели sidebar
, потому что некоторые функции, предоставляемые моделью sidebar
, также требуются для этого приложения наряду с некоторыми другими, объявленными новой прокси-моделью. Позвольте назвать этот проект WOW
.
Приложения sidebar
и WOW
являются частью одного и того же проекта/репозитория. Мы будем называть этот репозиторий Coneybeach
который имеет свою собственную базу данных. Однако kayakodb
- полностью не связанный проект. Он входит в Coneybeach
через файл требований, который мы устанавливаем через pip
.
Проблема
При создании миграции для новой настройки Django создает миграцию прокси-модели для установленного
kayakodb
, который, конечно же, не идет. Каждый раз, когда мы будем устанавливать новую версию kayakodb
, она перезапишет эту миграцию. Не говоря уже о том, что kayakodb
не должен знать ничего о том, какие модели используют его.
Код
Модель
Ticket
внутри kayakodb
:
class Ticket(models.Model):
"""
This model is a representation of the data stored in the "kayako" database table "swtickets". Minus a lot of stuff
we don't use. If you add a field make sure it has the same name as the field in kayako.swtickets.
"""
# Fields, functions and manager etc.
class Meta:
db_table = 'swtickets'
managed = False
Прокси-модель SidebarTicket
внутри sidebar
:
from kayakodb.models import Ticket
class SidebarTicket(Ticket):
class Meta:
# Since this class is a wrapper we don't want to create a table for it. We only want to access the original
# model as we always do, but provide a different interface (when it comes to functions). Proxy models allow us
# to do this: https://docs.djangoproject.com/en/1.10/topics/db/models/#proxy-models
proxy = True
# Don't look for this model in the sidebar tables, but in the kayakodb tables.
app_label = 'kayakodb'
# Some extra functions
Класс Contact
TicketWrapper
наследуется от (по запросу Hynekcer). Эта модель используется в качестве базовой модели для TicketWrapper
и другой модели, представляющей вызовы (хотя, насколько мне известно, проблем с этой моделью нет):
class Contact(models.Model):
type = None
class Meta:
abstract = True
def __getattr__(self, attr):
if attr in ['customers', 'add_customer_id', 'remove_all_customers', 'byters', 'domainnames', 'add_domain_name',
'remove_domain_name', 'add_text', 'remove_text', 'texts', 'creation_date', 'add_tag', 'get_tags',
'remove_tag', 'identifier']:
raise NotImplementedError('You should implement {}'.format(attr))
raise AttributeError(attr)
Прокси-модель TicketWrapper
внутри WOW
:
from sidebar.models import SidebarTicket
class TicketWrapper(Contact, SidebarTicket):
class Meta:
# Since this class is a wrapper we don't want to create a table for it. We only want to access the original
# model as we always do, but provide a different interface (when it comes to functions). Proxy models allow us
# to do this: https://docs.djangoproject.com/en/1.10/topics/db/models/#proxy-models
proxy = True
# Don't look for this model in the WOW database, but in the kayakodb database.
app_label = 'kayakodb'
# Some extra functions
Что я пробовал
- Я пробовал не указывать
app_label
для прокси-моделей. Это создает правильные миграции, но заставляет прокси-модели искать модельkayakodb.Ticket
в базе данных Coneybeach. - Я попытался указать
abstract = True
для подклассов, но не был уверен, что это было потому, что я все еще хочу иметь возможность использовать диспетчер для моделей. - Я думал о переносе миграции, которая создается в настоящее время в фактическом проекте
kayakodb
, но я не думаю, что это хорошее решение.kayakodb
не должен знать ничего о реализации своих моделей или о том, где они используются. -
./manage.py check
возвращает 0 проблем.
Вопрос
Как создать прокси-модель для модели, расположенной в другой базе данных или проекте?
Изменить
После того, как модель
kayakodb.Ticket
будет неуправляемой, проект WOW
пытается создать миграцию для всех моделей в kayakodb
. Результат:
Migrations for 'sidebar':
0004_auto_20170116_1210.py:
- Delete model Ticket
Migrations for 'kayakodb':
0001_initial.py:
- Create model Staff
- Create model Tag
- Create model Ticket
- Create model TicketPost
- Create model TicketTag
- Create model TicketCustomer
- Create model TicketDomain
- Create proxy model SidebarTicket
- Alter unique_together for ticketdomain (1 constraint(s))
- Alter unique_together for ticketcustomer (1 constraint(s))
- Create proxy model TicketWrapper