Nikolai Prokoschenko
Nikolai Prokoschenko

Reputation: 8755

How can I import a specific module with an ambiguous name?

This happens in Django context, but the question is not Django specific.

I'm trying to split my big urls.py into smaller and more manageable chunks (app includes, third-party modules, search, admin, development and so on). So instead of urls.py, I'm using urls/ directory now, with urls/__init__.py containing code like this:

import admin
urlpatterns += admin.urlpatterns

Now I've got into trouble with third-party modules. For example, I'm overriding a bunch of URLs and views for django-messages, and so I've put all of it into urls/messages.py. It turns out, I can't import django-messages' views then, since

from messages.views import inbox

inside urls/messages.py tries to import from local directory first, finds a messages module, but can't import messages.views then, since urls/messages/views.py is obviously absent. I wouldn't like having to rename my modules to something like urls.messages_urls, but I haven't found a way to explicitely tell Python to import the "other" messages.views. Neither would I like to specify my imported views via strings, even though I can do that in Django.

How can I solve this situation cleanly?

Upvotes: 1

Views: 1059

Answers (3)

Steve K
Steve K

Reputation: 11369

For those who could not find it, I was hitting ambiguous import errors. For example, in a django project, let's say I have this tree :

  • tax module
    • models module
      • init.py
      • tax.py
      • foo.py

In init.py, I want to import tax.models.tax.Tax. So I write :

from tax.models.tax import Tax

But python does not find the correct import (it looks for models inside tax.models) and throws

ImportError: No module named models

You have indeed understood that it's all about relative imports. python first looks in the current module. If the first part of your import exists in the current module, it fails. This behaviour has been fixed in Python 2.5 (and may have become default in Python 3.0), you just have to add :

from __future__ import absolute_import

before your absolute imports. Have a look at Python 2.5 introduces absolute imports for more thorough information.

Upvotes: 2

Daniel Roseman
Daniel Roseman

Reputation: 599450

This is the wrong way to do it.

Django has a method for splitting urls.py into separate files, and that is to use include(). Keep the urls for each application in its own urls.py, and include them into the main one.

Upvotes: 2

kungphu
kungphu

Reputation: 4849

Have you tried:

from django.contrib.messages.views import inbox

Untested, but I'd think the full import would work as expected.

Upvotes: 1

Related Questions