How start background periodic task with django-background-tasks - python

I want to create periodic task for check values in my SQLite file. I tried to create repeating task with django-background-tasks but it doesn't work. It works fine when I used python manage.py process_tasks in cmd. How start this task with start django and without use this command?
I develop my web app on Windows 10.
urls.py
from django.contrib import admin
from django.urls import path, include
from client import tasks as task
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('client.urls')),
path('account/', include('account.urls')),
]
task.check_groups(repeat=10, repeat_until=None)
tasks.py
from background_task import background
from django.utils import timezone
from client.models import StudyGroup, Account
#background()
def check_groups():
check_active_groups()
check_inactive_groups()

From the docs:
setup a cron task (or long running process) to execute the tasks
You have to setup cron or some other periodic runner to call that command because Django by itself will not be able to do this.

Related

Using Django ORM in plain python script / infinite task

I have application in plain python with some basic libraries. I'm looking to use Django as main framework for this application and maintain frontend.
My question is, can I still use my already written application and switch to Django ORM and maybe controlling the application via some callbacks. This application is running infinitely with asincio library.
Or is there any way how to run background tasks in Django? I found celery but I'm not sure about starting this process. Maybe use of some Django commands and supervisor.
TLDR: I need some way of running background task (command, controller, python script) infinitely long without user interaction.
You can do that with Django Background Tasks.
Define your background-task as a function with the decorator #background.
Since you want your task to run infinitely, call it in your main urls.py and just set
repeat_until = None, then it will repeat infinitely.
Copied Example from the linked tutorial:
from django.shortcuts import render,HttpResponse
from background_task import background
# Create your views here.
#background(schedule=5)
def hello():
print "Hello World!"
def background_view(request):
hello(repeat=10)
return HttpResponse("Hello world !")
And this is your call in the urls.py:
from django.conf.urls import url
from django.contrib import admin
from django.conf.urls import include
from background_app.views import hello
urlpatterns = [
url(r'^admin/', admin.site.urls),
url( r'^', include('background_app.urls',namespace='background')),
]
hello(repeat=10,repeat_until=None) # This is how you call it
Doc:
https://django-background-tasks.readthedocs.io/en/latest/
Tutorial with small example:
https://medium.com/#robinttt333/running-background-tasks-in-django-f4c1d3f6f06e

Using django-stripe's built-in webhook support

I'm using Django 3.0, dj-stripe 2.0, and the Stripe CLI. dj-stripe provides native support for Stripe webhooks, and their documentation says to include the following in my django project's main urls.py file to expose the webhook endpoint:
url(r"^stripe/", include("djstripe.urls", namespace="djstripe")),
I have done this, but how do I now leverage the endpoint?
As a separate experiment, I created a payments app, setup the URL conf, and successfully called the view when triggering the non dj-stripe webhook endpoint via the Stripe CLI. But it doesn't use any dj-stripe functionality:
# project urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('stripe/', include("djstripe.urls", namespace="djstripe")),
path('payments/', include("payments.urls", namespace="payments")),
]
# payments/urls.py
from django.urls import path
from . import views
app_name="payments"
urlpatterns = [
path("", views.my_handler, name="my-handler"),
]
# payments/views.py
from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt
#csrf_exempt
def my_handler(request, **kwargs):
print(request.body)
return HttpResponse(status=200)
Running stripe listen --forward-to localhost:8000/payments/ and, in a separate window, stripe trigger product.created returns a 200 response.
But stripe listen --forward-to localhost:8000/stripe/webhook/ and stripe trigger product.created returns a 500.
Thank you in advance for your help.
[UPDATE]
I have not modified the default DJSTRIPE_WEBHOOK_URL or DJSTRIPE_WEBHOOK_VALIDATION settings. In settings.py I have:
STRIPE_LIVE_PUBLIC_KEY = os.environ.get("STRIPE_LIVE_PUBLIC_KEY")
STRIPE_LIVE_SECRET_KEY = os.environ.get("STRIPE_LIVE_SECRET_KEY")
STRIPE_TEST_PUBLIC_KEY = os.environ.get("STRIPE_TEST_PUBLIC_KEY")
STRIPE_TEST_SECRET_KEY = os.environ.get("STRIPE_TEST_SECRET_KEY")
STRIPE_LIVE_MODE = os.environ.get("STRIPE_LIVE_MODE")
DJSTRIPE_WEBHOOK_SECRET = "*************************************"
The test keys are pulled from env/bin/activate:
export STRIPE_LIVE_PUBLIC_KEY="pk_live_****...."
export STRIPE_LIVE_SECRET_KEY="sk_live_****...."
export STRIPE_TEST_PUBLIC_KEY="pk_test_****...."
export STRIPE_TEST_SECRET_KEY="sk_test_****...."
export STRIPE_LIVE_MODE="False"
When I run stripe listen --forward-to localhost:8000/stripe/webhook/ and trigger stripe trigger customer.created I get the following 500 error:
stripe.error.InvalidRequestError: Request req_NTtzsTFS8uVdfL: No such customer; a similar object exists in test mode, but a live mode key was used to make this request.
But I don't understand how my keys could be getting mixed up, because the webhooks work fine when I trigger the same event and listen via the /payments/ endpoint.
Thank you again for your time.
In summary, you need to decorate a handler function using the #webhooks.handler decorator.
You have some examples in the webhooks section of the dj-stripe documentation.

