Add method imports to shell_plus with alias - django

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',
]

Related

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 settings.AUTH_USER_MODEL defined in separate module

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

Can I make a folder of forms and views and use an __init__.py file like models and test?

I would like to keep my views and forms separate, just like you can with models. Are you able to make a directory of views and forms, and if so, what goes in the init.py files for each.
Update:
I made my folders, but I keep getting errors. Here's all my code info:
myproject structure (abbreviated):
myproject/
myproject/
name/
forms/
__init__.py
name_form.py
models/
__init__.py
name_model.py
urls.py
views/
__init__.py
name_view.py
models/init.py
from .name_model import Name
models/name_model.py
from django.db import models
from django.urls import reverse
class Name(models.Model):
...
forms/__init__.py and views/__init__.py are blank files.
urls.py
from django.urls import path
from name.views import name_view
app_name = 'name'
urlpatterns = [
path('', views.name_view, name='name-view'),
]
forms/name_form.py
from django.forms import ModelForm, TextInput
from name.models import Name
class NameForm(ModelForm):
class Meta:
model = Name
views/name_view.py
from django.shortcuts import render, redirect
from name.forms import NameForm
def name_view(request):
...
I run python3 manage.py makemigrations in the terminal and get:
/myproject/name/views/name_view.py", line 4, in <module>
from name.forms import NameForm
ImportError: cannot import name 'NameForm'
Thinking you can't make a ModelForm without a model, I run python3 manage.py migrate and get the same error.
I created a project to isolate this issue. Without the folders it worked, unless I messed up my original code trying to get this to work.
Just make a folder for your views and a folder for your forms wherever you want them to be and put an empty __init__.py file into each folder. The purpose of the __init__.py file is to tell python to treat the folder as a module. Then make your views.py file and your forms.py file in their respective directories and now you can do...
from myproject.path.to.views import MyView
from myproject.path.to.forms import MyForm
...as if it were any other module. Which it is.

Flask Blueprints sharing

I want to make an API with Flask and it also needs to have an admin panel.
I guess that Blueprints are the way to go, but I don't want to make models twice.
My structure is going to be this:
- app
- api
- admin
- models
So my question is: How can I access the models in the models folder in my api blueprint and my admin blueprint?
Thanks in advance.
if you'd in a module within the api or admin folders you can import anything from a module in the models folder using this notation
from ..models.module_name import model1, model2, etc
for small projects i usually keep all the models in a single models.py file like:
[app]
[blueprint_1]
__init__.py
views.py
[blueprint_2]
[static]
[templates]
__init__.py
models.py
then from within any of your blueprint files just:
from ..models import model1, model2, etc
About the import, If your directory include __init__.py then it is a python package so . use for current dir. For example:
auth/
__init__.py
forms.py
views.py
#views.py
from forms import Form name
from . import auth_blueprint # imports from __init__.py
So if you wants to import from another directory you have to use .. to imports from __init__.py file let's say your models directory include those files :
models/
__init__.py
UserModel.py
Now let's import models for auth module :
#auth/views.py
from .. import models # import froms models/__init__.py
from ..models import UserModel

Import relative apps in Django

I'm new to Django and have a question about app structure and imports. My project structure looks like this (from deploydjango.com):
root/
manage.py
mysite/
__init__.py
urls.py
wsgi.py
settings/
apps/
__init__.py
profile
__init__.py
models.py
views.py
video
__init__.py
models.py
views.py
photos
__init__.py
models.py
views.py
Basically I will have some profiles on my site, where each profile then have a number of uploaded photos and videos. So in my video model I have the following code:
from django.db import models
from XXXXX import Profile
class Video(models.Model):
# more fields
company = models.ForeignKey(Profile, related_name='videos')
How do I import the Profile model for use in the Video model? Or is my structure not suitable..? What would be best practice for this?
I think your structure is fine. Basically, python's modules are just a python file which you may import like this: import <filename> and you will have its functionality imported. But when you group some python files in a folder and include in that folder a file called init.py there you have a python package. With is a better way to manage a group of modules and it allows the dot notation in your imports. Django apps behave like packages as you may see.
If you want to import Profile within your video module then you have to do this:
from profile.models import Profile
That is, assuming that the Profile model is defined in your profile app in models.py. That should do.
If you want more information about python project structure this is a great place.