How to use Dynaconf to configure Celery - python

Recently I discovered Dynaconf which is a nice configuration management package that integrates nicely with Flask and Django. The Django app is running wonderfully with Dynaconf. However the Celery app that my App depends on to run background tasks is not.
Here is the code for the configuration of the Celery app that was working before using Dynaconf:
from celery import Celery
app = Celery('KillerApp')
app.config_from_object('django.conf:settings', namespace='CELERY')
It seems that I need to change 'django.conf:settings' to something else. Any ideas?

You can pass in a string representing a module to import, or just pass in the configuration object directly; see the Celery.config_from_object() method documentation.
You'll have a module that sets up the Dynaconf() instance, e.g. if you have a package named acme_project with a config.py file in it with
from dynaconf import Dynaconf
settings = Dynaconf(
settings_files=['settings.toml', '.secrets.toml'],
)
then you can import acme_project.config and find the settings object there. You can either import that object or let Celery do that by using 'acme_project.config:settings' as the value you pass to app.config_from_object(). The namespace argument tells Celery to expect all settings to be prefixed with CELERY_, exactly like the way this works with Django. Use this if you plan to use the Dynaconf-managed settings to configure multiple components, not just Celery.
E.g., if you used:
app.config_from_object('acme_project.config:settings', namespace='CELERY')
then your settings.toml or settings.yaml or whatever file format you picked would need to use CELERY_ as a prefix for all the settings.

If you are using the Django plugin for Dynaconf then you are able to just use the django.conf:settings directly as Dynaconf patches the django settings object.
If you still have problems I recommend opening an issue on dynaconf repo and try using the settings of your application directly.
Example, if you have an app called foo your DJANGO_SETTINGS_MODULE might be foo.settings then you can use for celery:
app.config_from_object('foo.settings:settings')

Related

Django Django model “doesn't declare an explicit app_label” because of project's init.py file

I have a django 1.11 project with some rest_framework related apps. Writing tests for new app, I have suddenly gotten the issue
'RuntimeError: Model class core.myApp.models.query_record
doesn't declare an explicit app_label and isn't in an
application in INSTALLED_APPS'
I do have this listed in installed_apps, and in the end, the reason I have this issue is because I have an __init.py__ file in the top level of the project that loads some config for some related celery tasks.
I'm unaware why I haven't seen this issue in other app tests, as there is nothing particularly special about this app or it's model. But, this is causing all tests to fail for this app.
So, my question is, is there a way I can run these unit tests and ignore the projects top level __init.py__ ? Or maybe I should ask, is there a non-hacky way to do it?
the project level __init.py__:
from __future__ import absolute_import
from .celeryapp import app as celery_app
All other app init.py files are empty.
A problem might be, that .celeryapp is trying to import some models that aren't loaded yet.
You can try to add a AppConfig to core.myApp and load/import your celery app in it's ready() method. See the Django docs for more information Django docs for more information
It turned out, in the end this was simply because of how I was running tests
I was running tests like this
./manage.py test myApp --pattern=*.py
The pure wildcard was causing import issues. I should have done this:
./manage.py test myApp --pattern=prefix_*.py
D'oh.

Apps Registry error Django 1.8

Python version : 2.7.10
Django version : 1.8
Environment : Virtual environment
Problem: Whenever i tried to run ./manage.py runserver or shell I get this error
"The translation infrastructure cannot be initialized before the "
django.core.exceptions.AppRegistryNotReady: The translation infrastructure
cannot be initialized before the apps registry is ready. Check that you
don't make non-lazy gettext calls at import time."
Based on some responses on some related posts, I have also checked my wsgi file and it has the updated way of referencing the wsgi application. Here's how my wsgi file looks:
import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "instant_reports.settings")
from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()
Any help/guidance on resolving this ?
Did you use ugettext() in your code? Change it to ugettext_lazy().Quoting Django official documentation:
AppRegistryNotReady: This happens when importing an application configuration or a models module triggers code that depends on the app registry.
For example, ugettext() uses the app registry to look up translation
catalogs in applications. To translate at import time, you need
ugettext_lazy() instead. (Using ugettext() would be a bug, because the
translation would happen at import time, rather than at each request
depending on the active language.)
You need to use the lazy translation in your settings.py and any file (views.py, models.py) that might get imported while Django is boostrapped.

Complex Python Bottle App + WSGI

