I added settings for django_crontab
INSTALLED_APPS = [
....
'django_crontab',
....
]
and setting for cron
CRONJOBS = [
('* * * * *', 'app.cron.task'),
]
add task method to app.cron
from .views import add_to_cache_table()
def task():
add_to_cache_table()
and created method add_to_cache_table() in app.views:
from django.core.cache import cache
def add_to_cache_table():
cache.add('key', 'value')
But, when I'm trying to get value form cache by that key, I get None.
Can i use database cache in cron and write to it?
Thanks!
Hosting service (Pythonanywhere) doesn't support crontab for users.
https://github.com/kraiz/django-crontab/issues/14
Related
I am using django-background-tasks to read data from an API into my database. A cronjob is starting python manage.py process_tasks every 15 minutes and works off the jobs in the queue. The task is looking like:
#background(schedule = 900)
def API_2_DB()
....
return None
Now for the first question:
So, how do I reliable create the tasks that will be worked off while the page is "not in use"?
Second question: The database is stockpiling completed tasks - I know I can easily delete them with CompletedTasks.objects.all().delete() somewhere - but is there no built in automatism for this?
As I needed to look around a lot and Stackoverflow being my major source for django related questions, I thought I shared what I learned in case someone comes looking for the same question here:
After a task was created in the task.py inside an app you can regularly call that task while no user is active calling it from the project urls.py:
urls.py:
from django.contrib import admin
from django.urls import path, include
from django.views.generic.base import RedirectView
urlpatterns = [
path('home/', RedirectView.as_view(url='/')),
path('admin/', admin.site.urls),
path('', include('APPName.urls')),
]
from APPName.tasks import API_2_DB
API_2_DB(repeat=100, repeat_until=None)
I have to allow the admin the set the cron time from admin view in django.
Like i have an configuration model , where admin can put the time as record
2 am (record 1)
4 pm (record 2)
So on each record i have to run the cron.
But cron time is in setting.py
CRONJOBS = [
('*/5 * * * *', 'myapp.cron.my_scheduled_job')
]
https://pypi.org/project/django-crontab/
How to make this setting available for admin.
I don't see any nice way of doing it, because vanilla django_crontab allows populating crontab only from settings. You'd better find other package that allows what you want. But if you have no choice, I think the following will work:
my_crontab.py
from django_crontab.app_settings import Settings
from django_crontab.crontab import Crontab
from django.conf import settings
# function need to return crontab
# in the same format as settings.py
def populate_from_db():
# some db magic
return [('*/5 * * * *', 'myapp.cron.my_scheduled_job')]
class DBCronSettings(Settings):
def __init__(self, settings):
super().__init__(settings)
self.CRONJOBS = populate_from_db() #
class DBCrontab(Crontab):
def __init__(self, **options):
super().__init__(**options)
self.settings = DBCronSettings(settings)
You need to subclass Crontab and Settings. Make DBCronSettings read your cron jobs from database and then use this settings in your custom DBCrontab.
Then make your own crontab command. Handle method exactly the same as in base command, but uses your DBCrontab class instead of original.
command.py
from django_crontab.management.commands.crontab import Command as CrontabCommand
from my_crontab import DBCrontab as Crontab
class Command(CrontabCommand):
def handle(self, *args, **options):
"""
Dispatches by given subcommand
"""
if options['subcommand'] == 'add': # add command
with Crontab(**options) as crontab: # initialize a Crontab class with any specified options
crontab.remove_jobs() # remove all jobs specified in settings from the crontab
crontab.add_jobs() # and add them back
elif options['subcommand'] == 'show': # show command
# initialize a readonly Crontab class with any specified options
with Crontab(readonly=True, **options) as crontab:
crontab.show_jobs() # list all currently active jobs from crontab
elif options['subcommand'] == 'remove': # remove command
with Crontab(**options) as crontab: # initialize a Crontab class with any specified options
crontab.remove_jobs() # remove all jobs specified in settings from the crontab
elif options['subcommand'] == 'run': # run command
Crontab().run_job(options['jobhash']) # run the job with the specified hash
else:
# output the help string if the user entered something not specified above
print(self.help)
Also don't forget to remove django_crontab from INSTALLED_APPS if you plan to name your command 'crontab'.
I have been trying to import a model in a middleware process function but I am getting the error:
Value: Model class x doesn't declare an explicit app_label and isn't in an application in INSTALLED_APPS
I am guessing the problem is that the application setup is not complete, however, all my attempts to solve this have hit a wall.
middleware.py function
from notifications.models import Notification
...
class CheckNotificationMiddleware(object):
"""
Checks clicked notification to mark it as read
"""
def process_request(self, request):
if request.user.is_authenticated():
notification_id = request.GET.get('notification_id')
if notification_id:
AppConfig.get_model('Notification')
try:
notification = Notification.objects.get(
pk=notification_id, status=0, recipient=request.user)
notification.status = 1
notification.save()
except ObjectDoesNotExist:
pass
settings.py
INSTALLED_APPS = (
...
'notifications',
...
)
I have tried a couple of things including...
from django.apps import AppConfig
AppConfig.get_model('Notification')
I am using Django version 1.11 and python 2.7
you have to include notifications under the
INSTALLED_APPS = [
'notifications',
]
in the settings file
I have a Django project that I am building. Within the django project I have two apps. one is users and one is accounts. I want to call a view from the acounts app called user_synapse in the users app. I have imported the accounts views python file to import all the methods. I am then calling the method but I am getting an error that says the view method that I am trying to call is not defined. It was working earlier but now it is not working at all. I added the django app name to the settings file and the main urls file. Here is the code I have:
Users app:
views.py file:
#import all references from other apps
from accounts.views import *
from groups.models import *
from groups.views import *
...
# create synapse user
user_synapse(request)
accounts app:
views.py file:
#import all references from other apps
from groups.models import *
from groups.views import *
from users.views import *
from users.models import *
# synapse import statements that are needed
from synapse_pay_rest import Client, Node, Transaction
from synapse_pay_rest import User as SynapseUser
from synapse_pay_rest.models.nodes import AchUsNode
...
# ensure someone is logged in
#login_required
# create a synapse user
def user_synapse(request):
# grab the logged in user
user = request.user
# grab users profile
profile = Profile.objects.get(user = user)
# set user items before creating items
legal_name = profile.first_name + " " + profile.last_name
note = legal_name + " has just created his synapse profile "
supp_id = generate_number()
cip_tag = user.id
# grab the account type
account = profile.business
if account == 'INDIVIDUAL':
account = False
if account == 'BUSINESS':
account = True
# the following is all of the information that is required in order to make a
# new user within the Synapse application
args = {
'email':str(user.email),
'phone_number':str(profile.phone),
'legal_name':str(legal_name),
'note': str(note),
'supp_id':str(supp_id),
'is_business':account,
'cip_tag':cip_tag,
}
# the following is the request to the synapse api as well as the returned
# json that contains information that needs to ba saved in local database
create_user = SynapseUser.create(client, **args)
response = create_user.json
# the following updates the current profile to add the users synapse id within
# the local database.
if response:
synapse_id = response['_id']
updateProfile = profile
updateProfile.synapse_id = synapse_id
updateProfile.save()
the view does exist. why in the world is it saying that the method is not defined:
NameError at /personal/
name 'user_synapse' is not defined
settings.py file:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'general',
'users',
'localflavor',
'groups',
'accounts',
]
It was working earlier but now it is not working and I have no idea why.
The problem is that you have a circular import: in users.views.py
from accounts.views import *
in accounts.views.py
from users.views import *
This is not permitted in Python. See import dependency in Python for more info.
My Django site uses the LDAP backend for authentication in production, but this is not suitable for testing (impossible to create requests from dummy users). How can I disable this backend, solely for tests?
Here is the relevant settings.py section:
AUTHENTICATION_BACKENDS = (
#'crowd.backend.CrowdBackend',
# 'django_auth_ldap.backend.LDAPBackend',
'django.contrib.auth.backends.ModelBackend',
)
AUTH_LDAP_SERVER_URI = "ldap://ldap.cablelabs.com"
import ldap
from django_auth_ldap.config import LDAPSearch
AUTH_LDAP_BIND_DN = "CN=CableLabs Internal,OU=cabletest,OU=Teamwork,OU=community,DC=cablelabs,DC=com"
AUTH_LDAP_BIND_PASSWORD = "UAq,0#ki"
AUTH_LDAP_USER_SEARCH = LDAPSearch("ou=community,dc=cablelabs,dc=com",ldap.SCOPE_SUBTREE, "(sAMAccountName=%(user)s)")
AUTH_LDAP_USER_ATTR_MAP = {"first_name": "givenName", "last_name": "sn","username":"sAMAccountName","email":"mail","photo":"thumbnailPhoto"}
AUTH_LDAP_CONNECTION_OPTIONS = {
ldap.OPT_REFERRALS: 0
}
If you only need/want to disable the backend for certain tests, you can also use the override_settings decorator. You can use this decorator on the test case class:
from django.test.utils import override_settings
#override_settings(AUTHENTICATION_BACKENDS=
('django.contrib.auth.backends.ModelBackend',))
class FooTest(TestCase):
def test_bar(self):
pass
But you can also selectively use it on a test method:
from django.test.utils import override_settings
class FooTest(TestCase):
#override_settings(AUTHENTICATION_BACKENDS=
('django.contrib.auth.backends.ModelBackend',))
def test_bar(self):
pass
Create an alternative settings file, for example myproj/test_settings.py, and specify that settings file when running unit tests.
Write the alternative settings file like this:
from myproj.settings import *
AUTHENTICATION_BACKENDS = (
#'your.ldap.backend',
'django.contrib.auth.backends.ModelBackend',
)
That is, the settings inherits everything from your regular settings, but overrides the AUTHENTICATION_BACKENDS definition, with your LDAP backend commented out.
Then, run your tests like this:
python manage.py test --settings=myproj.test_settings
For future reference, another option to look into for testing is to change the is_authenticated property of the User object to a lambda. For example:
user = User(...)
user.is_authenticated = lambda: True