两个类:一个用于Django模型,一个用于表示Django外的数据
有没有一种合理的方法来处理一个对象,它在某个Django应用中是一个Django模型,而在这个应用之外又是一个非Django类?
举个例子,我在Django应用Blog中有一个Post模型。我希望能够在Blog这个Django应用之外,甚至在另一个Django应用中,与一个表示这个帖子(Post)的类进行交互。
以前我只是创建了两个完全不同的类,它们的接口稍微有点不同。Django模型里有一些方法,可以把非Django版本的数据转换成Django模型,或者把Django模型的数据导出到非Django版本。但我觉得这样做不太对劲。
补充说明:我意识到我用的语言和“访问”这个词可能让人困惑。我并不是在问怎么和Django应用沟通,而是在问怎么让一个Django模型类和一个非Django类表示相同的数据,并且有相同的接口,这样我就可以把Django模型对象导出到非Django类中,以便在另一个应用中使用。呃,这样说可能也不够清楚,对吧?
3 个回答
我有点搞不清楚你说的“在Django应用之外访问对象”是什么意思。外部应用是怎么获取定义模型实例的数据的呢?这两个应用是怎么关联的?它们是同一代码的不同部分,还是完全独立的进程,通过像HTTP这样的方式进行通信?
如果它们是独立的,你可能需要为你的模型创建一个RESTful API,这样外部应用就可以通过HTTP访问它。django-piston这个项目可以让这个过程变得简单。你是在寻找这样的东西吗?
你可以在正常的服务器环境之外使用Django代码(就像测试案例那样)。如果你需要写一些Python脚本来操作你的Django模型,你可以像平常一样使用ORM来访问或修改你的模型,只需要先做一个简单的准备工作:
from django.core.management import setup_environ
from mysite import settings
from myapp.models import MyModel
setup_environ(settings)
# Now do whatever you want with the ORM
mystuff = MyModel.objects.all()
我通常会通过使用管理命令来避免这些繁琐的步骤。
如果你需要多个Django应用程序来访问这些数据,那也没问题——只要确保它们在同一个Django项目里就行。
如果你真的需要把它们放在不同的项目中,那我可能会写一个API,和Django的视图进行交互,以便添加、获取、更新或删除我的模型——可能会使用REST API。你可以在这里找到一些实现的思路。
如果我理解得没错,你有一个东西,想在多个程序中把它当作一个对象来使用。更有趣的是,如果这个对象是在Django程序中使用的话,你希望它能成为一个Django模型,这样你就可以把这个对象存储到数据库里,还能利用Django模型的其他一些好处。虽然你没有明确说,但我猜想你不仅仅是想列出这个对象的属性,你还希望这个对象能在不同的环境中(无论是Django还是其他)实现一些行为。
如果你是在用Java或C#来实现这个功能,我会建议你这样做:
interface IFoo { ... }
class FooHelper { ... }
class app1.Foo extends Model implements IFoo { ... }
class app2.Foo implements IFoo { ... }
对于IFoo
中每个可用的方法,app1.Foo
和app2.Foo
都需要通过调用FooHelper
中的相应方法来实现这个方法。举个例子,bar
方法可以这样写:
interface IFoo {
int bar();
}
class FooHelper {
int bar( object foo ) { ... }
}
package app1;
class Foo extends Model implements IFoo {
...
int bar() {
return FooHelper.bar( this );
}
}
package app2;
class Foo implements IFoo {
...
int bar() {
return FooHelper.bar( this );
}
}
当然,FooHelper
需要足够聪明,能够根据传入的Foo
类型做出正确的处理。
在Python中解决这个问题应该更简单,因为Python是一种动态语言。
# Create a class decorator
def decorate_foo( fooclass ):
def bar( self ):
return 0
fooclass.bar = bar
# Create a class to decorate
class Foo: pass
# Decorate the class
decorate_foo( Foo )
# Use the decorated class
f = Foo()
f.bar()
只需把你所有的功能放到decorate_foo
函数中,然后在你需要调用新增的方法之前,让它把这些功能添加到类里。