I have a python bottle application inside of a single folder that's been organized by function and I would like to convert my existing cherrypy usage over to apache mod_wsgi.
The folder structure looks like the following:
- project
-- app.py (loads the webserver class and runs it)
-- app
--- common
--- logs
--- modules
--- tools
--- web
---- webserver.py
The reason for this structure was so code from common could be used within tools and web without any issue. Imports are all done in a style of "from app.common.blah import utility". When trying to setup mod_wsgi, it expects to load up a simple application.
Is it possible to run mod_wsgi with a folder structure like this? If not, are there any recommendations for setting up a structure that will allow for mod_wsgi, but also the sharing of common utilities between folders like tools and web?
From the Bottle deployment docs on Deployment:
All you need is an app.wsgi file that provides an application object. This object is used by mod_wsgi to start your application and should be a WSGI-compatible Python callable.
File /var/www/yourapp/app.wsgi:
import os
# Change working directory so relative paths (and template lookup) work again
os.chdir(os.path.dirname(__file__))
import bottle
# ... build or import your bottle application here ...
# Do NOT use bottle.run() with mod_wsgi
application = bottle.default_app()
In your case, edit the snippet above to import the application object that is presumably defined in your app.py

Sys.path modification or more complex issue?

I have problems with importing correctly a module on appengine. My app generally uses django with app-engine-patch, but this part is task queues using only the webapp framework.
I need to import django settings for the app to work properly.
My script starts with:
import os
import sys
sys.path.append('common/')
# Force Django to reload its settings.
from django.conf import settings
settings._target = None
# Must set this env var before importing any part of Django
os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
I always get this error, or something related:
<type 'exceptions.ImportError'>: No module named ragendja.settings_pre
because the settings.py file starts with
from ragendja.settings_pre import *
I think I need to add ragendja to sys.path again but I had several tries that didn't work.
Here is my directory:
project/
app.yaml
setting.py
common/
appenginepatch/
ragendja/
setting_pre.py
myapp/
script.py
Is it only a sys.path problem and how do I need to modify it with the correct syntax?
Thanks
App engine patch manipulates sys.path internally. Background tasks bypass that code, so your path will not be ready for Django calls. You have two choices:
Fix the paths manually. The app engine documentation (see the sub-section called "Handling import path manipulation") suggests factoring the path manipulation code into a module that can be imported by your task script.
Eliminate dependencies on django code, if possible. If you can write your task to be pure python and/or google api calls, you're good to go. In your case, this might mean refactoring your settings code.
Why not:
sys.path.append('common/appenginepatch')
since the ragendja is in this directory?

Why do I need the DJANGO_SETTINGS_MODULE set?

Every time I log on to my server through SSH I need to type the following:
export DJANGO_SETTINGS_MODULE=settings
if I do not any usage of the manage.py module fails
My manage.py has the following added code:
if "notification" in settings.INSTALLED_APPS:
from notification import models as notification
def create_notice_types(app, created_models, verbosity, **kwargs):
notification.create_notice_type("friends_invite", _("Invitation Received"), _("you have received an invitation"))
notification.create_notice_type("friends_accept", _("Acceptance Received"), _("an invitation you sent has been accepted"))
signals.post_syncdb.connect(create_notice_types, sender=notification)
else:
print "Skipping creation of NoticeTypes as notification app not found"
Any ideas?
Yourmanage.py is referencing an application (notifications). This forces Django to complain about DJANGO_SETTINGS_MODULE being set because the Django environment hasn't been set up yet.
Incidentally, you can force the enviroment setup manually, but honestly I wouldn't do this in manage.py. That's not really a good practice in my opinion.
Here is how you can manually setup the Django environment from within any app (or program for that matter):
# set up the environment using the settings module
from django.core.management import setup_environ
from myapp import settings
setup_environ(settings)
You need to set the DJANGO_SETTINGS_MODULE environment variable because it's how Django knows what your settings module is called (so you can have different ones per project or for testing and development.) You can set it in the scripts themselves before you import django (directly or indirectly) but that won't do much good when you run the Django-provided scripts.
The easiest solution is probably to just set DJANGO_SETTINGS_MODULE in your shell's startup scripts, so you won't have to set it manually anymore. The usual files to add it to are .bash_profile and .bashrc (if you do indeed use bash.)
By default, manage.py looks for a settings module in the same directory as itself. If it doesn't find one, it bombs out with a message to use django-admin.py instead. It doesn't actually set up the environemnt until it runs execute_manager. If you need to run your hooks before calling your management functions, the practice I've seen suggested is to put them in the relevant app's models.py.

Categories