How to set django middleware in settings file - python

Hi all i am trying to add middleware to my app and the app is located in this location
myapp/sitemanager/middleware/__init__.py
myapp/sitemanager/middleware/redirects.py
what is the right way to declare it in my settings.py file.i currently have it set this way
MIDDLEWARE_CLASSES = ("sitemanager.middleware.redirects.SiteDetectionMiddleware")
but i keep geting this error
ImproperlyConfigured: Error importing middleware sitemanager.middleware.redirects: "cannot import name Address"
Thanks

You'd make sure that your Python path is properly configured.
Suppose (in your project) your directory structure resembling this:
Django 1.4
/mysite
/mysite/mysite #defult settings.py gonna here...
/mysite/apps
/mysite/apps/__init__.py
/mysite/apps/main
/mysite/apps/main/__init__.py
/mysite/apps/main/models.py
/mysite/apps/main/views.py
/mysite/apps/main/middleware/__init__.py
/mysite/apps/main/middleware/log.py
It is my simple midlleware logger exemple (in log.py):
from django.http import HttpRequest
import datetime
class Logger(object):
def process_request(self, request):
f = open('/tmp/log.txt', 'w')
f.write(str(datetime.datetime.now()))
Note that my custom middleware class (in log.py) is under my middleware python package, that is under main app.
So, you should put in your settings.py something like this:
import sys
sys.path.append(MY_PROJECT_ROOT)
and in middleware tuple:
MIDDLEWARE_CLASSES = (
'...',
'apps.main.middleware.log.Logger',
)

Related

Django app dissapears from Django Admin site when I add apps.py file

