Sytuacja
Django modelu proxy do innej bazy danych
Mamy kilka różnych aplikacji, które wykorzystują bilety od systemu wsparcia bilet na różnego rodzaju funkcjonalności.
Przede wszystkim mamy aplikację, która ma kilka modeli reprezentujących modele naszego systemu obsługi biletów Kayako. Ta aplikacja nie powinna wiedzieć nic o innych aplikacjach, które jej używają i powinna pozostać jak najbardziej ogólna. Ponieważ ta aplikacja korzysta z istniejących tabel Kayako, uruchamiamy ją w tej samej bazie danych. Nazwijmy tę aplikację kayakodb
.
Jedna aplikacja łączy klientów z naszej bazy danych klientów z biletami w systemie obsługi biletów. Poprzednio ten system posiadał własną reprezentację biletów w naszym systemie obsługi zgłoszeń, wyszukując bilety za pomocą interfejsu API dostarczonego przez kayakodb
. Następnie wykorzystała tę reprezentację biletów do połączenia klientów i domen. Było to jednak zbyt złożone i niezbyt logiczne. Dlatego zdecydowaliśmy się przełączyć na model proxy i przenieść modele reprezentujące łącza do klientów i domen na kayakodb
. Nazwijmy tę aplikację sidebar
.
Kolejna, nowa aplikacja pokazuje bilety z systemu wsparcia biletów w przejrzysty sposób wraz z połączeniami telefonicznymi, dzięki czemu nasz dział wsparcia może łatwo sprawdzić, które połączenia i bilety są powiązane z wybranymi klientami. Ten system ma model proxy dla modelu proxy z sidebar
, ponieważ niektóre funkcje zapewnione przez model sidebar
są również wymagane dla tej aplikacji wraz z innymi, które deklaruje nowy model proxy. Nazwijmy ten projekt WOW
.
Aplikacje sidebar
i WOW
są częścią tego samego projektu/repozytorium. Nazwiemy to repozytorium Coneybeach
, które ma własną bazę danych. Jednak kayakodb
jest całkowicie niezależnym projektem. Jest on zawarty w Coneybeach
poprzez plik wymagań, który instalujemy poprzez pip
.
Problem
Przy tworzeniu migracji do nowej konfiguracji Django tworzy model proxy migracji dla zainstalowanego
kayakodb
co jest, oczywiście, nie iść. Za każdym razem, gdy instalujemy nową wersję
kayakodb
, zostanie ona nadpisana. Nie mówiąc już o tym, że
kayakodb
nie powinien wiedzieć nic o tym, które modele z niego korzystają.
kod
Ticket
modelu wewnątrz
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
Model SidebarTicket
Pełnomocnik wewnątrz 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
potrzeb klasy Contact
TicketWrapper
dziedziczy od (a żądanie Hynekc er).Model ten jest używany jako model bazowy TicketWrapper
i innego modelu reprezentującego połączeń (choć nie ma problemów z tym modelem ile jestem świadomy):
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)
Model TicketWrapper
proxy wewnątrz 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
Co mają próbowałem
- próbowałem nie określając th e
app_label
dla obu modeli proxy. Tworzy to poprawne migracje, ale powoduje, że modele proxy szukają modelukayakodb.Ticket
w bazie danych Coneybeach. - Podjęto próbę określenia
abstract = True
dla podklas, ale nie byłem pewien, czy to dlatego, że nadal chcę móc korzystać z menedżera dla modeli. - Zastanawiam się nad przeniesieniem migracji, która jest obecnie tworzona, do rzeczywistego projektu
kayakodb
, ale nie sądzę, że jest to dobre rozwiązanie.kayakodb
nie powinien wiedzieć nic o implementacjach swoich modeli lub miejscach, w których są używane. ./manage.py check
zwraca 0 wydań.
Pytanie
Jak mogę utworzyć model proxy dla modelu, który znajduje się w innej bazy danych lub projektu?
Edit
Po ustawieniu modelu
kayakodb.Ticket
być niekontrolowana projekt
WOW
próbuje utworzyć migracji dla
wszystkich modeli
kayakodb
. Rezultat:
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
@ e4c5 Tak, wiem o tym. To miło i wszystko, ale jeśli to jest konsekwencja, gdy zostanie nadpisane. – Bono
Sam tak mówisz "To dlatego, że model proxy może zostać skierowany przez inny model w przyszłej migracji." Dlaczego w przeciwnym razie miałby przeszkadzać w stworzeniu migracji, jeśli można ją później wyrzucić? – Bono
Masz mnie tam !! Wycofujemy głosowanie bliskie. – e4c5