Code

Opened 8 years ago

Closed 7 years ago

#2289 closed defect (wontfix)

sqlall etc. don't work on models within a package

Reported by: adurdin@… Owned by: adrian
Component: Database layer (models, ORM) Version:
Severity: normal Keywords:
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: UI/UX:

Description

I was trying to split my models.py out into separate modules to prevent it becoming too monolithic, so I created a models package. I moved some of the classes into models/init.py, and the other I split off into several other modules in the models package.

Now when trying to update the database for the new models I've created, I found that manage.py sql <appname> only outputs sql for the classes in models/init.py, and not for any of the other modules.

Attachments (0)

Change History (8)

comment:1 Changed 8 years ago by ubernostrum

This may be a silly question, but does your __init__.py specify which files are part of the module?

comment:2 Changed 8 years ago by adurdin@…

Should it be necessary to have all the classes in the package namespace? I don't believe so. Half the reason for trying to create separate modules was so I'd have separate namespaces to group related models.

But to answer your question: before posting the ticket, I'd tried both:

# other models get missed
models/init.py # core models
models/other.py # other models

and

# all models get missed
models/init.py # contains 'from app.models.core import A, B' and 'from app.models.other import C, D'
models/core.py # core models
models/other.py # other models

With the latter, manage.py sqlall didn't output sql for any models.

comment:3 Changed 8 years ago by adurdin@…

Sorry, tried to use the wrong markup for code blocks (too-many-wiki-syntaxes syndrome). Those should have been:

# other models get missed
models/__init__.py  # core models
models/other.py     # other models

and

# all models get missed
models/__init__.py  # contains 'from app.models.core import A, B' and 'from app.models.other import C, D'
models/core.py      # other models
models/other.py     # other models

comment:4 Changed 8 years ago by mtredinnick

  • Resolution set to duplicate
  • Status changed from new to closed

This is kind of a wart, but it is possible to work around: put an app_label attribute on the inner Meta class in each of your models. The value of this attribute should be the dotted Python path to the application directory. So if your directory structure looks like

project/
   application/
      models/
         __init__.py
         mymodels1.py
         mymodels2.py
         ...

Then app_label on each model would be 'project.application'.

Fixing this in a better way is the topic of #1821.

comment:5 Changed 8 years ago by adurdin@…

  • Resolution duplicate deleted
  • Status changed from closed to reopened

That workaround is no good for several reasons, the most obvious being that it doesn't work at all; manage.py still fails to see the other models--although the models are imported into models/__init__.py, and each models has class Meta: app_label='myproject.myapp' (the names I'm using in an isolated test project).

But more importantly, the workaround isn't suitable because:

  • The application I'm developing is intended to be used in several different projects, so it must be independent of the project name
  • Even if it did work, it still requires all the models to be in a flat namespace, which is not desirable.

I can't see the connection between this problem and #1821 -- can you enlighten me?

comment:6 Changed 8 years ago by mtredinnick

The connection with #1821 is that it provides a way to specify once what the application label is. That is the hard bit here: we need to know the app name in a number of places.

comment:7 Changed 8 years ago by adurdin@…

After poring over db/models/loading.py and db/models/base.py, I finally found that app_label should have been myapp, not myproject.myapp; then it works as advertised.

It's not a perfect solution, but it's close enough for me right now. Cheers!

comment:8 Changed 7 years ago by adurdin@…

  • Resolution set to wontfix
  • Status changed from reopened to closed

Using app_label on each model is a workable solution. There's not enough of a problem here to be worth chasing up.

Add Comment

Modify Ticket

Change Properties
<Author field>
Action
as closed
as The resolution will be set. Next status will be 'closed'
The resolution will be deleted. Next status will be 'new'
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.