Get blinker signal's receivers names

| Comments
from unittest import TestCase
from app.main import init_app
from app.signals import my_signal

class SignalTests(TestCase):

    def setUp(self):

    def test_signal_is_connected_to_my_receiver(self)
        receivers = [r().__name__ for r in signal.receivers.values()]
        self.assertIn('my_receiver', receivers)

Easy charts in python app with plotly

| Comments

An example how to add a chart to Flask app with plotly library:

def get_chart_data():
    return mongo_db['item'].aggregate([
        {'$sort': {'date': 1}},
        {'$group': {
            '_id': {'year': {'$year': '$date'}, 'month': {'$month': '$date'}},
            'num': {'$sum': 1}
        {'$project': {
            'date': {'$dateFromParts' : {'year': '$_id.year', 'month': '$_id.month'}},
            'num': '$num'
        {'$sort': {'date': 1}}

def get_chart():
    data = list(get_chart_data())
    layout = plotly.graph_objs.Layout(title='Items by month')
    scatter_data = [
            x=[d['date'] for d in data], 
            y=[d['num'] for d in data]
    fig = plotly.graph_objs.Figure(data=scatter_data, layout=layout)
    return plotly.offline.plot(fig, include_plotlyjs=True, output_type='div')

def chart():
    return render_template('chart.html', chart=get_chart())

Jinja template:

{{ chart|safe }}

For jupyter notebook it will be:

from plotly.offline import init_notebook_mode, iplot

Mongoengine as_pymongo performance

| Comments

When you need to get only several fields from the list of complex objects, it works much faster with as_pymongo function.

In my situation I have a 16x increase:

%timeit list(SomeObject.objects.scalar('id')[0:500])
# 129 ms ± 11 ms per loop

%timeit list(o['_id'] for o in SomeObject.objects.scalar('id')[0:500].as_pymongo())
# 7.98 ms ± 849 µs per loop

Maximum number of client connections in Flask-SocketIO with Eventlet

| Comments

It’s not mentioned in the docs for Flask-SocketIO that Eventlet has an option max_size which by default limits the maximum number of client connections opened at any time to 1024. There is no way to pass it through flask run command, so the application should be run with, for example:

if __name__ == '__main__':, host='', port='8080', max_size=int(os.environ.get('EVENTLET_MAX_SIZE', 1024)))

How to split Celery tasks file

| Comments

Suppose there is a large file, like this:

def task1():

def task2():


A good idea is to split it on the smaller files, but Celery auto_discover by default search tasks in package.tasks module, so one way to do this is to create a package tasks and import tasks from other files in

from .task1 import task1
from .task2 import task2

__all__ = ['task1', 'task2']

def task1():

from .task1 import task1

def task2():

CSRF exempt for Flask-RESTPlus API

| Comments

The @csrf.exempt method does not work with Resource methods or decorators, it should be done on Api level. Here is an example how to exclude resources from CSRF protection based on class:

def csrf_exempt_my_resource(view):
    if issubclass(view.view_class, MyResource):
        return csrf.exempt(view)
    return view

api_blueprint = Blueprint('api', __name__)
api = Api(api_blueprint, title='My API', decorators=[csrf_exempt_my_resource])

Or for all resources:

api_blueprint = Blueprint('api', __name__)
api = Api(api_blueprint, title='My Private API', decorators=[csrf.exempt])

Function as model column in Flask Admin

| Comments

I like the idea about separation of business logic from models and views into services. There are more details in these slides from the EuroPython talk.

Usually in Flask-Admin for a new column a new method with @property decorator is added and the model becomes fat. Also it’s not good to put something with queries in property. Another way is to put this function to the services and use column formatter in Flask-Admin.

def get_some_data(model_id)
    """Function in services."""
    return RelatedModel.objects(model=model_id).count()

class MyModelView(ModelView):
    column_formatters = {
        'related_model_count': lambda view, context, model, name: get_some_data(

    column_list = [..., 'related_model_count']
1/4 »