views:

222

answers:

1

Hi,

I am writing a couple of django apps wich by design is coupled together. But i get sircular import problems. I know it might be bad design, so please give examples of better solutions, but i cant seem to find a better suited design. So if there isnt a better design, how to solve this one?

It is basically two django apps, with some models, wich relate to each other cross app-wise. In short the system is a event based system. So there is an event model and a task model. These live in different apps, Events and Tasks. When events is triggered, i need to check that surtain tasks are solved or not, and when a task is solved, that can trigger some other events.

So in events i need to store data about tasks (to check if these tasks are solved) and in tasks i need to store data about events (wich events to trigger when they are solved)

Here is some sample code from my apps:

Events app
models.py

from tasks.models import Task

class Event(models.Model):
    ...
    tasks = models.ManyToManyField(Task, help_text=_("Tasks we need to check if are solved before triggering this event."))
    ...


Tasks app
models.py

from events.models import Event

class Task(models.Model):
    ...
    events = models.ManyToManyField(Event, help_text=_("Events to trigger when this task i solved."))
    ...

This is causing import problems when i try to validate:

AttributeError: 'module' object has no attribute 'Event'

So how to solve this? Ive tried to use some of the django helper functions in hope that that would help, more specifically i've tried to use the django.db.models.get_app and get_model functions to import the models instead of directly importing them, but i still get problems.

Of course i could collect them into the same app, but i clearly belive they should live in separate apps, since they handle seperate things. But yes they are dependent on each other. If i cant solve the import problems, any ideas on how to design this different?

I could of course use some generic relations, but that would actually make things harder to understand for other people since it doesnt specify the content type that it should relate to.

+4  A: 

Both models do not need many-to-many fields.

Do not put both sides of a many-to-many relationship in your model.

When you put in one many-to-many relationship, Django inserts the other side of the relationship for you.

http://docs.djangoproject.com/en/1.1/topics/db/queries/#many-to-many-relationships

Both ends of a many-to-many relationship get automatic API access to the other end. The API works just as a "backward" one-to-many relationship, above.

"When events is triggered, i need to check that surtain tasks are solved or not".

  • This means that Event can be triggered some other way and is independent of any Task.

  • If an Event can be triggered and that leads to Tasks, then Tasks depend on Events.

"when a task is solved, that can trigger some other events"

  • This means that Tasks depend on Events. Events do not depend on Tasks.

Put the many-to-many reference to Events in Tasks. Put nothing in Events, since Events can be used elsewhere, to trigger a chain of Tasks and other Events. Some client application will import Events only.

Further, you can provide many-to-many field references using a string name instead of importing the model.

S.Lott
Sure about this? It is not the same tasks and events. One task may trigger certain events, but not the same events that might check if that task is solved.Can you use string name insted of importing the model if it isnt in the same app?
Espen Christensen
http://docs.djangoproject.com/en/dev/ref/models/fields/#lazy-relationships says that it is possible to use lazy relationships cross-appwise so i'll try that out.
Espen Christensen
@Espen Christensen: You must break the circularity somehow. You cannot have a many-to-many in *both* places, It must be in only one place. Pick one. I updated the question to explain why I picked the one I picked. You can pick Task instead of Event, but you must pick exactly one and only one. You cannot have a many-to-many relationship in both places.
S.Lott