Making django server tick? - python

I have a django server setup on Linux/Apache/Mysql with WSGI (WGSIDaemonProcess/WGSIDaemonGroup/WSGIScriptAlias).
I'd like to write a python function that has access to all the backend models and stuff that a normal view function has, and to have that function run periodically (perhaps once a second or faster) while the server is up.
I guess I could write a new view function and then write a local script to GET that url every second, but is there a way of doing this within the django app itself?

Related

How can I test the functions in this Flask app- write unittests?

POOL = redis.ConnectionPool(host='localhost', port=6379, db=0)
app = Flask(__name__)
#app.route('/get_cohort_curve/', methods=['GET'])```
def get_cohort_curve():
curve = str(request.args.get('curve'))
cohort = str(request.args.get('cohort'))
key = curve+cohort
return get_from_redis(key)
def get_from_redis(key):
try:
my_server = redis.Redis(connection_pool=POOL)
return json.dumps(my_server.get(key))
except Exception, e:
logging.error(e)
app.run()
I need to write unit-tests for this.
How do I test just the route, i.e. a get request goes to the right place?
Do I need to create and destroy instances of the app in the test for each function?
Do I need to create a mock redis connection?
If you are interested in running something in Flask, you could create a virtual environment and test the whole shebang, but in my opinion that is THE HARDEST way to do it.
When I built my site installing Redis locally, setting the port and then depositing some data inside it with an appropriate key was essential. I did all of my development in iPython (jupyter) notebooks so that I could test the functions and interactions with Redis before adding the confounding layer of Flask.
Then you set up a flawless template, solid HTML around it and CSS to style the site. If it works without data as an html page, then you move on to the python part of Flask.
Solidify the Flask directories. Make sure that you house them in a virtual environment so that you can call them from your browser and it will treat your virtual environment as a server.
You create your app.py application. I created each one of the page functions one at a time. tested to see that it was properly pushing the variables to post on the page and calling the right template. After you get on up and running right, with photos and data, then at the next page's template, using #app.route
Take if very slow, one piece at a time with debugging on so that you can see where when and how you are going wrong. You will only get the site to run with redis server on and your virtual environment running.
Then you will have to shut down the VE to edit and reboot to test. At first it is awful, but over time it becomes rote.
EDIT :
If you really want to test just the route, then make an app.py with just the #app.route definition and return just the page (the template you are calling). You can break testing into pieces as small as you like, but you have to be sure that the quanta you pick are executable as either a python script in a notebook or commandline execution or as a compact functional self-contained website....unless you use the package I mentioned in the comment: Flask Unit Testing Applications
And you need to create REAL Redis connections or you will error out.

Using Django outside of view.py

I have a twisted based script running that is managing IO, monitoring serial inputs, writing logs etc. It uses Twisted to run events every minute and every hour as well as interrupt on serial traffic.
Can Django be used to provide an interface for this, for example taking live values and display them using
#python code generating value1 and value2
def displayValues(request):
context = {
'value1':value1,
'value2':value2
}
return render(request, 'interface.html', context)
The obvious issue is that this python file doesn't live in the Django file setup and so the URL call wouldn't know where to look or how to call the displayValues function.
An additional feature I might look to is to write the IO values in to a mysql database through Django as it is already setup.
I understand Django from a simple databases application point of view but this is not something I've come across online and I might be moving outside of the scope of Django.
I've seen this but it is more to do with using the Model outside of the standard setup. Using Django database layer outside of Django?
Is this possible?
Thanks!
Why do you need Django for such a simple use case?
For simple Http requests you can you the included Python tool:
https://docs.python.org/2/library/simplehttpserver.html

Create New Model Instance with API Call in Django

I'm unsure how to approach this problem in general in my Django app:
I need to make a call to an API every n days. I can make this call and fetch the data required via Python, but where exactly should I put the code?
Do I put the code in a specific view and then map the view to a URL and have that URL called whenever I want to create new model instances based on the API call?
Or am I approaching this the wrong way?
The way I usually do this is with a combination of custom Django-admin commands, and then run them wit a scheduled Cron job
You can run your custom commands in the same way as you would run the default ones:
python manage.py <your_command_name> <your_command_arguments>
Sounds like you are trying to have a schedule-able job. Celery works well for this sort of situation.
You would create a task that runs every N days. In that task, you would put your code that calls the API and processing the response as necessary.
Reference:
Celery Periodic Tasks
Do I put the code in a specific view
a django view is a callable that must accept an HTTP request and return an HTTP response, so unless you need to be able to call your code thru HTTP there's no point in using a view at all, and even if you want to have a view exposing this code it doesn't mean the code doing the API call etc has to live in the view.
Remember that a "django app" is basically a Python package, so beside the django-specific stuff (views, models etc) you can put any module you want and have your views, custom commands etc call on these modules. So just write a module for your API client etc with a function doing the fetch / create model instance / whatever job, and then call this function from where it makes sense (view, custom command called by a cron job, celery task, whatever).

Force django cache updating

I have a site with pages hierarchy, which shows tables based on complex calculation from values stored in database. That database can be updated by external application. During to long time of calculation, I prefer to use per-page caching to show result pages (I'm using DatabaseCache). After external updating of database, I can clear cache, but I want to refresh it (create new one instead) before user's visit (assuming that user will see only next cached version).
Is any way in Django to force refreshing cache by external application?
Comes to mind only calling some Django code from external app, which will call all the pages urls one-by-one, after cache deleting..
Will be grateful for your advice anyway
in your external script you can do
import django
from django.core.cache import cache
django.setup() # Needed to make django ready from the external script
cache.clear() # Flush all the old cache entry.

global counter in Django Application?

I was wondering if there is "global counter" in Django application, like the way I store "global counter" in Servlet Context scope in Tomcat.
something like
getServletContext().getAttribute("counter");
counter++;
When you write a django application (or any wsgi application, for that matter), you don't know beforehand if your application will end up running standalone on a single server, or multithreaded, or multiprocessed, or even in multiple separate machines as part of a load balancing strategy.
If you're going to make the constraint "my application only works on single-process servers" then you can use something like this:
from django import settings
settings.counter += 1
However that constraint is often not feasible. So you must use external storage to your counter.
If you want to keep it on memory, maybe a memcached
Maybe you just log the requests to this view. So when you want the counter just count the number of entries in the log.
The log could be file-based, or it could be a table in the database, just define a new model on your models.py.

Categories