Automatically import custom files in Django - python

I have a Django project containing some files which are, obviously, not automatically discovered by Django. My workaround is to import them in urls.py so that Django can see them. This is how my urls.py looks like:
from django.contrib import admin
from django.urls import path
from custom_file_1 import * # "unused" import
from custom_file_2 import * # "unused" import
urlpatterns = [
...
]
My IDE considers the commented imports unused, since they are not used, but they are vital so that Django can process those files.
And the question: is there any nice way to let Django see those files? And how to do that?

It is usually not a good idea to import things with wildcards. Imagine that in one of the custom files some object with the name path is present, then it will override the reference to the path function you imported from django.urls.
Usually one imports such files (that for example contain signals, etc.) in the AppConfig.
In the directory of the app, there is an __init__.py file. You can write
# app/__init__.py
default_app_config = 'app.config.CustomAppConfig'
In your app directory, you then define the config of your app:
# app/config.py
from django.apps import AppConfig
class CustomAppConfig(AppConfig):
name = 'app'
def ready(self):
import custom_file_1 # noqa
import custom_file_2 # noqa
Here # noqa is used to ignore the flake8 warnings.

Related

Can't import 'views' from 'urls' - Django

I'm trying to import 'views' file to my 'urls' so I could map the path to this 'vehicle_validation' function.
For some reason, pycharm can't find this file.
can someone help me understand what's the problem?
urls file:
from django.urls import path
from vehicule_approver import views # error here
urlpatterns = [
path('admin/', admin.site.urls),
path('vehicle_validation/', views.vehicle_validation)
]
views file:
import requests
from django.http import HttpResponse
import json
from pyapi.vehicule_approver.models import Vehicle
def vehicle_validation(request):
...
project structure:
structure image
I think the problem cames from the import of vehicule_approver you used in views.py.
With from vehicule_approver import views Python tries to find a module vehicule_approver inside your sys.path.
Perhaps use one of those imports:
from ..vehicule_approver import views # Relative import
from pyapi.vehicule_approver import views # Absoute import
The problem is:
from pyapi.vehicule_approver.models import Vehicle
Imports should be relative to the project directory (the one that contains manage.py), so you should remove the pyapi and change the import to:
from vehicule_approver.models import Vehicle
Alternatively, since you are importing from the same app, you can use a relative import.
from .models import Vehicle

Apps not loaded yet when using actstream django

So i'm trying to create an application for user interaction with stream_django. So far everything was going well until I got error:
'User model not registered. Please register model with actstream.registry'.
So after searching for some time, I modified my apps.py to be like this:
The project is called reviews
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import os
import django
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "reviews.settings")
os.environ["DJANGO_SETTINGS_MODULE"] = "reviews.settings"
django.setup()
from django.apps import AppConfig
from django.contrib.auth.models import User
class MyappConfig(AppConfig):
name = 'myapp'
def ready(self):
from actstream import registry
registry.register(User,self.get_model('Post'),self.get_model('UserProfile'))
But now I'm getting error:
'AppRegistryNotReady("Apps aren't loaded yet")'
I'm not sure what to do anymore, any help is appreciated.
I faced the same problem but I found that the solution was to add the default_app_config setting in the __init__.py of your main project (same location as your settings.py).
For your case, that __init__.py file should look like this:
# reviews/__init__.py
default_app_config = 'myapp.apps.MyappConfig'

apps/goods/models.py 'apps.goods.models' apps is not package?

