django apps and models.py in 1.7 - what exactly has changed? - django

Django 1.7 has introduced some apparently major changes for how apps work
https://docs.djangoproject.com/en/dev/releases/1.7/#app-loading-refactor
These release notes seem to be saying that you can define models outside of models.py and we don't even need a models.py (or models/__init__.py) inside an app.
Am I misunderstanding this? If not, could someone explain where we define our models if they are not in models.py and how does django find and load them?

You should still define your models in models.py.
Before the app refactor in 1.7 there wasn't a unified API for declaring metadata about your app. In particular, the way Django determined whether something was an app or not was by looking for a models.py file. That was not an elegant system, especially when you consider that some apps don't even have models (for example, the app might just provide management commands).
Now that the AppConfig API exists it's no longer necessary to require the existence of a models.py. However, it's still the natural, and default, place to define your models.
How does django find and load them?
From the documentation: "You must define or import all models in your application’s models.py or models/__init__.py."
That suggests the following practice: if you don't have any models, don't include a models.py. If you have a file's worth of models, put them in models.py. If you have a bunch of models and want to spread them out over multiple files, put the files in a models submodule and import their contents in models/__init__.py.

Related

Does it matter if admin classes are located in models.py vs. admin.py?

I'm working through a (presumably) older Django tutorial and noticed that the customized admin classes for my models are located in models.py. In other tutorials they have been located in admin.py. My customized admin is working just fine, so I'm wondering why later Django tutorials extract admin classes out into a separate admin.py file?
admin.py is the more canonical way of storing admin classes. As the ModelAdmin documentation indicates:
The ModelAdmin class is the representation of a model in the admin interface. These are stored in a file named admin.py in your application.
It may have been different in the past or your particular tutorial may have decided to do things differently. Either way it's better to move the admin classes to admin.py.
Any tutorial with admin classes in models.py is not following the convention. The admin.py module was introduced in Django 1.0.
Before Django 1.0, you defined an inner Admin class inside the model. Any tutorial doing that is completely out of date, and should be avoided.

Django models for multiple apps

I am making my way from RoR to Django and am making a a site with two main parts - one with 'User' management and another with 'Resource' management.
As far as I understand, these two will be defined as separate apps (in RoR would have been separate controllers). In Django the default seems to be that each app has a separate model.
How can I use the same model for these two sections? Must I define them as separate apps or can I use the same model for both?
You seem confused.
A model is a class that equates (more or less) to a database table. An app is a collection of models, views and templates. You can have more than one model in an app. If your code is all highly related, then it belongs in one app. If you have more than one area of focus in your code, you should probably have more than one app, although this isn't a requirement.
If you want to use a model from one app in another, just import it.

Where is recommended spot for storing admin customizations for Django contrib apps?

I want to add Django Sessions to my Django Admin, and I am following an SO post about this, but it is unclear where I store this code. Do I put it in an admin.py file? Under what directory?
In short, it doesn't matter. You can put the code into any of your apps' admin.py files. However, in situations like these I tend to use a generic app in my project, usually named something like utils, that exists for the sole purpose of housing code that doesn't belong to one specific app or could be used by multiple apps.
If you want to be more specific, you can create a sessions app in your project specifically devoted to this code and any other code related to session management for your project, or perhaps an existing app that is somewhat related. For example, I put customizations to the User admin in my accounts app that holds the UserProfile model.

Sharing models between Django apps

I will be brief: to work in the spirit and idea of a Django app, it is ok for an app to import models from inside another app ? Say, a User statistics app will import models from a User app something like: from users.models import users
The answer is yes. It's perfectly okay for one application inside your django project to import models from another application. The power of a django project lies in the apps and their interactions.
Also make sure that you have utility applications importing models from more generic applications and not the other way. So "userstatistics" app should import models from the "users" app but "users" app should not rely on the "userstatistics".
If your app is importing models from a 3rd party application (lets say django-piston), be sure to specify that in a requirements file.
If you're building an internal app that has no chance of ever being released to the public, sure, do whatever you want.
If you're building an internal app that has little chance of ever being released to the public, but will possibly be used by future/current developers, sure, but be sure to document what the app needs to work properly.
If you're building an app for public release, try to keep it self-dependent (and django-internals dependent, ie, use what django provides, when possible). If you really need a third-party app to work, or if a third party app would make your code more manageable, then sure, include dependencies, but be doubly sure to document all requirements and necessary setup.
In most cases, you can do almost whatever you want so long as you have sufficient documentation.
I do, however, have to question the sanity of making your own User model that has the same name as django's builtin auth.User.
You cand try better extending the Django User model with inheritance. You will use the django user with custom field added, so you will have the same user for all the apps.
You can directly import models in app2/models.py. Usually you might need a foreign key, which looks like
models.ForeignKey('app1.ModelClass1', on_delete=models.CASCADE, related_name='modelclass2')
Don't do this. They will have the same app name and the ORM will be confused. Use an abstract model instead, and have both derive from it.

How to register a model in django-tagging anywhere not in the applications?

Is it possible to register a model in django-tagging not in tagging app, nor in my app?
The standard way is to edit apps/myapp/models.py this way:
from apps import tagging
tagging.register(MyModel)
I want to keep both applications without changes, for example, to be able to pull new versions and just replace them. So I tried putting this into project settings.py, in the end, but of course this fails.
from apps.myapp.models import MyModel
from apps import tagging
tagging.register(MyModel)
(This fails when importing MyModel.)
Any other way?
You can't do that in settings.py, as the models haven't been set up yet. One possibility is to do it in urls.py - admin.autodiscover is already there, so this might be a good place for the call to tagging.register as well.
There has been quite a lot of discussion in the django-developers group about the correct place for this sort of thing, but as yet no firm policy has been reached.