Django settings.AUTH_USER_MODEL defined in separate module - django

What is the proper way to say what is my AUTH_USER_MODEL?
I have the following set:
Folder structure:
--- backend
----- api
-------- models
----------- user.py
user.py lies within models folder
in settings.py:
AUTH_USER_MODEL = 'myapp.User'
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'api',
]
The model:
class User:
class Meta:
app_label = "myapp"
And when I run any manage.py command, for example
python manage.py showmigrations
I get this error:
LookupError: No installed app with label 'myapp'.
The problem solution would be renaming api folder to myapp, which I cannot do due to some restrictions on model names. Or setting AUTH_USER_MODEL to api.User, but this will incur changing all data table names and those must remain the same
Data table names starting with 'myapp_' should not change

Given your folder structure looks like that:
backend
└── api
| ├── __init__.py
| ├── apps.py
| └── models
| ├── __init__.py
| └── user.py
├── manage.py
└── settings.py
then you can create an app config in backend/api/ by creating a file called apps.py inside it. There you can rename your app:
backend/api/apps.py:
from django.apps import AppConfig
class MyAppConfig(AppConfig):
name = 'myapp'
verbose_name = _('My App')
Also you need to add this to the __init__.py inside that folder:
backend/api/__init__.py:
default_app_config = 'api.apps.MyAppConfig'
Also if you want to use myapp.User as your user model you also have to import in in the models module:
backend/api/models/__init__.py:
from .user import User
# or use "from .user import *" to import everything but then make sure you have __all__ defined in user.py

The solution was to change AppConfig.label in class MyAppConfig(AppConfig), so if you update your answer, I will accept it. Changing name ends in nothing, it must be the real name of the module the code sits in, but adding label = 'arbitrary_name' is actually the solution

Related

Add method imports to shell_plus with alias

I have a model naming collision in my django models, with 2 models called Tag in separate modules. That looks something like this:
.
├── conversations/
│   └──models.py <- contains a model called Tag
└── dogs/
   └──models.py <- contains a model called Tag
In shell_plus I want to import each module with an alias in SHELL_PLUS_POST_IMPORTS so that it's available when I start the shell. How can I do this?
As an example, if i were doing this manually in shell_plus I'd write:
# These are the imports I want to happen automatically:
from conversation import models as conversation_models
from dogs import models as dog_models
# Then I can write:
conversation_models.Tag()
dog_models.Tag()
In your settings you can specify additional imports:
SHELL_PLUS_IMPORTS = [
'from conversations.models import Tag as ConversationsTag',
'from dogs.models import Tag as DogsTag',
]

Django AppConfig ready()

I have Django 2.1.7
I read Django documentation as well as, this How to use django AppConfig.ready() and this Overriding AppConfig.ready().
Now, the folder/file structure is like this,
my_app
__init__.py
urls.py
sub_app1
migrations
__init__.py
admin.py
apps.py
models.py
...
sub_app2
...
sub_app3
...
and all sub_apps are registered into INSTALLED_APPS of Django settings.py file as my_app.sub_app1 for example. I noticed that when I try to override ready()for sub_app1 w/in sub_app1.apps.py, overriding has no effect.
When I flatten my structure above as
my_app
__init__.py
urls.py
apps.py
overriding of ready works fine.
In other words, it seems that overriding of readyof a sub app w/in sub app's apps.py doesn't work.
Also, whether using default_app_config w/in sub app's __init__.py or my_app.sub_app1.apps.SubApp1Config w/in settings.py INSTALLED_APPS it gives error django.core.exceptions.ImproperlyConfigured: Cannot import 'sub_app1'. Check that 'my_app.sub_app1.apps.SubApp1Config.name' is correct.
Why is this happening?

Django app_label is wrong on models