I'm working with Django 3.2 and trying to configure correctly the AppsConfig subclass of apps.py in order to avoid duplicate apps names when initzialing the project.
The context is the following. I have in my INSTALLED_APPS two apps whose names are equal although their paths not:
INSTALLED_APPS = [
...
'first_app.myapp',
'second_app.myapp'
]
To avoid the error shown below (and according to the documentation), I need to create an apps.py file subclassing AppConfig in at least one of the apps called myapp. I've decided to create that file in the second one, second_app.myapp.
django.core.exceptions.ImproperlyConfigured: Application labels aren't unique, duplicates: myapp
The app.py in second_app.myapp module looks like as follows:
from django.apps import AppConfig
class MySecondAppConfig(AppConfig):
name = "second_app.myapp"
label = "my_second_app"
And in the __init__.py I've added:
default_app_config = 'second_app.myapp.apps.MySecondAppConfig'
My admin.py looks like:
from django.contrib import admin
from .models import MyModel
class MySecondAppAdminModel(admin.ModelAdmin):
list_display = ('attr_1', 'attr_2')
admin.site.register(MyModel, MySecondAppAdminModel)
When I start the project all works OK and I can use that model information, views called from second_app.myapp also work OK.
The problem comes when I access to the admin site (http://localhost:8000/admin), where only appears the first_app.myapp admin form instead of both.
Can you help me? Thanks in advance.
instead of this:
INSTALLED_APPS = [
...
'first_app.myapp',
'second_app.myapp'
]
Just try this way only:
INSTALLED_APPS = [
...
'first_app',
'second_app'
]
You got that error because here first_app.myapp and second_app.myapp myapp is duplicate. you should not use like this in both the apps.
OR
INSTALLED_APPS = [
...
'first_app.apps.MyFirstAppConfig',
'second_app.apps.MySecondAppConfig'
]

Automatically import custom files in Django

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.

django-login-required-middleware WSGI error

I'm trying to apply this way to my project :
http://onecreativeblog.com/post/59051248/django-login-required-middleware
Here is my settings.py:
...
LOGIN_URL = '/admin/login/'
LOGIN_EXEMPT_URLS = (
)
MIDDLEWARE = [
...
'project.middleware.LoginRequiredMiddleware',
]
...
and here my middleware.py:
from django.http import HttpResponseRedirect
from django.conf import settings
from re import compile
EXEMPT_URLS = [compile(settings.LOGIN_URL.lstrip('/'))]
if hasattr(settings, 'LOGIN_EXEMPT_URLS'):
EXEMPT_URLS += [compile(expr) for expr in settings.LOGIN_EXEMPT_URLS]
class LoginRequiredMiddleware:
"""
Middleware that requires a user to be authenticated to view any page other
than LOGIN_URL. Exemptions to this requirement can optionally be specified
in settings via a list of regular expressions in LOGIN_EXEMPT_URLS (which
you can copy from your urls.py).
Requires authentication middleware and template context processors to be
loaded. You'll get an error if they aren't.
"""
def process_request(self, request):
assert hasattr(request, 'user'), "The Login Required middleware\
requires authentication middleware to be installed. Edit your\
MIDDLEWARE_CLASSES setting to insert\
'django.contrib.auth.middlware.AuthenticationMiddleware'. If that doesn't\
work, ensure your TEMPLATE_CONTEXT_PROCESSORS setting includes\
'django.core.context_processors.auth'."
if not request.user.is_authenticated():
path = request.path_info.lstrip('/')
if not any(m.match(path) for m in EXEMPT_URLS):
return HttpResponseRedirect(settings.LOGIN_URL)
I put that middleware.py on my project root.
project
|__db.sqlite3
|__manage.py
|__middleware.py
|__app
|___admin.py
|___views.py
|___models.py
but I got an error.
django.core.exceptions.ImproperlyConfigured: WSGI application
'project.wsgi.application' could not be loaded; Error importing
module: 'No module named 'project.middleware'
The project directory (the one including manage.py) is on the python path. Therefore you shouldn't include the project. prefix for modules in that directory.
Change your MIDDLEWARE setting to:
MIDDLEWARE = [
...
'middleware.LoginRequiredMiddleware',
]
It's better to use login_required decorator instead a middleware. Because the middleware will be executed for each and every request. So, just decorate the view with login_required decorator.
from django.contrib.auth.decorators import login_required
#login_required
def user_detail(request):
# some code

Error in URL configuration trying to set up django-contact-form

I have installed the django-contact-form module and modified my urls.py file at the root level of my django app to contain:
from django.conf.urls import include, url
urlpatterns = [
# ... other URL patterns for your site ...
url(r'^contact/', include('contact_form.urls')),
]
as per the instructions listed here:
https://django-contact-form.readthedocs.io/en/1.2/quickstart.html
But when I try and run my Django app, I get the following error:
RuntimeError: Model class django.contrib.sites.models.Site doesn't declare an explicit app_label and isn't in an application in INSTALLED_APPS.
I haven't added 'contact_form' to the INSTALLED_APPS setting as the guide explains that is not necessary.
Does anyone know what might be happening? Without that line in my urls.py file, the app runs fine.
Have you tried adding django.contrib.sites to the INSTALLED_APPS list in your settings.py?

Django: Dynamically add apps as plugin, building urls and other settings automatically

I have following structure of my folders in Django:
./project_root
./app
./fixtures/
./static/
./templates/
./blog/
./settings.py
./urls.py
./views.py
./manage.py
./__init__.py
./plugin
./code_editor
./static
./templates
./urls.py
./views.py
./__init__.py
./code_viewer
./static
./templates
./urls.py
./views.py
./__init__.py
So, how can I make root urls.py automatically build up the list of urls by looking for other urls.py based on the INSTALLED_APPS? I change settings.py in order to build INSTALLED_APPS, TEMPLATES_DIR, STATICFILES_DIRS dynamically. (It means i do not know how many plugins will be installed in different servers. It should dynamically check it on run time and add it.)on:
python manage.py runserver
Here is code for adding INSTALLED_APPS, TEMPATES_DIR, STATICFILES_DIR.
PLUGINS_DIR = '/path_to/plugins/'
for item in os.listdir(PLUGINS_DIR):
if os.path.isdir(os.path.join(PLUGINS_DIR, item)):
plugin_name = 'app.plugins.%s' % item
if plugin_name not in INSTALLED_APPS:
INSTALLED_APPS = INSTALLED_APPS+(plugin_name,)
template_dir = os.path.join(PLUGINS_DIR, '%s/templates/' % item)
if os.path.isdir(template_dir):
if template_dir not in TEMPLATE_DIRS:
TEMPLATE_DIRS = TEMPLATE_DIRS+(template_dir,)
static_files_dir = os.path.join(PLUGINS_DIR, '%s/static/' % item)
if os.path.isdir(static_files_dir):
if static_files_dir not in STATICFILES_DIRS:
STATICFILES_DIRS = STATICFILES_DIRS + (static_files_dir,)
Any help will be appreciated. Thank you in advance.
SOLUTION:
EDIT: So what i did are as following:
I include two modules like this:
from django.conf import settings
from django.utils.importlib import import_module
And then in root urls.py I add following code:
def prettify(app):
return app.rsplit('.', 1)[1]
for app in INSTALLED_APPS:
try:
_module = import_module('%s.urls' % app)
except:
pass
else:
if 'eats.plugins' in app:
urlpatterns += patterns('',
url(r'^plugins/%s/' % prettify(app), include('%s.urls' % app))
)
Thank you a lot #Yuka. Thank you. Thank you. Thank you. Thank you....
You make my day.
What you'll want is something like this:
from django.utils.importlib import import_module
for app in settings.INSTALLED_APPS:
try:
mod = import_module('%s.urls' % app)
# possibly cleanup the after the imported module?
# might fuss up the `include(...)` or leave a polluted namespace
except:
# cleanup after module import if fails,
# maybe you can let the `include(...)` report failures
pass
else:
urlpatterns += patterns('',
url(r'^%s/' % slugify(app), include('%s.urls' % app)
)
You'll also want to steal and implement your own slugify from django template or utils (I'm not exactly sure where it lives these days?) and slightly modify it to strip out any 'dots' and other useless namespacing you don't want in your 'url' e.g. you might not want your urls looking like so: 'example.com/plugin.some_plugin_appname/' but like example.com/nice_looking_appname/
You might even not want it automagicly named after all, and instead made a configurable 'setting' in your plugins own 'settings' module or something like so:
# plugin settings conf
url_namespace = 'my_nice_plugin_url/'
# root urls.py:
url(r'^%s/' % mod.url_namespace, include(...))
# or:
url(r'^%s/' % app.settings.url_namespace, inc..
You probably get the gist of it.
Kind regards,
I have modified the logic of #wdh and I have tested with Django 2.2.9 (latest stable in Jan 2020) and python 3.8
urls.py
from django.apps import apps
from django.conf import settings
for app in settings.INSTALLED_APPS:
if app.startswith('myappsprefix_'):
app_config = apps.get_app_config(app.rsplit('.')[0])
urlpatterns += i18n_patterns(
path(f'{app_config.urls}/', include(f'{app_config.name}.urls')),
)
i18n_patterns is for internationalization.
apps.py of every app
class MyCustomAppsConfig(AppConfig):
name = 'myappsprefix_mycustomapp'
urls = 'mybaseurlforapp' # required!
in my settings.py
INSTALLED_APPS = [
...
'myappsprefix_mycustomapp.apps.MyCustomAppsConfig',
...
]
It is best practice not to access INSTALLED_APPS directly as stated in django docs but to use the registry instead:
from django.apps import apps
for app in apps.get_app_configs():
app_name = app.name
try:
...
Have you tried something like:
for app in INSTALLED_APPS:
# You'll want to check that you can import the urls of that app here
urlpatterns += patterns('',
url(r'^%s/' % app, include('%s.urls' % app) )
)
I've modified #Progressify's code a bit further to do away with the app prefix.
# in your project's urls.py
from django.apps import apps
from django.contrib import admin
from django.conf import settings
from django.urls import include, path
urlpatterns = [
path('admin/', admin.site.urls),
# ...
# any other paths you may have
]
# Load urls from any app that defines a urls attribute in appname.apps.AppConfig
for app in settings.INSTALLED_APPS:
try:
app_config = apps.get_app_config(app.rsplit('.')[0])
try:
urls = app_config.urls
urlpatterns += [
path(f'{app_config.urls}', include(f'{app_config.name}.urls', namespace=f'{app_config.urls_namespace}')),
]
except AttributeError:
pass
except LookupError:
pass
This will look for an AppConfig in your project's apps.py that defines a prefix and a namespace, and include those accordingly. Admittedly the error catching is a bit crude, so you may want to refine it a bit depending on whether you want to allow your app to define urls but not a namespace, etc.
# in each of your apps' apps.py
from django.apps import AppConfig
class UsersConfig(AppConfig): # name the class whatever you want
name = 'users' # name of your app
urls = '' # prefix for this app's urls –– may need to append slash
urls_namespace = 'users' # app url namespace –– it's "best practice" to define one

Categories

Resources