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.
Related
Since I am a beginner in Django and Python world and I am currently trying to make a real project in it Django but being a java programmer by heart and I generally believe in breaking down application in parts as small as possible.
So I was trying to move /models.py file to /models/myModels.py, but when I try to do the migrations it was an unsuccessful attempt, so I want to ask whether we could relocate and break default models.py, views.py(like we could break tests files and also put them in specific packages following the naming conventions) or we have to accommodate all code in a single file. Although I firmly believe that we could do this but right now I am unable to find any way to do this.
Any help is greatly appreciated.
The trick here is that you cannot directly replace:
models.py
class ModelOne(...):
...
class ModelTwo(...):
...
with:
/models
model_one.py
class ModelOne(...):
...
model_two.py
class ModelTwo(...):
...
as now from models import ModelOne will fail, Python doesn't know how to find ModelOne within the directory. One fix is to change the imports, to e.g.
from models.model_one import ModelOne
but this may mean lots of changes throughout your app; it's much easier to use an __init__.py to determine what should be importable from models, making the directory a package that appears to Python to be identical to the single file you had before:
/models
__init__.py
from model_one import ModelOne
from model_two import ModelTwo
model_one.py
class ModelOne(...):
...
model_two.py
class ModelTwo(...):
...
See e.g. https://docs.python.org/2/tutorial/modules.html#packages for more information.
I have developed a backend library, say, cool_project. Now I want to build a web interface for it. So I create a Django project. Of course, I want to name it cool_project: my mother told me that Hungarian notation is bad and that the name cool_project is much better than any of cool_project_web etc.
But now I have a collision. As long as I try importing cool_project (the backend one) from django/cool_project/views.py (the views.py of the main Django app) a frontend package is being imported.
Is there any way to import backend project in this case? I tried to add full path to backend package (sys.path.insert(0, "/home/.../...")) but it didn't help.
Or maybe there is some well-known naming convention which helps avoiding such collisions?
You can use relative imports likefrom .. import cool_project as long you modules are in a package. I would suggest you to rename your app to something else though. It would create unnecessary complexity
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.
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.
I'd like to move my models to a separate directory, similar to the way it's done with Rails to cut down on code clutter. Is there any way to do this easily?
Thanks,
Collin
I assume you're using the basic webkit and not Django or something fancy. In that case just create a subdirectory called models. Put any python files you use for your models in here. Create also one blank file in this folder called __init__.py.
Then in your main.py or "controller" or what have you, put:
import models
at the top.
You just created a python package.
Brandon's answer is what I do. Furthermore, I rather like Rails's custom of one model per file. I don't stick to it completely but that is my basic pattern, especially since Python tends to encourage more-but-simpler lines of code than Ruby.
So what I do is I make models a package too:
models/
models/__init__.py
models/user.py
models/item.py
models/blog_post.py
In the main .py files I put my basic class definition, plus perhaps some helper functions (Python's module system makes it much safer to keep quickie helper functions coupled to the class definition). And my __init__.py stitches them all together:
"""The application models"""
from user import User
from item import Item
from blog_post import BlogPost
It's slightly redundant but I have lots of control of the namespace.