I have a Django DRF application. Here is my project structure.
myproject/
myproject/
apps/
myApp1/
__init__.py
apps.py
admin.py
models.py
urls.py
views.py
myApp2/
__init__.py
static/
manage.py
and myINSTALLED_APPS contains:
INSTALLED_APPS = [
'apps.myApp1.apps.AppOneConfig',
'apps.myApp2.apps.AppTwoConfig',
]
When I went to ./manage.py shell_plus and run:
SomeModel._meta.label
I see myApp1 or myApp2 instead of apps.myApp1 && apps.myApp2. And even in migrations Models are referred as myApp1.Model or myApp2.Model not as apps.myApp1.Model or apps.myApp2.Model
Also, specified AppConfig.
from django.apps import AppConfig
class AppOneConfig(AppConfig):
name = 'apps.myApp1'
verbose_name = 'My App One'
Is that expected ? I am pretty new to Django. Can anyone suggest what the mistake was?
Is that expected?
Yes, that is expected. By default, the app label uses the last part of the "python path". You can change it by specifying this in the AppConfig [Django-doc]. It is the .label attribute [Django-doc] of this AppConfig that determines the app label, and:
(…) It defaults to the last component of name. It should be a valid Python identifier. (…)
Now the .name attribute [Django-doc], and this is:
Full Python path to the application, e.g. 'django.contrib.admin'.
You can specify this by first specifying the AppConfig in the __init__.py file of your myApp1 directory:
# apps/myApp/__init__.py
default_app_config = 'apps.myApp.apps.App1Config'
then you make a file apps.py in the myApp1 directory, and write:
# apps/myApp/apps.py
from django.apps import AppConfig
class App1Config(AppConfig):
label = 'apps_myapp1'
Note: normally directories use slug_case, so I think it might be better to rename your myApp1 to myapp1 or my_app1.
EDIT: You thus need to set the label attribute of your AppOneConfig to:
class AppOneConfig(AppConfig):
name = 'apps.myApp1'
label = 'apps_myapp1'
verbose_name = 'My App One'

Django apps sharing a model

I Django can 2 apps share 1 model, or 2 apps must define the same model inside. so app1 and app1 can have have same products model inside them for example?
Yes, app1 and app2 can share the same model. You need to import it wherever you want to use it.
Lets say your project structure is like below having 2 apps app1 and app2.
my_project/
manage.py
my_project/
__init__.py
settings.py
urls.py
wsgi.py
app1/
__init__.py
admin.py
migrations/
__init__.py
models.py
tests.py
views.py
app2/
__init__.py
admin.py
migrations/
__init__.py
models.py
tests.py
views.py
Then to use the models defined in app1/models.py in app2, you just need to do:
from app1.models import MyModel # import the model
Just import the model from the app that defines it to the app that is using it.

ImportError After Moving App to Nested Folder

My application was working fine when I wanted to see whether I could organize my project in a better way. I read through this tutorial on structuring a django project.
Before my project structure was as follows:
camucamu
books
admin.py
models.py
views.py
__init__.py
static
templates
urls.py
views.py
settings.py
wsgi.py
__init__.py
What I wanted to do was move the books app into an apps folder. Thus I did that and changed the project structure to the following:
camucamu
apps
books
admin.py
models.py
views.py
__init__.py
static
templates
urls.py
views.py
settings.py
wsgi.py
__init__.py
I then changed the imports in views.py and admin.py
from books.models to apps.books.models.
I also changed INSTALLED_APPS in settings.py from books to apps.books.
When I then tried to run syncdb, I get the following error:
raise ImproperlyConfigured('ImportError %s: %s' % (app, e.args[0]))
django.core.exceptions.ImproperlyConfigured: ImportError apps.books: No module named apps.books
What am I messing up here so it can't find my app anymore?
Your apps folder does not have an __init__.py file so it cannot be recognized as a python module
I got the same error, following the same guide, as the last point of the following list was not cited. Make sure you performed the following changes:
Create a blank __init__.py file inside the apps folder (needed for python to recognize it as a package)
Update the import statements wherever you refer to an external app:
from projectname.apps.appname.models import YourModel, YourOtherModel
Inside settings.py edit INSTALLED_APPS such that it looks like this:
INSTALLED_APPS = (
...
# apps
'projectname.apps.appname1',
'projectname.apps.appname2',
)
This one is not specified in the guide: In all your urls.py files, update the urlpatterns!
BEFORE:
# client views
urlpatterns += patterns('appname',
...
)
AFTER:
# client views
urlpatterns += patterns('projectname.apps.appname',
...
)
Finally remember to update your changes by calling python manage.py syncdb
Hope that helped.