我有 2 个 django 项目
- 帝王猎鹰
- 系统模型
在每个项目中,我都有一个“数据源”应用程序:
- regalbeagle/数据源
- 系统模型/数据源
在每个数据源应用程序中,
- regalbeagle/数据源/models.py
- system_models/datasources/models.py
我有一个“数据源”模型:
class Datasource(models.Model):
fullname = models.CharField(max_length=100)
url = models.URLField()
source_type = SmallIntegerField(default=1)
icon = models.CharField(max_length=255)
def __unicode__(self):
return self.fullname
我将在一秒钟内了解为什么我在不同项目中的同名应用程序中有两个相同的模型,但首先我想确定我看到的奇怪行为。我已经使用 python setup.py install 将 system_models 项目安装到全局 python lib 目录中。但是,当从 regalbeagle 项目中运行 python manage.py shell 时,即使使用完全限定的路径,我也无法访问 system_models 的数据源模型。
from system_models.datasources.models import Datasource as SystemDatasource
from regalbeagle.datasources.models import Datasource
当我使用 python 检查模块查看正在加载的文件时,我看到以下内容:
inspect.getfile(SystemDatasource)
'/Users/george/svn/regalbeagle/trunk/regalbeagle/../regalbeagle/datasources/models.pyc'
inspect.getfile(Datasource)
'/Users/george/svn/regalbeagle/trunk/regalbeagle/../regalbeagle/datasources/models.pyc'
但是,如果我在 system_models 中创建一个没有相应 regalbeagle 类的虚拟模型,则路径似乎已被识别:
from system_models.datasources.models import DummyClass
inspect.getfile(DummyClass)
'/Library/Python/2.6/site-packages/system_models/datasources/models.pyc'
所以我的问题是,即使我使用完整路径导入,Django 如何神奇地将 system_models 中的 Datasource 类交换为 regalbeagle 中的那个?如果 django 不喜欢有两个同名的应用程序,为什么我的 DummyClass 似乎工作正常?
最简单的修复似乎是将 system_models 模型名称显式更改为 SystemDatasource,但这似乎违背了模块/打包的目的。
所以我的问题是:
是否有一些我可以指定的附加信息,以便 Django 允许这些模型共存?还是我是 SOL?
正如所承诺的,我为什么需要这两个版本的数据源的解释:
我有一个后端抓取过程,需要能够将数据写入数据库,出于性能原因,我希望这个数据库与我的 Web 应用程序分开。因此,我创建了一个 systemdb 并针对此同步了我的 system_models 项目。我的 Web 应用程序能够查看后端进程抓取的数据的聚合统计信息,并且执行此操作的信息位于 regalbeagle 数据库中。有一些查询需要在 regalbeagle 中加入数据源表,因为无法跨 dbs 加入,所以 regalbeagle 有自己的数据源副本。但我还需要能够更新与爬网相关的信息,我正在通过 regalbeagle 的管理界面进行更新。这意味着我也需要访问那里的表的 system_models 版本。
添加完整模型定义:
regalbeagle/datasources/models.py:
from django.db import models
class LanguageManager(models.Manager):
def filter_by_datasources(self, exclude_datasource_id_list=None):
qs = self.get_query_set().filter(datasource__isnull=False)
if exclude_datasource_id_list:
qs = qs.exclude(datasource__in=exclude_datasource_id_list)
return qs.distinct()
class Language(models.Model):
name = models.CharField(max_length=128)
objects = LanguageManager()
class Meta:
ordering = [ 'name' ]
def __unicode__(self):
return "[%s] %s" % (self.id, self.name)
class DataSourceManager(models.Manager):
def get_query_set(self):
return super(DataSourceManager, self).get_query_set() \
.extra(select={ 'lower_fullname': 'lower(fullname)' }) \
.filter(is_inactive__isnull=True) \
.order_by('lower_fullname')
class DataSource(models.Model):
fullname = models.CharField(max_length=100)
url = models.URLField()
icon = models.URLField(null=True)
language = models.ManyToManyField(Language, null=True)
objects = DataSourceManager()
def __unicode__(self):
return "[%s] %s, %s" % (self.id, self.fullname, self.url)
class DataSourceInactive(models.Model):
datasource = models.OneToOneField(DataSource, null=True, related_name='is_inactive')
def __unicode__(self):
return self.datasource.__unicode__()
system_models/datasources/models.py:
from django.db import models
# DataSource -- these are the different places that we import data
# from.
class DataSource(models.Model):
fullname = models.CharField(max_length=100)
url = models.URLField()
source_type = SmallIntegerField(default=1)
icon = models.CharField(max_length=255)
def __unicode__(self):
return self.fullname