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

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?

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.

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.

Have you tried:
from django.contrib.messages.views import inbox
Untested, but I'd think the full import would work as expected.

Related

Cannot find django.views.generic . Where is generic. Looked in all folders for the file

I know this is a strange question but I am lost on what to do. i cloned pinry... It is working and up . I am trying to find django.views.generic. I have searched the directory in my text editor, I have looked in django.views. But I cannot see generic (only a folder with the name "generic"). I cant understand where the generic file is . It is used in many imports and to extend classes but I cannot find the file to see the import functions. I have a good understanding of files and imports and i would say at this stage I am just above noob level. So is there something I am missing here. How come i cannot find this file? If i go to from django.core.urlresolvers import reverse, I can easly find this but not
eg : from django.views.generic import CreateView
Where is generic?
Try running this from a Python interpreter:
>>> import django.views.generic
>>> django.views.generic.__file__
This will show you the location of the gerneric as a string path. In my case the output is:
'/.../python3.5/site-packages/django/views/generic/__init__.py'
If you look at this __init__.py you will not see the code for any of the generic *View classes. However, these classes can still be imported from the path django.views.generic (if I am not mistaken, this is because the *View classes are part of the __all__ list in django/views/generic/__init__.py). In the case of CreateView, it is actually in django/views/generic/edit.py, although it can be imported from django.views.generic, because of the way the __init__.py is set up.
This is technique is generally useful when you want to find the path to a .py file. Also useful: if you use it on its own in a script (print(__file__)), it will give you the path to the script itself.

Python package naming issue

I have a python package named gutils, which contains a lot of useful tools for development, some of them are generic, some of them use reportlabs and the most important part forms a layer of abstraction on top of django, customizing a lot of default behaviour
I would like to keep the convention of the exterior interface similar to django's, as to not add complexity to the development proccess..
I have this structure (as an example):
gutils
|---- django
|
|----forms
|
|---widgets.py
The problem is, inside this widgets.py file, the imports resolve to the current subpackage.
For example:
from django.forms import TextInput
Is treated as if it were:
from gutils.django.forms import TextInput
As a workaround, I've named the top-level package gdjango, but it looks awkward.
So, the question is:
Is there a way to reference the real django package from within the gutils.django package?
NOTE: I'm using python 3
If you're dealing with a package, for example, like this:
mypackage /
mypackagesubdir /
myfile.py
mypackagesubdirII /
myfileII.py
and you're editting myfile.py, import myfileII like import .mypackagessubdirII.myfileII. . means the root of the package.

Search path for Pyramid modules

I have a Pyramid app, I split models AND views into separate files in following manner:
How do I split models.py into different files for different models in Pyramid?
One small consequence for views is that since I have them in separate view files in a "views" package is that they cannot find models.py, now models package, since it resides in parent directory.
That is, it used to be:
models.py
views.py
Now it's:
views/__init__.py
views/view1.py
views/view2.py
models/__init__.py
models/model1.py
models/model2.py
Therefore, importing from models in a view results in:
from models import (
ImportError: No module named models
Now, I can work around this by adding following path search module extension in views/__init__.py:
sys.path.append(os.path.dirname(os.path.dirname(__file__)))
But that's kind of kludgy. Is there a better, maybe Pyramid-specific solution?
This is not really pyramid specific, it is just python.
See https://docs.python.org/2/tutorial/modules.html#packages
for a detailed explanation.
You want to
import models.model1
Or
from models.model2 import (...)
I'm late, but it can help some other person.
For solve this, you need to specify your project name. In your case, if the project name is projet_name import your models like this.
from project_name.models.model1 import *
or
import project_name.models.model1
I suppose is not the best way, but it work fine for me.

How do I avoid naming clashes within Python's module system?

In my Django project I have an app called profile, which mostly contains my profile.models.UserProfile class for additional information on User objects (may seem familiar to Django folks). Now I've put some initialization code into profile/__init__.py (some signals) and have ran into a problem: Django tells me that a table called hotshot_profile has not been found.
After literally hours of searching, I traced the problem back to importing order. Running python -v manage.py test I've found the following:
import nose.plugins.prof # precompiled from /home/rassie/.virtualenvs/myproject/lib/python2.6/site-packages/nose/plugins/prof.pyc
import hotshot # directory /usr/lib64/python2.6/hotshot
import hotshot # precompiled from /usr/lib64/python2.6/hotshot/__init__.pyc
dlopen("/home/rassie/.virtualenvs/myproject/lib64/python2.6/lib-dynload/_hotshot.so", 2);
import _hotshot # dynamically loaded from /home/rassie/.virtualenvs/myproject/lib64/python2.6/lib-dynload/_hotshot.so
import hotshot.stats # from /usr/lib64/python2.6/hotshot/stats.py
import profile # directory /home/rassie/MyProject/apps/profile
import profile # precompiled from /home/rassie/MyProject/apps/profile/__init__.pyc
So my Nose runner imports the nose.plugins.prof (even though this plugin is off), imports hotshot, which tries to import profile. However, profile gets imported from my project, while it ready should have been imported from system Python.
Obviously, my own profile module clashes with system profile module. I obviously can't exclude every module name that comes bundled with Python from my own programming. So the question is, where do I go from here? Do I have to create a myproject namespace for all of my apps? Will Django work with that?
PS: Table's name hotshot_profile seems to come from a further yet-to-be-fully-analyzed naming clash with a Profile class from pybb, which I'm also using in my project. But that's out of this question's scope.
You should never import your own modules in the form import mymodule (relative imports). Instead you should always use import myproject.mymodule instead (absolute imports). This avoids all name clashes.

Django: standard location/conventions for data import scripts?

I'm working on a number of Django projects, and in most of them, I have initial data to import.
This data isn't neat JSON, as shown in the fixture examples in the Django docs - it tends to be messy Excel or CSV files. The scripts tend to look like the following snippet, and I just run them as standalone Python, because I don't know any better:
import sys
from django.core.management import setup_environ
sys.path.append(LOCATION OF YOUR DJANGO PROJECTS, EX: 'C:\django')
from mysite import settings
setup_environ(settings)
from PROJECT_NAME.APP_NAME.models import MODEL_NAME
import csv
reader = csv.reader(open(COMPLETE PATH TO YOUR DATA, EX: "C:/django/mysite/restaurants.csv"), dialect='excel')
for row in reader:
COLUMN_ONE_TITLE = row[0]
COLUMN_TWO_TITLE = row[1]
MODEL_NAME.objects.get_or_create(MY_FIRST_COLUMN=COLUMN_ONE_TITLE, MY_SECOND_COLUMN=COLUMN_TWO_TITLE)
I feel that when I commit these projects to GitHub or send them to the client or whatever, I should include the import scripts. They're an important part of the project.
Is there a standard way, in Django, to store the import scripts that I've written to import this data?
Where in the project should they sit? Should I be using management commands?
Thanks!
I like putting them in management commands - that way when someone else works on the project, the commands are where they're expected to be by someone who wasn't familiar with the choices being made during initial development.
Django supports pluggable serialization modules. If you can arrange your CSV formats to work as a deserializer, you can use the regular loaddata command.
What if you put all that code in a utility function? so your views.py would have from utils import csv_import or something like that. That way your views can programmatically use that functionality.
I would first suggest what Martin or Luke suggested.
But if that won't work for you for some reason, then putting the script right in the root of the git project makes sense. Note, I did not suggest putting it in the root of the django project (though, frankly, that isn't a wrong idea either), but I'm suggesting that the django project be a sub folder of the git repo for the very reason that you can put these helper files somewhere that's not clogging up the django project.

Categories

Resources