views:

43

answers:

3

Is there a reasonable pattern for handling an object that exists as a Django model within the context of a particular Django application and as a non-Django class outside of that particular application?

For example, let's say that I have a Post model within Django application Blog. I want to be able to interact with a class representing this post outside of the Blog Django application and possibly within a different Django application.

In the past I have just created two completely separate classes with slightly different interfaces. The Django model contains to and from methods to create from the non-Django version or to export to the non-Django version. But this feels all wrong to me.

EDIT: I realize that my language and the use of the word 'access' is confusing. I'm not asking about how to talk to a Django application, I'm asking about how to have a Django model class and a non-Django class represent the same data with the same interface where I can export a Django model object to the non-Django class so I can use it in another application. Errr, that probably wasn't clear either was it?

A: 

You can use Django code outside of the normal server environment (as the test cases do). If you need to write Python scripts that play with your Django models, you can just access/modify your models as usual, using the ORM, there's just a short magic incantation you have to use first:

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()

I tend to avoid this legwork using management commands.

If you need to have multiple Django applications accessing this data, that's fine - just make sure they're in the same Django project.

If you really need to have them in separate projects, then I'd probably write an API that interacts with Django views to add, fetch, update or delete my models - probably using a REST API. You can get some ideas for doing that here.

Dominic Rodger
I definitely do NOT want the model being used as a model outside of the django application that it came from. And I'm not having a problem getting the data to and from the application. The problem I'm having is that I'm writing two classes that look very similar but they have different APIs. Is there a way for me to minimize the amount and complexity of code that I have to write every time I have a thing that I want 1. represented as tables in a database with django and 2. interacted with outside of the database context.
guidoism
A: 

I'm having trouble imagining what you mean by 'accessing the object outside of the Django application'. How will the external application get the data that defines the model instance? How are the two applications related - are they simply different areas of the same code, or are they completely separate processes communicating via something like HTTP?

If they're separate, you may want to create a RESTful API to your models, which the external app can then access over HTTP. The django-piston project makes this simple. Is that the sort of thing you're after?

Daniel Roseman
A: 

If I understand you correctly, you have something that you want to represent in multiple programs as an object. To make matters more interesting, if your object is being used in the context of a Django program, you'd like your object to be a Django model, so that you can persist your object in a database, and do all of the other neat things that Django can do with a model. Presumably, although you don't state it explicitly, instead of just enumerating properties of the object, you have behavior that you'd like to have your object implement regardless of the environment (Django or otherwise).

If you were implementing this in Java or C#, I'd suggest something like this:

interface IFoo { ... }
class FooHelper { ... }
class app1.Foo extends Model implements IFoo { ... }
class app2.Foo implements IFoo { ... }

For each method available in IFoo, both app1.Foo and app2.Foo would need to implement the method by delegating to a matching method in FooHelper. As an example, a bar method would look like this:

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 );
    }
}

Of course FooHelper is going to have to be smart enough to Do The Right Thing depending upon which type of Foo it gets passed.

Solving this in Python should be easier, since Python is a dynamic language.

# 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()

Just put all of your functionality into the decorate_foo function, and then let it add that functionality to the class before you need to invoke one of the added methods.

Craig Trader