Sharing models between Django apps - django

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.

Related

Deploying Django admin and Site as different applications

Is there a way to deploy Django Admin and your main application separately, though both of them sharing the same Models / Business logic services.
I come from Grails background where you can create a plugin which can hold your Entities and common business logic and that plugin can be utilized by other application deployed and scaled separately though using the same Database. You don't have to repackage your plugin again for every change rather its just sibling folder to your other projects.
Can I achieve something similar with Django?
Assuming a typical setup, in order to be useful Django Admin needs access to project's apps and their models.
So a setup that you've described would require at least:
simple URLconf with just Django Admin
models and their Admin bindings for all apps that need Admin
settings with database credentials
Even if your models and Admin bindings are not dependent on other parts of the codebase,
extracting the above components to a separate project and then keeping everything
in sync sounds pretty hard.
Summarizing: I would say it's hard but possible if it's something that you really need,
but Django Admin hasn't been designed with such use case in mind.
Django admin is actually separate from the main application by placing it on its own url. Even if they know the admin url, users cannot log in to the site's admin unless they have already been assigned Staff status via the admin. You can set the admin prefix to anything you want, so if you want to "hide" the admin login page, just make it something long and random (good for security too), and basically no one but those you tell will even know where the admin site can be found.

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

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.

Django 1.5 and new User model : what about third party apps?

I am making some tests on a development site, currently using Django 1.4.
Most Django users are aware that Django 1.5 brings more flexibility in User models.
The project I'm working on uses monkey-patching on the auth.User model, and it works well. This adds useful methods I use everytime.
I have not added any database field on the User model for the sake of compatibility, my code only involves this:
User.__bases__ += (UserPlus,)
User.__unicode__ = UserPlus.__unicode__
UserPlusManager().contribute_to_class(User, 'objects')
with UserPlusManager being a subclass of UserManager.
Now, imagine I want to switch to the new user model. I already have many apps in INSTALLED_APPS, some of them are on unmaintained repos and have models with fields tied to auth.User.
I don't see a ny obvious strategy for this kind of configuration.
So, is it really advisable to upgrade to Django 1.5 with this in mind ? If so, what steps should I take ?
If a construct in Django changes, any third-party apps that leverage that construct would have to react accordingly. If your project is dependent on third-party apps that aren't 1.5 compatible, you should wait to upgrade your project until they are.

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.

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.