my project directories is:
apps/
goods/
models.py
views.py
base.py
trades/
users/
__init__.py
apps/goods/base.py
from django.views.generic.base import View
from apps.goods.models import Goods
class GoodsListView(View):
def get(self, request):
json_list = []
goods = Goods.objects.all()[:10]
for good in goods:
# json_dict = {}
# json_dict['name'] = good.name
# json_dict['category'] = good.category.name
# json_dict['market_price'] = good.market_price
# json_dict['add_time'] = good.add_time
# json_list.append(json_dict)
from django.forms.models import model_to_dict
for good in goods:
json_dict = model_to_dict(good)
json_list.append(json_dict)
from django.http import HttpResponse
import json
return HttpResponse(json.dumps(json_list), content_type='application/json')
i'm debug base.py not get data, but get the error:
from apps.goods.models import Goods
ModuleNotFoundError: No module named 'apps.goods'; 'apps' is not a package
and, i remove 'apps' in 'apps.goods.models', get the error:
from goods.models import Goods
ModuleNotFoundError: No module named 'goods'
env:
pycharm-2017.2
django-1.11.6
why get the error?
Use just from .models import Goods (look at "." before models - it means the module is from current folder ).Because base.py and models.py are in same folder (same app) so you dont need to specify from which app you want to import models. Just simply include it like this.
But if you want to import models from other apps, you should to make apps to be package.In Goods app folder add __init__.py.
Structure should look like:
apps/
goods/
__init__.py
models.py
views.py
base.py
trades/
users/
__init__.py
Than use from goods.models import Goods or from apps.goods.models import Goods
As in the others' comments, you need to create the init file in the folder that should be considered a package. It's called __init__.py however. You have one of these files in apps, make sure you have it in apps/goods as well.
If you still have the same problem, make sure your configuration in Django is correct, i.e. the folder above apps is loaded

Using globals() to augment django settings

It seems to be relatively normal in the Django world to import a local environment settings override file at the end of settings.py, something like:
from settings_local.py import *
This has a couple of issues, most notably for me being that you cannot inspect or modify base settings, only override them - which leads to some painful duplication and headaches over time.
Instead, is there anything wrong with importing an init function from a local file and injecting the output of globals() to allow that local file to read and modify the settings a bit more intelligently?
settings.py:
from settings_local.py import init
init( globals() )
settings_local.py:
def init( config ):
config['INSTALLED_APPS'].append( 'some.app' )
This seems to address a number of the concerns related to using import *, but I'd like to know if this is a bad idea for a reason I am not yet aware of.
The more common and readable way to handle this is to have multiple settings files, where you put all the common settings in one module and import that at the beginning of the environment-specific settings files:
settings
__init__.py
base.py
development.py
staging.py
production.py
This allows you the mutations you are referring to:
# base.py
INSTALLED_APPS = [
'foo',
'bar'
]
# development.py
from .base import *
INSTALLED_APPS += [
'debug_toolbar'
]
Then you run your app locally with DJANGO_SETTINGS_MODULE=settings.development

Module imported twice cause recreation on an object inside it

I have a Django project. A part from this Django project was a reporting module that searches for reports directory inside all INSTALLED_APPS, very similar to autodiscover mechanism of the admin interface.
This module had a small registery class that registers classes found. In a very simplified way it looks something like this:
def autodiscover():
"""
Searches for reports module in all INSTALLED_APPS
"""
global REPORTSLOADING
if REPORTSLOADING:
return
REPORTSLOADING = True
import imp
from django.conf import settings
for app in settings.INSTALLED_APPS:
try:
app_path = import_module(app).__path__
except AttributeError:
continue
try:
imp.find_module('reports', app_path)
except ImportError:
continue
import_module("%s.reports" % app)
REPORTSLOADING = False
class ReportsRegistery(object):
.....
registery = ReportsRegistery()
If any of the INSTALLED_APPS need to register a Report class, we need a line inside reports/__init__.py:
import reports
reports.registery.register(SomeReportClass)
And inside the main urls.py i would do:
import reports
reports.autodiscover()
urlpatterns = patterns('',
....
(r'', include(reports.registery.urls)),
)
Now I decided to create a pluggable django application for it and placed the same code in __init__.py of the package. The problem I am facing is that reports module with the new structure gets imported twice, thus causing the recreation of the 'registery' object. So, no urls are actually registered. It's loaded one time from the import inside urls.py (as expected) and another one initiated by autodiscover. I have verified this by:
print hex(id(registery))
and found out it returned 2 different values.
I thought that the reports package will be imported once just like when it was just a module.
How can I prevent it from being loaded twice ? Or how can I ensure that we will have only one ReportsRegistery instance to work with ?
It's not uncommon for Django to import modules twice. There are two reasons for this:
The classic Django project layout encouraged you to have your working directory on the path twice at two different locations. This meant you could import something as project.module, or as app.project.module, which would confuse the import machinery.
The settings.py file is actually imported twice.
Fixes:
Double-check that all of your imports use the same style of path.
Don't import your module from settings.py

Categories

Resources