Where to instantiate a client for an external service in Django?

What is the accepted practice in Django for creating an instance of a client for an external service (e.g. Zookeeper, Cassandra, Redis, etc.)?
I need this client to perform a "set key" operation from inside a view and I don't want to create the client on each request due to high overhead.
Currently I've declared it as a global variable in views.py, but that's not really ok, because it gets instantiated when I do python manage.py makemigrations too.
A really stripped down example of the issue:
urls.py
from django.conf.urls import url
from app.views import MyView
urlpatterns = [
url(r'^', MyView.as_view()),
]
views.py
from django.shortcuts import render
from django.views import View
from django.http import HttpResponse
from kazoo.client import KazooClient
import logging
logging.basicConfig(level=logging.DEBUG)
zk = KazooClient(hosts="127.0.0.1:2181")
zk.start()
# Create your views here.
class MyView(View):
def get(self, request):
value, _ = zk.get("/my_zk_key")
return HttpResponse("value: {}".format(value))
The problem is that the zookeeper client gets created and connects in cases other than runserver, like this:
$ python manage.py makemigrations
INFO:kazoo.client:Connecting to 127.0.0.1:2181
DEBUG:kazoo.client:Sending request(xid=None): Connect(protocol_version=0, last_zxid_seen=0, time_out=10000, session_id=0, passwd=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', read_only=None)
INFO:kazoo.client:Zookeeper connection established, state: CONNECTED
No changes detected
$
I'm looking for an accepted practice in Django for dealing with such cases.
If your problem can be reduced to the last point, you can avoid setting your global variable during the migration with:
import sys
if 'makemigrations' not in sys.argv and 'migrate' not in sys.argv:
# variable setting here

How to run a task with celery in django and save result in django database?

I have made a scraper to scrape some links from web page and want to run this scraper every 1 hours which resides in django app, but django it is impossible to run a scraper every 1 hours because the django views depends on the request response object. to solve this problem I have decided to use a python library named celery and according to the documentation I have write celery.py and tasks.py files
By django project structure is like this
newsportal
- newsportal
-settings.py
-celery.py
__init__.py
- news
-tasks.py
-views.py
-models.py
celery.py has the following code
from __future__ import absolute_import
import os
from celery import Celery
# set the default Django settings module for the 'celery' program.
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'newsportal.settings')
from django.conf import settings # noqa
app = Celery('newsportal')
# Using a string here means the worker will not have to
# pickle the object when using Windows.
app.config_from_object('django.conf:settings')
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)
#app.task(bind=True)
def debug_task(self):
print('Request: {0!r}'.format(self.request))
__init__.py file has the following lines of code
from __future__ import absolute_import
# This will make sure the app is always imported when
# Django starts so that shared_task will use this app.
from .celery import app as celery_app # noqa
while as tasks.py has the following lines of code
from __future__ import absolute_import
from celery import shared_task
from crawler import crawler
from .models import News
#shared_task
def news():
'''
scrape all links
'''
news = [] #store dict object
allnews.append(crawler())
for news_dict in allnews:
for news, url in news_dict.items():
#Save all the scrape news in database
News.objects.create(title=news, url=url, source=source)
what I want to do is to run the above news() function every 1 hours and save the result to the database.
I want to save the result of the tasks to the django database, how can I achive this.
according to the celery docs, to save the result given by the worker we need install django-celery==3.1.17, as I have already installed, and do migration.
For the database backend in celery according to celery docs, we should put
app.conf.update(
CELERY_RESULT_BACKEND='djcelery.backends.database:DatabaseBackend',
)
line of code on settings.py file, on putting this of code in `settings.py` file I got the error of
settings.py", line 141, in <module>
app.conf.update(
NameError: name 'app' is not defined
as I have already Import and put the following line of code in settings.py file as below
from __future__ import absolute_import
BROKER_URL = 'redis://localhost'
The main thing I want to do is,
Running the above crawler every 1 hour and saving the result of
crawler in databse called news
How can I accomplish this using celery or am I missing something ?
Are there any other alternatives way to accomplish this task
I believe you would use app.conf.update(...) in your celery.py if you wanted to add that configuration there.
Your app.config_from_object('django.conf:settings') call in celery.py indicates that you're loading the configuration settings from your settings.py file though.
So you should just be able to put CELERY_RESULT_BACKEND='djcelery.backends.database:DatabaseBackend' at the end of your settings.py file instead.
This should prevent you from getting that error.
I know this is a little late however I can highly recommend the Django Celery Result package found here.
Installation is straight forward and the package is recommended by Celery itself. Simply return some output from your task and it will be stored in the database and accessible under the Django admin.

The current URL, app/, didn't match any of these

I'm a newbie in Django and just started looking at it before a day by installing Django 1.10 on my local.
I've followed all the instructions of this link https://docs.djangoproject.com/en/dev/intro/tutorial01/. However I'm continuously getting this error:
Page not found (404) Request Method: GET Request URL: http://127.0.0.1:8000/polls/
Using the URLconf defined in mysite.urls, Django tried these URL patterns, in this order:
^admin/
The current URL, polls/, didn't match any of these.
I've created polls app to getting started.
To make a start, I went with view.py, here is the code:
polls/views.py
from django.shortcuts import render
# Create your views here.
from django.http import HttpResponse
def index(request):
return HttpResponse("Hello World!")
Here is my code for urls.py:
polls/urls.py
from django.conf.urls import patterns, url
from . import views
urlpatterns = patterns('',
url(r'^$', views.index, name='index'),
)
And here is the urls.py in root:
mysite/urls.py
from django.conf.urls import patterns,include, url
from django.contrib import admin
urlpatterns = patterns('',
url(r'^polls/', include('polls.urls')),
url(r'^admin/', include(admin.site.urls)),
)
I've spent good piece of time to find out the solution, found that this question has been asked for many times,so tried with those solutions as well but none of them worked for me.
I can't find out what I'm missing here so please draw my attention to the gap.
I think you have edited the wrong file when trying to change the root url config.
Make sure you are editing the root url config in mysite/mysite/urls.py (the directory containing settings.py) not mysite/urls.py (the directory containing manage.py).
As general advice, install the latest release, currently 1.9. Don't use 1.10, which is under development. Make sure that you are following the tutorial for 1.9, because the tutorial changes for different versions. For example, your mysite/urls.py doesn't match the tutorial for 1.9, as the urlpatterns should be:
urlpatterns = [
url(r'^polls/', include('polls.urls')),
url(r'^admin/', admin.site.urls),
]
In settings.py you have a setting name INSTALLED_APPS-
Adds you app i.e. polls to it.
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
....
'polls',
]
It's working. Go to your url bar and type your app name:
http://127.0.0.1:8000/home
My app name is home. It will work.
If you want to set your app as your default page then import views from your app.
Like
from home import views
then write
url(r'^$', views.index),
inside.
It will set the views as your default page
http://127.0.0.1:8000/
When you type this it will redirect to your views.
I had the same problem as described. Running a Windows machine.
It turned out, that the virtual environment I was using had not been configured properly (or maybe I had forgot to activate it before installing Django) and the interpreter and django-admin were fetched from the wrong path by CMD.EXE.
If it appears as if Django is "ignoring" your urls.py - try deleting everything, re-creating the virtual environment, activating it and re-installing Django afterwards.
Make sure you have path("admin/", admin.site.urls) in your main url settings.
change the mysite/url
from django.conf.urls import patterns,include, url
from django.contrib import admin
urlpatterns = patterns('',
url(r'^&', include('polls.urls')),
url(r'^admin/', include(admin.site.urls)),
)
Then run your server and visit 127.0.0.1/8000.
This should take you to the index of your website.
or you leave your code as it is and run 127.0.0.1/8000/polls on your browser
if #Alasdair answer does not work, and it seems your working on correct files, just restart your server
The path in Django 2.2 does not support regular expression , I was using, path('(?P<id>\d+)/share/', views.mail_send_view) , so getting error, now changed to this, path('<int:id>/share/', views.mail_send_view). Now not getting any error. For more info please follow django's official documentation.
I too had same problem going through the official docs tutorial. I was using cloud 9. What I realised before I was able to solve this problem was that while creating the workspace I already chose django(ie by the time my workspace was created, django had already been installed) And going through the tutorial, I again executed $ django-admin startproject mysite thereby having another layer of django with multiple directories and unavoidably the confusion. My solution was to delete everything and start all over.
Checklist:
Make sure to run the server
>>python manage.py runserver
Watching for file changes with StatReloader
Performing system checks...
System check identified no issues (0 silenced).
February 01, 2020 - 15:04:46
Django version 3.0.2, using settings 'corona.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.
Open the browser with cmd running, http://127.0.0.1:8000/polls
should be added to the url.

Categories