How to do a project-wide custom django-admin command? - django

In Django, it's easy to write custom management commands for django-admin.py/manager.py.
However, these commands reside at the application level, not the overall project level. You put implementations into the <project_dir>/<app_dir>/management/commands directory, and they get auto-discovered.
I have a number of commands which are project-level, not tied to any one application in the project. I can tuck them in one of the apps, but is there a way to implement project-level management commands in Django?

You can have application called core or similar, where things not tied to any application are contained. These can be management commands, temlatetags, models and maybe other modules like forms, decorators, middleware. You could use your project directory itself as "core" application.
Here is how I tend to structure my projects:
project_name
not_reusable_app1
not_reusable_app2
templatetages
tempates
utils
models.py
settings.py
management
middleware.py
forms.py
processors.py
__init__.py
parts
reusable-app-1
reusable_app_1
setup.py
reusable-app-2
reurable-app-3
gereric-python-lib
django
setup.py
My INSTALLED_APPS usually looks like this:
INSTALLED_APPS = (
...
'project_name',
'project_name.not_reusable_app1',
'reusable_app1',
...
)
I do not give any special treatment to django applications compred with other python packages. For example I don't put them under apps or similar directory.
It is clear that my not-reusable apps are part of project. Not reusable apps under project usually use various utilities from project, for example project_name.utils.decorators.some_kind_of_deco.
If you do not like to use project as application, like I mentioned you can move everything to project_name.core.

Related

Why django-admin startproject creates nested project folders?

