Django: How does it find the User model? - python

I have a question to the AUTH_USER_MODEL in Django:
https://docs.djangoproject.com/en/dev/ref/settings/#auth-user-model
The default value is auth.User. However, the actual model is in auth.models.User. How does Django find the correct class?
I am asking because when I usually use models in Django, I have to write from myapp.models import MyModel. So, why do I not need models in auth.User for AUTH_USER_MODEL?
Can some explain me that or show the code that uses it?

Well you define models in the models.py file of an app. So that means that the module in which you stored the model class is app.models. Therefore the import reads:
from app.models import MyModel
Django has in essence nothing to do with this: this is how Python loads modules and classes from these module(s).
Django however loads - when you for example run the server - the apps that are located in the INSTALLED_APPS list of the settings file (usually settings.py), and thus constructs a "register" where it stores Django models, and it names them in a uniform way: app_name.ModelName. There is no reason to specify models here, since models are defined in models.py, and it thus would only introduce "noise".
You can obtain a reference to the model class with apps.get_model [Django-doc]
from django.apps import apps
apps.get_model('app_name', 'ModelName')
It thus then checks the registers of the loaded models, and returns a reference to the model.
Linking through a string is useful (and sometimes required) when there is cyclic referencing. For example if you have two models A and B, and A refers to BandBthroughA(for example withForeignKeys), then one of the two models is defined first. This means that if you defineAfirst, it can not refer to theB` class itself, since at that point it does not yet exists. In Django, one then specifies the model through a string. The Django system will then first load the models, and then "tie the knot": resolve the references by replacing the strings with a reference to the actual model class.

Related

Django get list of Classes defined in controller of an application

I am creating django permissions based on django views rather than basic model based permissions. Hence I want to get the list of all the classes in a view. I tried the following:
from django.apps import apps
apps.get_app_config('my_app')
And also:
import sys, inspect
inspect.getmembers(sys.modules['my_app'], inspect.isclass)
But I didn't get classes object.
apps.get_app_config('my_app').get_models()
will return a list of all models declared in your application.
if you want to get all models including those in INSTALLED_APPS you can
appconfigs=apps.get_app_configs()
for appconfig in appconfigs:
models = appconfig.get_models()

Changing default auth_user table name

i'm happy with django built in user/auth , i just want to add some fields to it and change table name (mostly the last one , i can use another table for custom fields )
so i searched around and apparently we can use subclass as suggested on Rename Django's auth_user table?
So i have to start a new app and use it's model to as a subclass for AbstractUser or there is another way? (After all i just want to use it's model and other parts of app are useless )
anyway i created a new project / started app called customuser and in its model i have this code
customuser/models.py
from django.db import models
from django.contrib.auth.models import AbstractUser
class customuser(AbstractUser):
class Meta:
swappable = 'AUTH_USER_MODEL'
db_table = 'customuser'
i ran makemigrations AND migrate ... it's done successfully
but atill the tables with default name was created in database as you can see below ... am i missing something ?
To use a custom user model, you need to set the AUTH_USER_MODEL setting in your settings module.
Note that you don't need to set swappable = 'AUTH_USER_MODEL'. This is an undocumented and private attribute, and is probably better left untouched.
Quite frankly if you're still in the position to do it, i'd just start a new app. It says in the docs that this decision is best made before starting your project because its a pain in the ... its hard.
If you intend to set AUTH_USER_MODEL, you should set it before creating any migrations or running manage.py migrate for the first time.
The solution otherwise is to dumpdata from the database, and manually tweak it so any reference to the user class in your dump file is replaced with your new user class. then you need to create some migrations to change the schema.
So it is doable. its just much simpler to start from a fresh project.
Django allows you to override the default User model by providing a value for the AUTH_USER_MODEL setting that references a custom model
AUTH_USER_MODEL = 'myapp.MyUser'
This dotted pair describes the name of the Django app (which must be in your INSTALLED_APPS), and the name of the Django model that you wish to use as your user model.
A full example of an admin-compliant custom user app can be found on the Django Project website.

Django - Using different models in different environments

We have a django application that is, at its core, a series of webpages with Forms which our users fill out in order. (We'll call the particular series of pages with forms on them a "flow".)
We will be white-labeling this application for a Partner -- the Partner will want to add some fields and even add some webpages with their own new Forms. This may result in a new order in which the Forms are filled out. (A new "flow", in addition to changes to existing Forms/Models or new Forms/Models.)
What is the best way to extend our existing, simple Forms-and-Models structure to use different Forms and Models depending on the running instance of the app (e.g. an environment variable)? Some things we thought about:
implement something like get_user_model for every Model and Form use in the app, which would look at the current environment
implement a more generic key-value store so that we're not bound by the current implementation's field types (i.e., have the data field name be part of the data as well)
a data model which tracks this particular environment's "flow" and which models it needs to use
subclass existing Models and Forms for each new white-label implementation
Model Field injection may be what you are looking for, take a look of this article
The approach boils down to three concepts:
Dynamically adding fields to model classes Ensuring Django’s model
system respects the new fields
Getting the load ordering correct for the above to work
Mezzanine has done a beautiful job implementing this model field injection with dynamic extra models via EXTRA_MODEL_FIELDS

Django Models: Where is Model class?

On documentation it has been said that each model is a python subclass of models.Model class that is inside django folder followed by db folder. When i look inside my django folder i see a db folder which was expected and inside my db folder i see models folder which contains lot of files. But I was expecting a models.py package which contains Model class. So my doubt is from where does this models.Model class come from?
This might be not a top level question but I am hopeful someone here will certainly help.
Nope it's not magic it's django , it does exist if you go to the django's source code, you can see that the Model class exists, But in that way don't you had to import models in this way??:
from django.db.models.base import Model
Yes you can do it in that way, But django does it for you in the models/__init__ file, so the only thing you have to do is:
from django.db import models
models refers to the models folder inside django.db but when you import it, it brings you all the things that are inse the models/____init__.py file, I recommend you to read this

Django model proxy in diffrent package

I want to use one model for global scope for app. In future, probably models will be changed. I created backend.py file in root directory of project with model wrapper (I think it's the best solution as I can change declaration of models in one place, and using global model is more transparent than using imports from app).
from project.backend import models as backend_models
class Game(backend_models.Game):
class Meta:
proxy = True
But when I make any relation to model I get following error:
screens.screen: 'game' has a relation with model <class 'energy.backend.Game'>, which has either not been installed or is abstract.
If I import project.package.Game, not backend.Game everything works fine. Of course I have project.backend in installed apps. Only I don't know how to point django that class in backend is installed, and loaded model (from other app).
EDIT
I solved it by in backend.py:
Game = em_models.Game
But there must be same solution with extending model in non-models package.

Categories