views:

909

answers:

3

Hi all,

I'm having problems structuring classes in the Model part of an MVC pattern in my Python app. No matter how I turn things, I keep running into circular imports. Here's what I have:

Model/__init__p.y

  • should hold all Model class names so I can do a "from Model import User" e.g. from a Controller or a unit test case

Model/Database.py

  • holds Database class
  • needs to import all Model classes to do ORM
  • initialization should be performed on first module import, i.e. no extra init calls or instantiations (all methods on Database class are @classmethods)

Model/User.py

  • contains User model class
  • needs access to Database class to do queries
  • should inherit from base class common to all Model classes to share functionality (database persistency methods, parameter validation code etc.)

I have yet to see a real world Python app employing MVC, so my approach is probably un-Pythonic (and possibly a language-agnostic mess on top of that...) - any suggestions on how to solve this?

Thanks, Simon

+2  A: 

Generally, we put it all in one file. This isn't Java or C++.

Start with a single file until you get some more experience with Python. Unless your files are gargantuan, it will work fine.

For example, Django encourages this style, so copy their formula for success. One module for the model. A module for each application; each application imports a common model.

Your Database and superclass stuff can be in your __init__.py file, since it applies to the entire package. That may reduce some of the circularity.

S.Lott
Good advice. Keep it simple until you gain more expertise.
codeape
A: 

I think you have one issue that should be straightened. Circular references often result from a failure to achieve separation of concerns. In my opinion, the database and model modules shouldn't know much about each other, working against an API instead. In this case the database shouldn't directly reference any specific model classes but instead provide the functionality the model classes will need to function. The model in turn, should get a database reference (injected or requested) that it would use to query and persist itself.

Joe Skora
+5  A: 

There is an inconsistency in your specification. You say Database.py needs to import all Model classes to do ORM but then you say the User class need access to the Database to do queries.

Think of these as layers of an API. The Database class provides an API (maybe object-oriented) to some physical persistence layer (such as DB-API 2.0). The Model classes, like User, use the Database layer to load and save their state. There is no reason for the Database.py class to import all the Model classes, and in fact you wouldn't want that because you'd have to modify Database.py each time you created a new Model class - which is a code smell.

davidavr