django-admin startproject mysite creates something like this:
/mysite
/mysite
settings.py
....
I know if I add a period at the end of command (django-admin startproject mysite .) the second folder will not be created, but I don't understand what is the rationale behind creating nested project folders. Maybe I'm missing something critical?
A project is a collection of one or more apps. When you create a project by default, a default app of the same name is made within a folder of the same name. Thus you end up with a nested folder structure like /myproject/myproject.
I suppose why it doesn't dump all the default/root app files in the root of the project folder is because that would make it a bit more complex to manage multiple apps. The default app is structurally the same as other apps. Django relies on certain conventions, including special filenames and certain folder structure, to tell what's what.
In a structure like this:
myproject
/myproject
/myapp
/anotherapp
You can refer to myapp from within myproject, and Django can locate myproject very cheaply due to these folder conventions (and likewise the other way around).
You can tell which app is the default app by examining manage.py, which will have a line like this within def main()
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings')
The command django-admin startproject mysite creates a project. Django
defines a project as a container for one or more apps. The command creates a project and an app.
If am correct you are attempting to create an app inside another app.
One may decide to nest an app due to various reasons such as close association or dependencies of apps
Eg.
a website may have a public site and an administrator site. The public site(app)
may have public account user(another app) implemented as a user model.
The administrator site may have private account user.
Therefore one may seek to contain public user model inside the public site
and the same for private user account.
Fix
The command django-admin startproject mysite . is the wrong command to use. You don't nest projects, you nest apps.
To create an app use python manage.py startapp mysite, then cd into the app
then use python manage.py startapp nestedsite to nest it.
See [https://stackoverflow.com/q/2862084/6753642][1]

Installing Pinax, where is my deployment folder?

I'm trying to set up Pinax and I'm new to everything involved (Django, Pinax, webservers, etc). I'm following http://pinax.readthedocs.org/en/latest/gettingstarted.html
When I generate a project using:
(mysite-env)$ pinax-admin setup_project -b basic mysite
The directory structure I get is:
apps __init__.py manage.py settings.pyc urls.py
dev.db __init__.pyc requirements static urls.pyc
fixtures locale settings.py templates wsgi.py
Which as far as I can tell is missing the deployment folder (when you compare to the directory structure shown here : http://pinax.readthedocs.org/en/latest/starterprojects.html). It doesn't seem to be effecting anything yet, but it makes me nervous. What is going on and is the fact I'm missing the deployment folder going to cause problems in the future?
I'm running Ubuntu and using python 2.7. I had the same behaviour with Windows 7, python 2.6
Thanks!
The new Django versions have made the old pinax pretty much useless. Now Django supports project templates and Pinax is separated into several smaller projects regarding starter projects (such as pinax-project-account) and apps (such as django-user-account).
The current way to use pinax is to choose a starter project, and then running something like:
$ django-admin.py startproject --template=https://github.com/pinax/pinax-project-account/zipball/master <project_name>
and then install requirements:
$ pip install -r requirements.txt
This will create a new Django project using the starter-project as a template, which already includes a few apps (like django-user-account) and templates (with bootstrap!). The project is ready to run, and already includes a bunch of functionality (like user registration, login and management).
Also, Django has changed the project directory structure a bit, so now it doesn't really look like that anymore.

Separate Git repository for multiple Django sites

I am using Django as development framework for my current Project (say Project A).
I want to create a new application (say Project B) that has different views as Project A. But this new Project B is going to use most of the existing backend modules and models from current Project A.
Such that my Current Project (Project A) is hosted on URL http://www.site-one.com and and New Project B will be hosted on http://www.site-two.com. With respect to this, I have one doubt and a question that I want to ask:
Doubt: Is my choice of using "Django sites framework" for this is correct?
Question: Is there any way to keep two Django sites (A and B) in different Git Repo and still access the models and other modules from Current Site A?
I would suggest for shared functionality create separate django apps with a structure resembling something like the following. (I'm assuming you've got your projects in virtualenvs)
appname/
__init__.py
models.py
views.py
templates/
base.html
Store this app in a git repository of it's own.
then inside the requirements.txt for each of your projects this functionality is needed in add a line like the following, assuming you're using bitbucket:
-e git+https://yourusername#bitbucket.org/appname/appname.git#egg=appname
install
pip install -r requirements.txt
then in your settings.py add myappname to your INSTALLED_APPLICATIONS

How to test single application (not project) in Django?

I would like to test my small application, that I keep in a separate package. Right now I created a "test_project" directory, created a test project there and I am using the project's manage.py to run tests. But I keep wondering - is there a better method? Is it possible to launch a single app's tests, perhaps with some default configuration (like, sqlite database)?
It is possible to run a single app's tests standalone, without creating a Django test project for that purpose. One way of doing so is by creating a runtests.py in your app's root dir which setups Django settings and runs ./manage.py test your_app programmatically. One example of runtests.py is Django's own: runtests.py (documentation).
Django's own runtests.py is a good reference but I find it convoluted for most cases. Below are a couple of alternative examples:
Django-Modeltranslation
My own minimalistic one
Writing this down because I don't see it on here yet
From the docs
If your django structure looks something like this as it should:
Project dir/
/myapp
/myotherapp
/myproject
Django allows you to execute test from only "myotherapp" by executing:
./manage.py test myotherapp/
This will execute all test under "myotherapp" whereas
./manage.py test
will execute all test in your projects directory.
If you use nose you can run a single app's tests.
python manage.py test app.tests:TestClassHere
as for testing a single app. I just follow the convention other big django projects do, and that is exactly what you are doing. Create a test_project directory.
https://github.com/mozilla/django-piston/tree/master/tests/test_project
I figure if it is good enough for some of the biggest django pluggable apps it's good enough for me.
Ofcourse you can test the Python parts with a standalone unittest if you don't need any django dependencies
A Django environment requires atleast a settings.py and manage.py file. You can setup those with essential stuff only and UnitTest your app with manage.py. You should see a project as a Django runtime environment, there's no Django without it. You can probably mimic settings but tbh you would just be creating more hacks than simplicity.
You can also create a custom test runner and override the path it searches for tests in.
Perhaps I buried the lede here. I recently inherited a project that had legacy tests they wanted to keep for historical reasons, so I was forced to write all my tests in one folder and point to it
from django.test.runner import DiscoverRunner
class MyTestRunner(DiscoverRunner):
def __init__(self, *args, **kwargs):
kwargs.update({'top_level': str(settings.TEST_DISCOVER_TOP_LEVEL)})
super().__init__(*args, **kwargs)
def run_tests(self, test_labels, extra_tests=None, **kwargs):
# In order to override the top_level directory, the test_label must match the top_level
kwargs.update({'test_labels': [str(settings.TEST_DISCOVER_TOP_LEVEL)]})
return super().run_tests(extra_tests=extra_tests, **kwargs)
and in your settings
TEST_RUNNER = 'path.to.my.module.MyTestRunner'
TEST_DISCOVER_TOP_LEVEL = BASE_DIR / 'tests/unit_and_integration_tests'

Appropriate placement for my testcases belonging to a non-app in Django

I have built my website in Django. And like any other django project I have got apps inside the project root directory and some special folders like(extensions a.k.a custom django command extensions). With an app, we dont have any problem with having testcases. "tests.py" inside the app directory will be the solution. But for a special folder(which is not an app or which doesn't have a models.py) where do I place the testcases. I tried placing the tests.py inside the extensions directory and it said the directory is not a model and unable to run the tests. HOw do I solve this? How can I have a proper placement of testcases related to non-apps?
I think it will work to put them in a tests/ directory at the project level.
If, for some reason, it doesn't then try creating an empty models.py in your extensions directory.