I know Django applications are typically named django-appname, however, our non-django packages are released under a namespace for our company (eg. company.modulename). Our Django applications are currently structured in a "django" namespace within that namespace (eg. company.django.appname).
We are evaluating our structure before releasing Django apps. Regardless of the internal path structure, which do you think would be a better project name convention for Django apps and why?
"django-company-appname" <-- more like community naming
"company.django.appname" <-- matches the internal structure and non-django python packages we release.
Edit:
Let me make this a little more clear. We already are using namespaces--our django apps are imported using "company.django.appname". What we are trying to decide, is if the name we use to release that app, as defined in setup.py and listed in PyPI/Github will be "company.django.appname" like our other Python releases or if we should do "django-company-app" instead.
We use a company.modulename style namespace for a few django apps and have encountered no problems.
In the __init__.py files we declare the namespace.
import pkg_resources
pkg_resources.declare_namespace(__name__)
and it's worked fine so far.
Forcing absolute imports will remove any chance of issues due to reuse of package names.
Related
In the django culture, I have encountered the concept of app reuse but not snippet reuse. Here is an example of what I mean by snippet reuse: I have a function getDateTimeObjFromString( sDateTime ), obviously you pass a string date time and it returns a python date-time object.
Back in the late 1980's or early 1990's, I was exposed to the idea of snippet reuse at a FoxPro developers conference. If you write code for a specific problem and find it is useful elsewhere in your project, move it to a project library. If you find that code is useful for other projects, move it to a generic library that can be accessed by all projects.
(At the FoxPro DevCon, they did not call it snippet reuse. I coined that term to make clear that I am referring to reuse of chunks of code smaller than an entire app. The FoxPro DevCon was long ago, I do not remember exactly what they called it.)
I read the most recent "Two Scoops of Django", and it does mention reusing snippets within a single project but I did not find any mention of the concept of snippet reuse across multiple projects.
I wrote and used getDateTimeObjFromString() long before I tackled my django app. It is in packages I keep under /home/Common/pyPacks. On my computers, I set PYTHONPATH=/home/Common/pyPacks, so every project can access the code there. The code for getDateTimeObjFromString() is under a Time subdirectory in a file named Convert.py. So to use the code in any project:
from Time.Convert import getDateTimeObjFromString
My django app downloads data from an API, and that data includes timestamps. It would be nice if the API sent python date time objects, but what you get are strings. Hence the utility of getDateTimeObjFromString().
This is just one example, there are many little functions under /home/Common/pyPacks that I found convenient to access in my django project.
Yes /home/Common/pyPacks are under version control in github and yes I deploy on any particular machine via git pull.
When working on my django project from a development computer, PYTHONPATH works, and I can import the packages. But then I tried running my django app on a server via wsgi.py -- PYTHONPATH is disabled. I can set PYTHONPATH both at the OS and Apache2 level, but python ignores it, the functions cannot import.
I do not want to bother with making my personal generic library an official python package under PyPI.
Does the django community expect me to copy and paste?
I arrived at a work around: make /home/Common/pyPacks a psudeo site-package by putting a "pyPks" symlink in the virtual environment's site-packages directory to /home/Common/pyPacks, adding "pyPks" to the INSTALLED_APPS, then changing all the import statements as follows:
original:
from Time.Convert import getDateTimeObjFromString
work around update:
from pyPks.Time.Convert import getDateTimeObjFromString
I also had to update all my generic library files to handle both absolute imports via PYTHONPATH and relative imports.
How to fix “Attempted relative import in non-package” even with init.py
Is there a better way to reuse snippets in a django project?
In Djano, why should I add third-party package names inside the INSTALLED_APPS for some packages such as django-filter, DRF, debug-toolbar etc, while I don't want to add for some packages such as Celery, Requests etc ?
I couldn't figure out why should add them to a specific list, even though they all are similar pip packages and I installed them in the same way. Thanks in advance!
From docs :
Package? App?
A Python package provides a way of grouping related Python code for
easy reuse. A package contains one or more files of Python code (also
known as “modules”).
A package can be imported with import foo.bar or from foo import bar.
For a directory (like polls) to form a package, it must contain a
special file init.py, even if this file is empty.
A Django application is just a Python package that is specifically
intended for use in a Django project. An application may use common
Django conventions, such as having models, tests, urls, and views
submodules.
From above statements we understand that every well-written python code could be a package, now if this package is a bunch of python code in a directory, installing it would mean just copy the directory in your project and import them wherever needed in code.
But now there is this package which was already a django app and maybe used some special advantages of being one. Like exposing a restful API or delivering some sort of static resources or even working with special django-specific classes. these kind's of operation's need your direct permission in settings.py so that your project will know how to deal with this package. or even they may require to include their url path's to your project so that people visiting your site could access them.
I assume all this manual job is an act of security.
You need to add apps with models(non-abstract), templates, templatetags or management commands so that django-admin finds and loads them
I want to make use of Django's modularity and integrate some external apps that I installed using pip. However, I am encountering difficulties in understanding how can I integrate and use or extend their urls, views, models. There isn't much on this subject, I can't figure why.
Let's take the example of changuito-cart:
Do i create a folder named "changuito" in root and create urls/views in here, or should I just create a new app named like it?
In settings.py I added "changuito" to my installed apps list and I got "no module named 'changuito'" error. How do I add it correctly?
What are the basic steps required to integrate it?
After pip installing the app and adding it to your INSTALLED_APPS you should be good to go. There are cases where the name you need to add to your INSTALLED_APPS is different from the package name. Such cases should be apparent from the documentation, otherwise you need to look at the module structure itself. In your case the package is called "django-changuito" and you have to include "changuito" in your INSTALLED_APPS. Be also aware that this particular package depends on MIDDLEWARE_CLASSES settings. Please read the documentation!
Make also sure that the correct virtual environment is activated while installing if you use one.
In general you would not modify the external app itself. This would be quite dangerous since it will start to differ from the upstream and break down the road. If you want to subclass or extend classes of the external app you need to import these classes into your own app before extending or monkey patching. In this case you will create a different class in a different, your app.
Finally, some apps allow for extending templates. Django will search for templates and statics in your project structure first. If you recreate the folder structure of an external app and put new templates in the exact right place. Django will use those.
Why aren't they simply directories? Any good advice says to keep as much as possible in the apps and not to couple them to the project. The very ability to import an app as project.application discourages this. Why does django-admin.py create the __init__.py at all? The project is perfectly useful without it. What is the justification?
We have a single project that we "subclass" of sorts for other projects. So we have other projects that import stuff from the main project. I guess for us it provides the common namespace that contains all the other apps.
We could move to a package with all our apps in it separate from the projects i guess. Our system has grown rather than been planned.
So I guess my answer is, it provides a good root namespace. (for our needs) :)
The core of a project is a settings.py and a root urls.py. Both of those are Python modules, thus they need to be importable somehow. You can put the project directory directly on the Python path and thus make them importable as top-level modules, but that's arguably even worse practice. Better to have the project be a package and the settings and urls be modules within it.
There isn't a requirement that apps be inside the project's namespace, to my knowledge. Just that they be on the $PYTHONPATH. As such, they are usable by any other code on the system which shares the same PYTHONPATH.
I think the idea is that you can reuse the applications but you don't need to move them from the project where they were initially created. If the project weren't a package you would need to copy/move the application you want to reuse to a python package. Because of that being the project itself a proper python package you can reuse the applications in it without moving the applications to other place.
I have a python/django application that runs on the google app engine.
My views.py file has some imports...
from commands.userCommands import RegisterUserCommand
from commands.accountCommands import CreateNewAccountCommand, RenameAccountCommand
These imports work fine on my development environment (local machine). But when I upload to the google app engine, views.py fails with a "Could not import views. Error was: No module named userCommands" error.
Any idea why I can't import my commands.userCommands module?
My file structure looks as follows...
- app.yaml
- urls.py
- views.py
- etc...
- commands/__init__.py
- commands/userCommands.py
Note: I did try to append my application name to the module name/path. No luck.
Note: I did do an update with the --noisy argument, and it does appear to upload my commands folder successfully.
You could be running into a clash with Python's own commands module (which doesn't have submodules like yours) -- naming your own modules and packages in ways that are meant to hide ones in the standard library (just like naming your variables in ways that are meant to hide builtin names, like list or file) is always a perilous undertaking, even though it "should" work there's always potential for confusion.
Could you try renaming that commands package and its uses to something unambiguous and free from danger, such as mycommands, and see if that just makes the problem disappear? If that's the case you can then open a ticket on GAE's tracker (because it would show a minor but undeniable bug in GAE's runtime) but meanwhile your problem is solved!-) If the problem stays, ah well, at least we've eliminated one likely cause and can keep digging...
The __init__.py files are required to make Python treat the directories as containing packages, so you need a
commands/__init__.py
file in your directory structure. See http://docs.python.org/tutorial/modules.html.