I've just started working on a codebase that the team I've joined is updating from using Django 1.4 to Django 1.8. Along with that change, it's being restructured into separate apps, and the layout is being changed in various ways.
INSTALLED_APPS has some apps, let's call them foo and bar, but their models.py files have been put into db subdirectories, that is foo/db/models.py.
Those models can be accessed from code (for example views) with from foo.db.models import SomeModel, and that seems to work.
However, from my reading of https://docs.djangoproject.com/en/1.8/ref/applications/#initialization-process, particularly stage 2, models defined in foo/db/models.py rather than foo/models.py won't be found during application loading, which will cause a variety of issues.
Is it possible to support this non-standard location of models.py with a custom AppConfig, or in some other way?
To clarify, I think trying to have models.py in a non-standard location is a bad idea; I'm after confirmation to help make my argument to the rest of the team.
The models submodule name is hardcoded, and it's the only module that is imported by Django during that step of the initialization process.
However, you can easily import your models inside your models.py file to ensure your models are imported at the correct time. If all your app's models are defined or imported in foo.db.models, you can simply use this:
# foo/models.py
from foo.db.models import *
I read the documents, but could not understand how removing the need of models.py will improve the system.
The benefits are listed in bullet form here. You can see that not requiring models.py is just one of stated benefits of the new approach.
Applications can run code at startup, before Django does anything else, with the ready() method of their configuration.
Application labels are assigned correctly to models even when they’re defined outside of models.py. You don’t have to set app_label explicitly any more.
It is possible to omit models.py entirely if an application doesn’t have any models.
Applications can be relabeled with the label attribute of application configurations, to work around label conflicts.
The name of applications can be customized in the admin with the verbose_name of application configurations.
The admin automatically calls autodiscover() when Django starts. You can consequently remove this line from your URLconf.
Django imports all application configurations and models as soon as it starts, through a deterministic and straightforward process. This should make it easier to diagnose import issues such as import loops.
In addition, various bugs having to do with app loading were fixed under the rubric of app-loading refactor. For example, it used to be that some parts of the system looked at the INSTALLED_APPS from front-to-back and others back-to-front. Now the order is consistent throughout the system.
As for models.py, it doesn't make sense to use that to mark applications when it's not necessary to have models to be an application (for example, a reusable app can just have templates, say, or management commands). You used to have to include an empty models.py file; now you can leave it out entirely.
What really is the true meaning of django project and individual apps in it?
I mean - AFAIK you cannot create a project and live entirely in that project you created, you have to create an app in that project to be able to actually do something in django. Please correct me if I'm wrong.
Now what should really be the structure of a django project? I'm writing an e-shop. Let's say my project is named foo:
/foo
/foo
/settings.py
/templates
/urls.py
/wsgi.py
/shop
/__init__.py
/admin.py
/models.py
/tests.py
/views.py
and do everything entirely in /foo/shop/, but I edit urls.py inside /foo/foo/ etc.
I was following the Django Book, but I've begun to gain that strange feeling that /foo/foo/ is just for a main folder "stitching the thing together" but individual stuff should be done only in /foo/shop/, but not limited to. Preferably in /foo/web/, /foo/products/, /foo/forum/, /foo/controlpanel/, /foo/shop/, /foo/helpdesk/, /foo/backoffice/ etc.
Is that correct? Should I put everything products-related in /foo/products/, that including storage management, shipping, dealers, prices etc., then put management of those products (from the employee side) to /foo/backoffice/, which will serve as some sort of "django.contrib.admin" for this? Is that correct? Then if I want to host multiple instances of this (with completely separate databases and stuff) for multiple customers, should i only create a barebone project, that will put these things together, to configure the settings and then just move individual components in some sort of central repository and call them back in the project via INSTALLED_APPS? Because that would be cool as hell! I mean - making all the changes globally, not touching users data and configuration, unless necessary (adding columns in models and such). Is this how django is really supposed to be used? Or am I completely off the track and do things ENTIRELY wrong and this paragraph just doesn't make any django-sense?
I'm relatively new to this. I've been using PHP before and even though Django was a pain-in-the-ass to get basic grip of, I don't regret that and plan to deprecate and make offline any PHP project I created to date and replace them all with django. Well - where it makes sense and is not a single-purpose site. Not only because Django is awesome and versatile, but i cas I can scale it easily as well…
So… How should I really design Django projects, apps, and how to use them in production, providing them to multiple customers?
Thank you!
I mean - AFAIK you cannot create a project and live entirely in that project you created, you have to create an app in that project to be able to actually do something in django. Please correct me if I'm wrong.
You can do plenty of things on just a project, but you need an app for models to be auto discovered.
For example, I have a project with just this in urls.py:
class Homepage(generic.TemplateView):
template_name = 'homepage.html'
def get_context_data(self):
context = cache.get('homepage')
if not context:
management.call_command('reset_cache')
context = cache.get('homepage')
return context
urlpatterns = patterns("",
url(r"^$", Homepage.as_view(), name="home"),
)
You guessed it, it's a really basic website.
and do everything entirely in /foo/shop/, but I edit urls.py inside /foo/foo/ etc.
I was following the Django Book, but I've begun to gain that strange
feeling that /foo/foo/ is just for a main folder "stitching the thing
together" but individual stuff should be done only in /foo/shop/, but
not limited to. Preferably in /foo/web/, /foo/products/, /foo/forum/,
/foo/controlpanel/, /foo/shop/, /foo/helpdesk/, /foo/backoffice/ etc.
Well, you should define /foo/shop/urls.py, and import it from /foo/foo/urls.py ie.:
urlpatterns = patterns("",
url(r"^shop/", include("shop.urls")),
)
The point is to make your apps more convenient to reuse in other django projects.
Is that correct? Should I put everything products-related in
/foo/products/, that including storage management, shipping, dealers,
prices etc., then put management of those products (from the employee
side) to /foo/backoffice/, which will serve as some sort of
"django.contrib.admin" for this? Is that correct?
You should take a look at open source projects and see how they divided that.
According to the directory tree that you represented, you seem to have understood the point, but your statement seems fuzzy so I'll attempt to clarify it.
Apps are generally oriented around models. So if I make a product app it will probably contain:
Product model,
Product list, edit, create, delete and detail view
urls for the views,
Product admin,
tests for Product and views,
other things which are used by other django apps like product/admin.py would be used by django.contrib.admin, but also external apps like django-autocomplete-light would use product/autcomplete_light_registry.py and django-rules-light would use product/rules_light_registry
Then if I want to host multiple instances of this (with completely
separate databases and stuff) for multiple customers, should i only
create a barebone project, that will put these things together, to
configure the settings and then just move individual components in
some sort of central repository and call them back in the project via
INSTALLED_APPS?
There are many ways to do SaaS with django. But I agree that the easiest and most convenient is to maintain generic apps and build a project per customer that reuses (and eventually override parts of) these apps.
I am writing an app in Django which has a few sitewide fixed objects I need to instantiate which, for one reason or another, can't be fixtures.
For example, some (e.g. Permissions) I can't hardcode a PK for because I can't be sure that they'll be loaded in a certain order (and if I use pk=null then I get an IntegrityError if they exist already.)
Others (e.g. Sites) depend on values in settings.py. Edit: These need to run each time the project is deployed, otherwise I could use South's data migrations as per super9's suggestion below.
Since these are Django models, they're not directly related to any of the apps in my project. It would make the most sense to load them in settings.py but that results in a circular import. It works in urls.py but putting the loading code there seems hackish and out-of-place.
I looked into hooking a receiver into post_syncdb as follows:
#receiver(post_syncdb)
def create_groups_and_permissions(sender, **kwargs):
print "Creating groups and permissions"
u_ct = ContentType.objects.get(model="user")
Group.objects.get_or_create(name='Group 1')
Permission.objects.get_or_create(name="Perm 1", codename="perm_1", content_type=u_ct)
However, since I'm using South, per the documentation it only sends post_syncdb when the table is first created. I could call syncdb manually after each time I migrate but would prefer not to.
I am nearly resolved to put them in urls.py or the most closely related app's models.py but thought I'd check here to see if there's an accepted way of loading fixed objects which can't be loaded as fixtures.
Have you checked out data migrations in south yet? http://south.aeracode.org/docs/tutorial/part3.html
Sounds like it might be what you need.
Where would I put project based views that I've created for my django project?
For example - things like JSONResponseMixin?
I'd like to put them into a folder like my_project/views/generic/ajax.py - but I'm not sure how I would then call this within apps in my project?
Something like from my_project.views.generic.ajax import JSONResponseMixin doesn't work because it says there is no app "views"...
In django it is probaby best to follow the django way so a project is divided into apps, apps contain there modules (models, views, urls ...), you can however create your own local/utility/contrib app, it can just be a folder with an init.py and your modules. If you want to partition it further into directories (each sub directory I believe would need it's own init.py), you would have to then include it (the apps root folder) in your INSTALLED_APPS tuple and from there should be able to (afaik) import the module as you would have done for anything else.
Edit: Just found this answer to a somewhat related question, probably worth a read