Situation
We have a few different applications which use tickets from a ticket support system for different kinds of functionality.
First of all we have an application which has a few models that represent the models of our ticket support system Kayako. This application should not know anything about other applications that make use of it and should remain as generic as possible. Since this application is using existing tables of Kayako we have it running on the same database. Let's call this application kayakodb
.
One application links customers from our customer database to tickets in the ticket support system. Previously this system had it's own representation of the tickets inside our ticket support system, querying for tickets by using an API provided by kayakodb
. It then used this representation of tickets to link customers and domains to. This however was too complex and not very logical. So we opted to switch it to a proxy model and move the models that represent the links to customers and domains to kayakodb
. Let's call this application sidebar
.
Another, new application, shows the tickets from the ticket support system in a clear overview alongside calls so our support department can easily see which calls and tickets are related to which customers. This system has a proxy model to the proxy model of sidebar
, because some of the functionality provided by the sidebar
model are also required for this application alongside some others which the new proxy model declare. Let's call this project WOW
.
The sidebar
and WOW
applications are both part of the same project/repository. We'll call this repository Coneybeach
which has its own database. However, kayakodb
is a completely unrelated project. It is included in Coneybeach
via a requirements file which we install via pip
.
Problem
When creating migrations for the new setup Django creates a proxy model migration for the installed
kayakodb
which is, of course, a no go. Any time we would install a new version of kayakodb
it would overwrite this migration. Let alone the fact that kayakodb
shouldn't know anything about which models make use of it.
Code
The
Ticket
model inside 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
The SidebarTicket
proxy model inside 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
The Contact
class TicketWrapper
inherits from (as requested by Hynekcer). This model is used as base model for TicketWrapper
and another model representing calls (though there are not issues with this model as far as I'm aware):
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)
The TicketWrapper
proxy model inside 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
What have I tried
- I've tried not specifying the
app_label
for both the proxy models. This creates correct migrations, but causes the proxy models to look for thekayakodb.Ticket
model in the Coneybeach database. - I've tried specifying
abstract = True
for the subclasses, but wasn't sure this was the because I still want to be able to make use of the manager for the models. - I considered moving the migration that gets created currently to the actual
kayakodb
project, but I don't think this is a good solution.kayakodb
shouldn't know anything about the implementations of its models or where they are used. ./manage.py check
returns 0 issues.
Question
How can I create a proxy model for a model that's located in a different database or project?
Edit
After setting the
kayakodb.Ticket
model to be unmanaged the WOW
project tries to create a migration for all models in kayakodb
. Result:
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