SlideShare a Scribd company logo
1 of 41
Intelligent Security Automation hexadite.com
Real-life Django ORM
Presentation for PyWeb-IL #66, Monday, July 3, 2017
Intelligent Security Automation hexadite.com
What We Do
Intelligent Security Automation hexadite.com
Who We Are
Max Braitmaiere max@hexadite.com
VP of Engineering
Evgeniy (Jenya) Privalov jenya@hexadite.com
Software Developer
Intelligent Security Automation hexadite.com
Agenda
• Why Django
• Why Django ORM (for backend)
• Django DB connection handling (backend and frontend)
• Django + Postgres tweaks & tricks
• Running uTests with DB
Intelligent Security Automation hexadite.com
Why Django
Intelligent Security Automation hexadite.com
Advantages
• Written in Python.
• Complex solution for web apps
• Secure
• Batteries Included
• Predefined structures
• Community
• Good documentation
Intelligent Security Automation hexadite.com
Disadvantages
• Monolithic application
• All components are deployed together
Intelligent Security Automation hexadite.com
Why Django
ORM
Intelligent Security Automation hexadite.com
Why Django ORM
• Application design, maintainability
• Transaction management
• Cache management
• Connection management
• Community, documentation
• Code and Business-Logic reuse
Intelligent Security Automation hexadite.com
Django DB
connection
handling
Intelligent Security Automation hexadite.com
Thread Local
local() holds all connection(s)
references in a Thread local store
Connections == [processes] * [threads]
"""
from django/db/utils.py
"""
...
class ConnectionHandler(object):
def __init__(self, databases=None):
"""
databases is an optional dictionary of database definitions
(structured
like settings.DATABASES).
"""
self._databases = databases
self._connections = local()
...
Intelligent Security Automation hexadite.com
Web Request Lifecycle
close_if_unusable_or_obsolete()
• if unrecoverable errors have
occurred
• if it outlived its maximum age
(CONN_MAX_AGE)
called on request started / finished
"""
from django/db/__init__.py
"""
...
# Register an event to reset transaction state and close connections past
# their lifetime.
def close_old_connections(**kwargs):
for conn in connections.all():
conn.close_if_unusable_or_obsolete()
signals.request_started.connect(close_old_connections)
signals.request_finished.connect(close_old_connections)
Intelligent Security Automation hexadite.com
Regular Backend Implications
• Any use of the ORM to work with data, will create a Thread
local connection
• Long running services don’t operate within a “request” == no
call to close_if_unusable_or_obsolete()
Intelligent Security Automation hexadite.com
The Transaction Block
from django.db import transaction
with transaction.atomic():
# query and/or change data...
with transaction.atomic():
# runs an “inner” transaction
Used to define the beginning and end of a
transaction.
We can leverage this to define a clear “scope
of work” in code.
NOTE: With async, don’t yield within a
transaction block
Intelligent Security Automation hexadite.com
Enter ClosingAtomic
"""
from (our) transaction.py
"""
class _ClosingAtomic(object):
def __init__(self, base_atomic):
self._atomic = base_atomic
def __enter__(self):
self._atomic.__enter__()
def __exit__(self, exc_type, exc_val, exc_tb):
# end actual transaction
self._atomic.__exit__(exc_type, exc_val, exc_tb)
# get connection
conn = django.db.transaction.get_connection(self._atomic.using)
# if db connection is not closed, and this is the last transaction - close connection
if conn.connection is not None and not conn.in_atomic_block:
conn.close()
Intelligent Security Automation hexadite.com
Our Own “Atomic”
"""
from (our) transaction.py
"""
class _ClosingAtomic(object):
"""
Open/Closes an atomic transaction, on last transaction close - terminates the DB connection.
"""
def closing_atomic(using=None, savepoint=True):
"""
...
"""
return _ClosingAtomic(django.db.transaction.atomic(using=using, savepoint=savepoint))
# default atomic transaction with closing
atomic = closing_atomic
Intelligent Security Automation hexadite.com
Enter Pooling
• Django middleware (connection pooling within a process)
• External Connection pooling
Intelligent Security Automation hexadite.com
PgBouncer (https://pgbouncer.github.io)
“pool_mode” Specifies when a server connection can be reused by other clients.
• session: Server is released back to pool after client disconnects. Default.
• transaction: Server is released back to pool after transaction finishes.
• statement: Server is released back to pool after query finishes.
PostgreSQL
PgBouncerApps
hundreds fixed ~40
Intelligent Security Automation hexadite.com
Enter CleanupAtomic
"""
from (our) transaction.py
"""
class _CleanupAtomic(object):
...
def __enter__(self):
conn = django.db.transaction.get_connection(self._atomic.using)
# if this is the first transaction block - cleanup connection if unusable
if not conn.in_atomic_block:
conn.close_if_unusable_or_obsolete()
self._atomic.__enter__()
def __exit__(self, exc_type, exc_val, exc_tb):
self._atomic.__exit__(exc_type, exc_val, exc_tb)
conn = django.db.transaction.get_connection(self._atomic.using)
# if this is the last transaction block - cleanup connection if unusable
if not conn.in_atomic_block:
conn.close_if_unusable_or_obsolete()
Intelligent Security Automation hexadite.com
Putting It All Together
def cleanup_atomic(using=None, savepoint=True):
return _CleanupAtomic(django.db.transaction.atomic(...))
# default atomic transaction with cleanup
atomic = cleanup_atomic
...
with atomic():
# exiting this context will trigger the “cleanup”
with atomic():
# exiting this context affects inner transaction (no “cleanup”)
• PgBouncer can “multiplex” many
connections passing through only X
transactions
• No constant connection closing
• Uses the CONN_MAX_AGE if set
• Usage is applicable for request handling
and long running services
• Default Django autocommit is not
destructive
Intelligent Security Automation hexadite.com
Django
Postgres
tweaks & tricks
Intelligent Security Automation hexadite.com
Text Indexing (PostgreSQL)
"""
from django.db.backends.postgresql.schema
"""
class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
def _create_like_index_sql(self, model, field):
…
if db_type.startswith('varchar'):
return self._create_index_sql(..., suffix='_like')
elif db_type.startswith('text'):
return self._create_index_sql(..., suffix='_like')
...
def _alter_field(self, model, old_field, new_field, old_type, new_type,
old_db_params, new_db_params, strict=False):
...
self._create_like_index_sql(model, new_field)
...
• Fields with database column
types varchar and text need a
second index that specifies their
operator class , which is needed
when performing correct LIKE
operations, outside the C locale
Intelligent Security Automation hexadite.com
Text Indexing (Custom Fields)
"""
from (our) fields.py
"""
class TextFieldIndexControlled(TextField):
...
class CharFieldIndexControlled(CharField):
def __init__(self, *args, **kwargs):
self.like_index = kwargs.pop('like_index', True)
super(CharFieldIndexControlled, self).__init__(*args, **kwargs)
def deconstruct(self):
name, path, args, kwargs = super(CharFieldIndexControlled, self).deconstruct()
# Only include 'like_index' if it's not the default
if self.like_index != True:
kwargs['like_index'] = self.like_index
return name, path, args, kwargs
Intelligent Security Automation hexadite.com
Text Indexing (SchemaEditor)
"""
from (our) schema.py
"""
class DatabaseSchemaEditor(schema.DatabaseSchemaEditor):
def _create_like_index_sql(self, model, field):
if not getattr(field, 'like_index', True):
# if like_index is False explicitly , don't create
return None
return super(DatabaseSchemaEditor, self)._create_like_index_sql(model, field)
def _alter_field(self, model, old_field, new_field, old_type, new_type,
old_db_params, new_db_params, strict=False):
...
# ADD YOU LOGIC HERE
_create_like_index_sql(..)
...
• SchemaEditor class is
responsible for emitting
schema-changing
statements to the
database
Intelligent Security Automation hexadite.com
Text Indexing (DatabaseWrapper)
"""
from (our) base.py
"""
from django.db.backends.postgresql_psycopg2 import base
from schema import DatabaseSchemaEditor
class DatabaseWrapper(base.DatabaseWrapper):
SchemaEditorClass = DatabaseSchemaEditor # our schema editor
DataBaseWrapper is a class that
represent the DB connection in Django
Intelligent Security Automation hexadite.com
Text Indexing (Database Engine)
"""
from (our) settings.py
"""
# https://docs.djangoproject.com/en/1.10/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'our.backends.postgresql_psycopg2',
'HOST': '127.0.0.1',
'NAME': 'db',
'USER': 'user',
'PASSWORD': 'password',
'CONN_MAX_AGE': 300,
},
}
Intelligent Security Automation hexadite.com
Bulk delete
Django needs to fetch objects into memory to send signals and handle cascades. However, if there are no cascades and no signals,
then Django may take a fast-path and delete objects without fetching into memory. For large deletes this can result in significantly
reduced memory usage.
https://docs.djangoproject.com/en/1.10/ref/models/querysets/#delete
Intelligent Security Automation hexadite.com
QuerySets Iterator
"""
from (our) iterators.py
"""
def querysets_bulk_iterator(qs, batchsize=500, gc_collect=True, nullify_each_iteration=False):
start = 0
end = batchsize
last_element = max(qs.count(), batchsize)
while start <= last_element:
if nullify_each_iteration:
yield qs.order_by('pk')[:batchsize]
else:
yield qs.order_by('pk')[start:end]
start += batchsize
end += batchsize
if gc_collect:
gc.collect()
raise StopIteration
• gc.collect() explicitly tell to
the garbage collector start to
collect.
• when done with each yielded
queryset need to call del() on
the queryset
Intelligent Security Automation hexadite.com
Foreign Keys
class User(models.Model):
name = models.CharField()
class Order(models.Model):
user = models.ForeignKey(User, related_name="orders", db_constraint=False, db_index=False)
• Maintain integrity and
consistency of data
• Dramatic slow down on writes
• Django has out of the box
solution db_constraint=False
• Indexing may also not be
required db_index=False
Intelligent Security Automation hexadite.com
PostgresSQL Tunings
• models.PositiveIntegerField
• Find useless, unused indexes and delete them.
• Use “ANALYZE” and “EXPLAIN” to optimize PostgreSQL queries.
• Vacuum database.
• Analyse database.
• Tune PostgreSQL server configuration.
Intelligent Security Automation hexadite.com
Running
uTests with
DB
Intelligent Security Automation hexadite.com
Best Practice
• Regular utest: mock data calls, will allow best performance
• Django utest: Use in memory sqlite, performs all DB
operations much faster.
What if our DAL/BL uses some custom capabilities?
• Array Fields
• JSON Field query
• etc
Intelligent Security Automation hexadite.com
Test DB
Use a predefined suffix:
• Allows isolation
• Multiple tests can run on
same machine
"""
from (test) settings.py
"""
import os
TEST_DB_SUFFIX = os.getenv( 'OUR_TEST_DB_SUFFIX', '')
DATABASES = {
'default': {
'ENGINE': 'our.backends.postgresql_psycopg2',
'HOST': '127.0.0.1',
'PORT': '5432',
'NAME': 'db' + TEST_DB_SUFFIX,
'TEST': {'NAME': 'test_db' + TEST_DB_SUFFIX},
'USER': 'user',
'PASSWORD': 'password',
'CONN_MAX_AGE': 300, # persistent connections for 5
minutes
},
}
Intelligent Security Automation hexadite.com
Q&A
Thank You :)
max@hexadite.com
jenya@hexadite.com
Intelligent Security Automation hexadite.com
Optional Slides
Intelligent Security Automation hexadite.com
Delayed
Migrations
Intelligent Security Automation hexadite.com
Data Migration
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations
def update_usernames(apps, schema_editor):
User = apps.get_model('app', 'User')
User.objects.update(name=Upper(F('name')))
class Migration(migrations.Migration):
dependencies = [
('app', '0001_initial'),
]
operations = [
migrations.RunPython(update_usernames),
]
• Data Migration - change or
loading of data. Should be
done manually.
• For large data sets could take a
lot of time.
Intelligent Security Automation hexadite.com
Delayed Migration
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations
def update_usernames_delayed(apps, schema_editor):
User = apps.get_model('app', 'User')
User.objects.update(name=Upper(F('name')))
class Migration(migrations.Migration):
dependencies = [
('app', '0001_initial'),
]
operations = [
# REGULAR DJANGO MIGRATION OPERATIONS
]
delayed_operations = [
migrations.RunPython(update_usernames_delayed),
]
• delayed_operations won’t
run with regular operations
Intelligent Security Automation hexadite.com
Delayed Migration (Migrate Command)
MIGRATIONS_DUMPS_PATH = os.path.join(os.path.dirname(__file__), 'migrations')
MIGRATIONS_PATH = os.path.join(os.path.dirname(__file__), 'migrations',
'delayed_migrations.json')
class Command(CommandMigration):
def handle(self, *args, **options):
self.delayed_migrations_to_run = []
super(Command, self).handle(*args, **options)
if self.delayed_migrations_to_run:
with open(MIGRATIONS_PATH, 'wb') as f:
json.dump(self.delayed_migrations_to_run, f)
def migration_progress_callback(self, action, migration=None, fake=False):
if action == 'apply_success' and not fake:
if hasattr(migration, 'delayed_operations'):
self.delayed_migrations_to_run.append("%s.%s" % (migration.app_label, migration.name))
return super(Command, self).migration_progress_callback(action, migration, fake)
• Add custom migrate command
which will be use
delayed_operations
• Run all your migrations with
this command
Intelligent Security Automation hexadite.com
Delayed Migration (Command)
class Command(CommandMigration):
def handle(self, *args, **options):
self.executor = MigrationExecutor(self.connection, self.migration_progress_callback)
state = ProjectState(real_apps=list(self.loader.unmigrated_apps))
states = self.build_migration_states(plan, state)
try:
for migration in plan:
self.apply_migration(states[migration], migration)
plan.remove(migration)
finally:
self.update_migrations_state(plan)
• Run custom “delayed”
migration when you need
Intelligent Security Automation hexadite.com
Delayed Migration (Usage)
1. manage.py custom_migrate
2. manage.py custom_delayed_migrate

More Related Content

What's hot

Ten useful JavaScript tips & best practices
Ten useful JavaScript tips & best practicesTen useful JavaScript tips & best practices
Ten useful JavaScript tips & best practicesAnkit Rastogi
 
Imagine a world without mocks
Imagine a world without mocksImagine a world without mocks
Imagine a world without mockskenbot
 
JavaScript and the AST
JavaScript and the ASTJavaScript and the AST
JavaScript and the ASTJarrod Overson
 
Lenses and Prisms in Swift - Elviro Rocca - Codemotion Rome 2018
Lenses and Prisms in Swift - Elviro Rocca - Codemotion Rome 2018 Lenses and Prisms in Swift - Elviro Rocca - Codemotion Rome 2018
Lenses and Prisms in Swift - Elviro Rocca - Codemotion Rome 2018 Codemotion
 
Clean Code Development
Clean Code DevelopmentClean Code Development
Clean Code DevelopmentPeter Gfader
 
New methods for exploiting ORM injections in Java applications
New methods for exploiting ORM injections in Java applicationsNew methods for exploiting ORM injections in Java applications
New methods for exploiting ORM injections in Java applicationsMikhail Egorov
 
Appsec usa2013 js_libinsecurity_stefanodipaola
Appsec usa2013 js_libinsecurity_stefanodipaolaAppsec usa2013 js_libinsecurity_stefanodipaola
Appsec usa2013 js_libinsecurity_stefanodipaoladrewz lin
 
Android programming -_pushing_the_limits
Android programming -_pushing_the_limitsAndroid programming -_pushing_the_limits
Android programming -_pushing_the_limitsDroidcon Berlin
 
Testing most things in JavaScript - LeedsJS 31/05/2017
Testing most things in JavaScript - LeedsJS 31/05/2017Testing most things in JavaScript - LeedsJS 31/05/2017
Testing most things in JavaScript - LeedsJS 31/05/2017Colin Oakley
 
Typed? Dynamic? Both! Cross-platform DSLs in C#
Typed? Dynamic? Both! Cross-platform DSLs in C#Typed? Dynamic? Both! Cross-platform DSLs in C#
Typed? Dynamic? Both! Cross-platform DSLs in C#Vagif Abilov
 
Policy Injection in ASP.NET using Enterprise Library 3.0
Policy Injection in ASP.NET using Enterprise Library 3.0Policy Injection in ASP.NET using Enterprise Library 3.0
Policy Injection in ASP.NET using Enterprise Library 3.0PhilWinstanley
 
Fixing Magento Core for Better Performance - Ivan Chepurnyi
Fixing Magento Core for Better Performance - Ivan ChepurnyiFixing Magento Core for Better Performance - Ivan Chepurnyi
Fixing Magento Core for Better Performance - Ivan ChepurnyiMeet Magento Spain
 
IndexedDB - Querying and Performance
IndexedDB - Querying and PerformanceIndexedDB - Querying and Performance
IndexedDB - Querying and PerformanceParashuram N
 
Re-Design with Elixir/OTP
Re-Design with Elixir/OTPRe-Design with Elixir/OTP
Re-Design with Elixir/OTPMustafa TURAN
 

What's hot (20)

Scala and Spring
Scala and SpringScala and Spring
Scala and Spring
 
Ten useful JavaScript tips & best practices
Ten useful JavaScript tips & best practicesTen useful JavaScript tips & best practices
Ten useful JavaScript tips & best practices
 
Imagine a world without mocks
Imagine a world without mocksImagine a world without mocks
Imagine a world without mocks
 
JavaScript and the AST
JavaScript and the ASTJavaScript and the AST
JavaScript and the AST
 
Lenses and Prisms in Swift - Elviro Rocca - Codemotion Rome 2018
Lenses and Prisms in Swift - Elviro Rocca - Codemotion Rome 2018 Lenses and Prisms in Swift - Elviro Rocca - Codemotion Rome 2018
Lenses and Prisms in Swift - Elviro Rocca - Codemotion Rome 2018
 
Deep dive into Oracle ADF
Deep dive into Oracle ADFDeep dive into Oracle ADF
Deep dive into Oracle ADF
 
Clean Code Development
Clean Code DevelopmentClean Code Development
Clean Code Development
 
New methods for exploiting ORM injections in Java applications
New methods for exploiting ORM injections in Java applicationsNew methods for exploiting ORM injections in Java applications
New methods for exploiting ORM injections in Java applications
 
Appsec usa2013 js_libinsecurity_stefanodipaola
Appsec usa2013 js_libinsecurity_stefanodipaolaAppsec usa2013 js_libinsecurity_stefanodipaola
Appsec usa2013 js_libinsecurity_stefanodipaola
 
Frontin like-a-backer
Frontin like-a-backerFrontin like-a-backer
Frontin like-a-backer
 
Android programming -_pushing_the_limits
Android programming -_pushing_the_limitsAndroid programming -_pushing_the_limits
Android programming -_pushing_the_limits
 
Hidden rocks in Oracle ADF
Hidden rocks in Oracle ADFHidden rocks in Oracle ADF
Hidden rocks in Oracle ADF
 
Testing most things in JavaScript - LeedsJS 31/05/2017
Testing most things in JavaScript - LeedsJS 31/05/2017Testing most things in JavaScript - LeedsJS 31/05/2017
Testing most things in JavaScript - LeedsJS 31/05/2017
 
Magento Indexes
Magento IndexesMagento Indexes
Magento Indexes
 
Con5623 pdf 5623_001
Con5623 pdf 5623_001Con5623 pdf 5623_001
Con5623 pdf 5623_001
 
Typed? Dynamic? Both! Cross-platform DSLs in C#
Typed? Dynamic? Both! Cross-platform DSLs in C#Typed? Dynamic? Both! Cross-platform DSLs in C#
Typed? Dynamic? Both! Cross-platform DSLs in C#
 
Policy Injection in ASP.NET using Enterprise Library 3.0
Policy Injection in ASP.NET using Enterprise Library 3.0Policy Injection in ASP.NET using Enterprise Library 3.0
Policy Injection in ASP.NET using Enterprise Library 3.0
 
Fixing Magento Core for Better Performance - Ivan Chepurnyi
Fixing Magento Core for Better Performance - Ivan ChepurnyiFixing Magento Core for Better Performance - Ivan Chepurnyi
Fixing Magento Core for Better Performance - Ivan Chepurnyi
 
IndexedDB - Querying and Performance
IndexedDB - Querying and PerformanceIndexedDB - Querying and Performance
IndexedDB - Querying and Performance
 
Re-Design with Elixir/OTP
Re-Design with Elixir/OTPRe-Design with Elixir/OTP
Re-Design with Elixir/OTP
 

Similar to Hexadite Real Life Django ORM

Safe Clearing of Private Data
Safe Clearing of Private DataSafe Clearing of Private Data
Safe Clearing of Private DataPVS-Studio
 
How my team is applying JS framework for PHP projects.
How my team is applying JS framework for PHP projects.How my team is applying JS framework for PHP projects.
How my team is applying JS framework for PHP projects.Damon Hung Tran
 
High Performance Django 1
High Performance Django 1High Performance Django 1
High Performance Django 1DjangoCon2008
 
High Performance Django
High Performance DjangoHigh Performance Django
High Performance DjangoDjangoCon2008
 
Building Content Recommendation Systems using MXNet Gluon
Building Content Recommendation Systems using MXNet GluonBuilding Content Recommendation Systems using MXNet Gluon
Building Content Recommendation Systems using MXNet GluonApache MXNet
 
Django - Know Your Namespace: Middleware
Django - Know Your Namespace: MiddlewareDjango - Know Your Namespace: Middleware
Django - Know Your Namespace: Middlewarehowiworkdaily
 
Working Effectively With Legacy Code
Working Effectively With Legacy CodeWorking Effectively With Legacy Code
Working Effectively With Legacy CodeNaresh Jain
 
Letswift18 워크숍#1 스위프트 클린코드와 코드리뷰
Letswift18 워크숍#1 스위프트 클린코드와 코드리뷰Letswift18 워크숍#1 스위프트 클린코드와 코드리뷰
Letswift18 워크숍#1 스위프트 클린코드와 코드리뷰Jung Kim
 
Тестирование и Django
Тестирование и DjangoТестирование и Django
Тестирование и DjangoMoscowDjango
 
How to write maintainable code without tests
How to write maintainable code without testsHow to write maintainable code without tests
How to write maintainable code without testsJuti Noppornpitak
 
Testing Ext JS and Sencha Touch
Testing Ext JS and Sencha TouchTesting Ext JS and Sencha Touch
Testing Ext JS and Sencha TouchMats Bryntse
 
Node.js for enterprise - JS Conference
Node.js for enterprise - JS ConferenceNode.js for enterprise - JS Conference
Node.js for enterprise - JS ConferenceTimur Shemsedinov
 
TransmogrifAI - Automate Machine Learning Workflow with the power of Scala an...
TransmogrifAI - Automate Machine Learning Workflow with the power of Scala an...TransmogrifAI - Automate Machine Learning Workflow with the power of Scala an...
TransmogrifAI - Automate Machine Learning Workflow with the power of Scala an...Chetan Khatri
 
XebiCon'17 : Faites chauffer les neurones de votre Smartphone avec du Deep Le...
XebiCon'17 : Faites chauffer les neurones de votre Smartphone avec du Deep Le...XebiCon'17 : Faites chauffer les neurones de votre Smartphone avec du Deep Le...
XebiCon'17 : Faites chauffer les neurones de votre Smartphone avec du Deep Le...Publicis Sapient Engineering
 
JVM Mechanics: A Peek Under the Hood
JVM Mechanics: A Peek Under the HoodJVM Mechanics: A Peek Under the Hood
JVM Mechanics: A Peek Under the HoodAzul Systems Inc.
 
Automate ml workflow_transmogrif_ai-_chetan_khatri_berlin-scala
Automate ml workflow_transmogrif_ai-_chetan_khatri_berlin-scalaAutomate ml workflow_transmogrif_ai-_chetan_khatri_berlin-scala
Automate ml workflow_transmogrif_ai-_chetan_khatri_berlin-scalaChetan Khatri
 
DjangoCon 2010 Scaling Disqus
DjangoCon 2010 Scaling DisqusDjangoCon 2010 Scaling Disqus
DjangoCon 2010 Scaling Disquszeeg
 
elm-d3 @ NYC D3.js Meetup (30 June, 2014)
elm-d3 @ NYC D3.js Meetup (30 June, 2014)elm-d3 @ NYC D3.js Meetup (30 June, 2014)
elm-d3 @ NYC D3.js Meetup (30 June, 2014)Spiros
 
Internet and Web Technology (CLASS-9) [React.js] | NIC/NIELIT Web Technology
Internet and Web Technology (CLASS-9) [React.js] | NIC/NIELIT Web TechnologyInternet and Web Technology (CLASS-9) [React.js] | NIC/NIELIT Web Technology
Internet and Web Technology (CLASS-9) [React.js] | NIC/NIELIT Web TechnologyAyes Chinmay
 

Similar to Hexadite Real Life Django ORM (20)

Safe Clearing of Private Data
Safe Clearing of Private DataSafe Clearing of Private Data
Safe Clearing of Private Data
 
How my team is applying JS framework for PHP projects.
How my team is applying JS framework for PHP projects.How my team is applying JS framework for PHP projects.
How my team is applying JS framework for PHP projects.
 
High Performance Django 1
High Performance Django 1High Performance Django 1
High Performance Django 1
 
High Performance Django
High Performance DjangoHigh Performance Django
High Performance Django
 
Building Content Recommendation Systems using MXNet Gluon
Building Content Recommendation Systems using MXNet GluonBuilding Content Recommendation Systems using MXNet Gluon
Building Content Recommendation Systems using MXNet Gluon
 
Django - Know Your Namespace: Middleware
Django - Know Your Namespace: MiddlewareDjango - Know Your Namespace: Middleware
Django - Know Your Namespace: Middleware
 
Working Effectively With Legacy Code
Working Effectively With Legacy CodeWorking Effectively With Legacy Code
Working Effectively With Legacy Code
 
Letswift18 워크숍#1 스위프트 클린코드와 코드리뷰
Letswift18 워크숍#1 스위프트 클린코드와 코드리뷰Letswift18 워크숍#1 스위프트 클린코드와 코드리뷰
Letswift18 워크숍#1 스위프트 클린코드와 코드리뷰
 
Тестирование и Django
Тестирование и DjangoТестирование и Django
Тестирование и Django
 
How to write maintainable code without tests
How to write maintainable code without testsHow to write maintainable code without tests
How to write maintainable code without tests
 
Testing Ext JS and Sencha Touch
Testing Ext JS and Sencha TouchTesting Ext JS and Sencha Touch
Testing Ext JS and Sencha Touch
 
Node.js for enterprise - JS Conference
Node.js for enterprise - JS ConferenceNode.js for enterprise - JS Conference
Node.js for enterprise - JS Conference
 
TransmogrifAI - Automate Machine Learning Workflow with the power of Scala an...
TransmogrifAI - Automate Machine Learning Workflow with the power of Scala an...TransmogrifAI - Automate Machine Learning Workflow with the power of Scala an...
TransmogrifAI - Automate Machine Learning Workflow with the power of Scala an...
 
XebiCon'17 : Faites chauffer les neurones de votre Smartphone avec du Deep Le...
XebiCon'17 : Faites chauffer les neurones de votre Smartphone avec du Deep Le...XebiCon'17 : Faites chauffer les neurones de votre Smartphone avec du Deep Le...
XebiCon'17 : Faites chauffer les neurones de votre Smartphone avec du Deep Le...
 
JVM Mechanics: A Peek Under the Hood
JVM Mechanics: A Peek Under the HoodJVM Mechanics: A Peek Under the Hood
JVM Mechanics: A Peek Under the Hood
 
Automate ml workflow_transmogrif_ai-_chetan_khatri_berlin-scala
Automate ml workflow_transmogrif_ai-_chetan_khatri_berlin-scalaAutomate ml workflow_transmogrif_ai-_chetan_khatri_berlin-scala
Automate ml workflow_transmogrif_ai-_chetan_khatri_berlin-scala
 
DjangoCon 2010 Scaling Disqus
DjangoCon 2010 Scaling DisqusDjangoCon 2010 Scaling Disqus
DjangoCon 2010 Scaling Disqus
 
elm-d3 @ NYC D3.js Meetup (30 June, 2014)
elm-d3 @ NYC D3.js Meetup (30 June, 2014)elm-d3 @ NYC D3.js Meetup (30 June, 2014)
elm-d3 @ NYC D3.js Meetup (30 June, 2014)
 
Django at Scale
Django at ScaleDjango at Scale
Django at Scale
 
Internet and Web Technology (CLASS-9) [React.js] | NIC/NIELIT Web Technology
Internet and Web Technology (CLASS-9) [React.js] | NIC/NIELIT Web TechnologyInternet and Web Technology (CLASS-9) [React.js] | NIC/NIELIT Web Technology
Internet and Web Technology (CLASS-9) [React.js] | NIC/NIELIT Web Technology
 

Recently uploaded

Introduction to IEEE STANDARDS and its different types.pptx
Introduction to IEEE STANDARDS and its different types.pptxIntroduction to IEEE STANDARDS and its different types.pptx
Introduction to IEEE STANDARDS and its different types.pptxupamatechverse
 
SPICE PARK APR2024 ( 6,793 SPICE Models )
SPICE PARK APR2024 ( 6,793 SPICE Models )SPICE PARK APR2024 ( 6,793 SPICE Models )
SPICE PARK APR2024 ( 6,793 SPICE Models )Tsuyoshi Horigome
 
chaitra-1.pptx fake news detection using machine learning
chaitra-1.pptx  fake news detection using machine learningchaitra-1.pptx  fake news detection using machine learning
chaitra-1.pptx fake news detection using machine learningmisbanausheenparvam
 
HARMONY IN THE NATURE AND EXISTENCE - Unit-IV
HARMONY IN THE NATURE AND EXISTENCE - Unit-IVHARMONY IN THE NATURE AND EXISTENCE - Unit-IV
HARMONY IN THE NATURE AND EXISTENCE - Unit-IVRajaP95
 
the ladakh protest in leh ladakh 2024 sonam wangchuk.pptx
the ladakh protest in leh ladakh 2024 sonam wangchuk.pptxthe ladakh protest in leh ladakh 2024 sonam wangchuk.pptx
the ladakh protest in leh ladakh 2024 sonam wangchuk.pptxhumanexperienceaaa
 
(MEERA) Dapodi Call Girls Just Call 7001035870 [ Cash on Delivery ] Pune Escorts
(MEERA) Dapodi Call Girls Just Call 7001035870 [ Cash on Delivery ] Pune Escorts(MEERA) Dapodi Call Girls Just Call 7001035870 [ Cash on Delivery ] Pune Escorts
(MEERA) Dapodi Call Girls Just Call 7001035870 [ Cash on Delivery ] Pune Escortsranjana rawat
 
Call Girls Service Nagpur Tanvi Call 7001035870 Meet With Nagpur Escorts
Call Girls Service Nagpur Tanvi Call 7001035870 Meet With Nagpur EscortsCall Girls Service Nagpur Tanvi Call 7001035870 Meet With Nagpur Escorts
Call Girls Service Nagpur Tanvi Call 7001035870 Meet With Nagpur EscortsCall Girls in Nagpur High Profile
 
HARDNESS, FRACTURE TOUGHNESS AND STRENGTH OF CERAMICS
HARDNESS, FRACTURE TOUGHNESS AND STRENGTH OF CERAMICSHARDNESS, FRACTURE TOUGHNESS AND STRENGTH OF CERAMICS
HARDNESS, FRACTURE TOUGHNESS AND STRENGTH OF CERAMICSRajkumarAkumalla
 
(RIA) Call Girls Bhosari ( 7001035870 ) HI-Fi Pune Escorts Service
(RIA) Call Girls Bhosari ( 7001035870 ) HI-Fi Pune Escorts Service(RIA) Call Girls Bhosari ( 7001035870 ) HI-Fi Pune Escorts Service
(RIA) Call Girls Bhosari ( 7001035870 ) HI-Fi Pune Escorts Serviceranjana rawat
 
APPLICATIONS-AC/DC DRIVES-OPERATING CHARACTERISTICS
APPLICATIONS-AC/DC DRIVES-OPERATING CHARACTERISTICSAPPLICATIONS-AC/DC DRIVES-OPERATING CHARACTERISTICS
APPLICATIONS-AC/DC DRIVES-OPERATING CHARACTERISTICSKurinjimalarL3
 
VIP Call Girls Service Kondapur Hyderabad Call +91-8250192130
VIP Call Girls Service Kondapur Hyderabad Call +91-8250192130VIP Call Girls Service Kondapur Hyderabad Call +91-8250192130
VIP Call Girls Service Kondapur Hyderabad Call +91-8250192130Suhani Kapoor
 
Architect Hassan Khalil Portfolio for 2024
Architect Hassan Khalil Portfolio for 2024Architect Hassan Khalil Portfolio for 2024
Architect Hassan Khalil Portfolio for 2024hassan khalil
 
Gfe Mayur Vihar Call Girls Service WhatsApp -> 9999965857 Available 24x7 ^ De...
Gfe Mayur Vihar Call Girls Service WhatsApp -> 9999965857 Available 24x7 ^ De...Gfe Mayur Vihar Call Girls Service WhatsApp -> 9999965857 Available 24x7 ^ De...
Gfe Mayur Vihar Call Girls Service WhatsApp -> 9999965857 Available 24x7 ^ De...srsj9000
 
(ANJALI) Dange Chowk Call Girls Just Call 7001035870 [ Cash on Delivery ] Pun...
(ANJALI) Dange Chowk Call Girls Just Call 7001035870 [ Cash on Delivery ] Pun...(ANJALI) Dange Chowk Call Girls Just Call 7001035870 [ Cash on Delivery ] Pun...
(ANJALI) Dange Chowk Call Girls Just Call 7001035870 [ Cash on Delivery ] Pun...ranjana rawat
 
Call Girls in Nagpur Suman Call 7001035870 Meet With Nagpur Escorts
Call Girls in Nagpur Suman Call 7001035870 Meet With Nagpur EscortsCall Girls in Nagpur Suman Call 7001035870 Meet With Nagpur Escorts
Call Girls in Nagpur Suman Call 7001035870 Meet With Nagpur EscortsCall Girls in Nagpur High Profile
 
GDSC ASEB Gen AI study jams presentation
GDSC ASEB Gen AI study jams presentationGDSC ASEB Gen AI study jams presentation
GDSC ASEB Gen AI study jams presentationGDSCAESB
 
main PPT.pptx of girls hostel security using rfid
main PPT.pptx of girls hostel security using rfidmain PPT.pptx of girls hostel security using rfid
main PPT.pptx of girls hostel security using rfidNikhilNagaraju
 
MANUFACTURING PROCESS-II UNIT-2 LATHE MACHINE
MANUFACTURING PROCESS-II UNIT-2 LATHE MACHINEMANUFACTURING PROCESS-II UNIT-2 LATHE MACHINE
MANUFACTURING PROCESS-II UNIT-2 LATHE MACHINESIVASHANKAR N
 

Recently uploaded (20)

Introduction to IEEE STANDARDS and its different types.pptx
Introduction to IEEE STANDARDS and its different types.pptxIntroduction to IEEE STANDARDS and its different types.pptx
Introduction to IEEE STANDARDS and its different types.pptx
 
SPICE PARK APR2024 ( 6,793 SPICE Models )
SPICE PARK APR2024 ( 6,793 SPICE Models )SPICE PARK APR2024 ( 6,793 SPICE Models )
SPICE PARK APR2024 ( 6,793 SPICE Models )
 
chaitra-1.pptx fake news detection using machine learning
chaitra-1.pptx  fake news detection using machine learningchaitra-1.pptx  fake news detection using machine learning
chaitra-1.pptx fake news detection using machine learning
 
HARMONY IN THE NATURE AND EXISTENCE - Unit-IV
HARMONY IN THE NATURE AND EXISTENCE - Unit-IVHARMONY IN THE NATURE AND EXISTENCE - Unit-IV
HARMONY IN THE NATURE AND EXISTENCE - Unit-IV
 
the ladakh protest in leh ladakh 2024 sonam wangchuk.pptx
the ladakh protest in leh ladakh 2024 sonam wangchuk.pptxthe ladakh protest in leh ladakh 2024 sonam wangchuk.pptx
the ladakh protest in leh ladakh 2024 sonam wangchuk.pptx
 
Roadmap to Membership of RICS - Pathways and Routes
Roadmap to Membership of RICS - Pathways and RoutesRoadmap to Membership of RICS - Pathways and Routes
Roadmap to Membership of RICS - Pathways and Routes
 
(MEERA) Dapodi Call Girls Just Call 7001035870 [ Cash on Delivery ] Pune Escorts
(MEERA) Dapodi Call Girls Just Call 7001035870 [ Cash on Delivery ] Pune Escorts(MEERA) Dapodi Call Girls Just Call 7001035870 [ Cash on Delivery ] Pune Escorts
(MEERA) Dapodi Call Girls Just Call 7001035870 [ Cash on Delivery ] Pune Escorts
 
Call Girls Service Nagpur Tanvi Call 7001035870 Meet With Nagpur Escorts
Call Girls Service Nagpur Tanvi Call 7001035870 Meet With Nagpur EscortsCall Girls Service Nagpur Tanvi Call 7001035870 Meet With Nagpur Escorts
Call Girls Service Nagpur Tanvi Call 7001035870 Meet With Nagpur Escorts
 
Exploring_Network_Security_with_JA3_by_Rakesh Seal.pptx
Exploring_Network_Security_with_JA3_by_Rakesh Seal.pptxExploring_Network_Security_with_JA3_by_Rakesh Seal.pptx
Exploring_Network_Security_with_JA3_by_Rakesh Seal.pptx
 
HARDNESS, FRACTURE TOUGHNESS AND STRENGTH OF CERAMICS
HARDNESS, FRACTURE TOUGHNESS AND STRENGTH OF CERAMICSHARDNESS, FRACTURE TOUGHNESS AND STRENGTH OF CERAMICS
HARDNESS, FRACTURE TOUGHNESS AND STRENGTH OF CERAMICS
 
(RIA) Call Girls Bhosari ( 7001035870 ) HI-Fi Pune Escorts Service
(RIA) Call Girls Bhosari ( 7001035870 ) HI-Fi Pune Escorts Service(RIA) Call Girls Bhosari ( 7001035870 ) HI-Fi Pune Escorts Service
(RIA) Call Girls Bhosari ( 7001035870 ) HI-Fi Pune Escorts Service
 
APPLICATIONS-AC/DC DRIVES-OPERATING CHARACTERISTICS
APPLICATIONS-AC/DC DRIVES-OPERATING CHARACTERISTICSAPPLICATIONS-AC/DC DRIVES-OPERATING CHARACTERISTICS
APPLICATIONS-AC/DC DRIVES-OPERATING CHARACTERISTICS
 
VIP Call Girls Service Kondapur Hyderabad Call +91-8250192130
VIP Call Girls Service Kondapur Hyderabad Call +91-8250192130VIP Call Girls Service Kondapur Hyderabad Call +91-8250192130
VIP Call Girls Service Kondapur Hyderabad Call +91-8250192130
 
Architect Hassan Khalil Portfolio for 2024
Architect Hassan Khalil Portfolio for 2024Architect Hassan Khalil Portfolio for 2024
Architect Hassan Khalil Portfolio for 2024
 
Gfe Mayur Vihar Call Girls Service WhatsApp -> 9999965857 Available 24x7 ^ De...
Gfe Mayur Vihar Call Girls Service WhatsApp -> 9999965857 Available 24x7 ^ De...Gfe Mayur Vihar Call Girls Service WhatsApp -> 9999965857 Available 24x7 ^ De...
Gfe Mayur Vihar Call Girls Service WhatsApp -> 9999965857 Available 24x7 ^ De...
 
(ANJALI) Dange Chowk Call Girls Just Call 7001035870 [ Cash on Delivery ] Pun...
(ANJALI) Dange Chowk Call Girls Just Call 7001035870 [ Cash on Delivery ] Pun...(ANJALI) Dange Chowk Call Girls Just Call 7001035870 [ Cash on Delivery ] Pun...
(ANJALI) Dange Chowk Call Girls Just Call 7001035870 [ Cash on Delivery ] Pun...
 
Call Girls in Nagpur Suman Call 7001035870 Meet With Nagpur Escorts
Call Girls in Nagpur Suman Call 7001035870 Meet With Nagpur EscortsCall Girls in Nagpur Suman Call 7001035870 Meet With Nagpur Escorts
Call Girls in Nagpur Suman Call 7001035870 Meet With Nagpur Escorts
 
GDSC ASEB Gen AI study jams presentation
GDSC ASEB Gen AI study jams presentationGDSC ASEB Gen AI study jams presentation
GDSC ASEB Gen AI study jams presentation
 
main PPT.pptx of girls hostel security using rfid
main PPT.pptx of girls hostel security using rfidmain PPT.pptx of girls hostel security using rfid
main PPT.pptx of girls hostel security using rfid
 
MANUFACTURING PROCESS-II UNIT-2 LATHE MACHINE
MANUFACTURING PROCESS-II UNIT-2 LATHE MACHINEMANUFACTURING PROCESS-II UNIT-2 LATHE MACHINE
MANUFACTURING PROCESS-II UNIT-2 LATHE MACHINE
 

Hexadite Real Life Django ORM

  • 1. Intelligent Security Automation hexadite.com Real-life Django ORM Presentation for PyWeb-IL #66, Monday, July 3, 2017
  • 2. Intelligent Security Automation hexadite.com What We Do
  • 3. Intelligent Security Automation hexadite.com Who We Are Max Braitmaiere max@hexadite.com VP of Engineering Evgeniy (Jenya) Privalov jenya@hexadite.com Software Developer
  • 4. Intelligent Security Automation hexadite.com Agenda • Why Django • Why Django ORM (for backend) • Django DB connection handling (backend and frontend) • Django + Postgres tweaks & tricks • Running uTests with DB
  • 5. Intelligent Security Automation hexadite.com Why Django
  • 6. Intelligent Security Automation hexadite.com Advantages • Written in Python. • Complex solution for web apps • Secure • Batteries Included • Predefined structures • Community • Good documentation
  • 7. Intelligent Security Automation hexadite.com Disadvantages • Monolithic application • All components are deployed together
  • 8. Intelligent Security Automation hexadite.com Why Django ORM
  • 9. Intelligent Security Automation hexadite.com Why Django ORM • Application design, maintainability • Transaction management • Cache management • Connection management • Community, documentation • Code and Business-Logic reuse
  • 10. Intelligent Security Automation hexadite.com Django DB connection handling
  • 11. Intelligent Security Automation hexadite.com Thread Local local() holds all connection(s) references in a Thread local store Connections == [processes] * [threads] """ from django/db/utils.py """ ... class ConnectionHandler(object): def __init__(self, databases=None): """ databases is an optional dictionary of database definitions (structured like settings.DATABASES). """ self._databases = databases self._connections = local() ...
  • 12. Intelligent Security Automation hexadite.com Web Request Lifecycle close_if_unusable_or_obsolete() • if unrecoverable errors have occurred • if it outlived its maximum age (CONN_MAX_AGE) called on request started / finished """ from django/db/__init__.py """ ... # Register an event to reset transaction state and close connections past # their lifetime. def close_old_connections(**kwargs): for conn in connections.all(): conn.close_if_unusable_or_obsolete() signals.request_started.connect(close_old_connections) signals.request_finished.connect(close_old_connections)
  • 13. Intelligent Security Automation hexadite.com Regular Backend Implications • Any use of the ORM to work with data, will create a Thread local connection • Long running services don’t operate within a “request” == no call to close_if_unusable_or_obsolete()
  • 14. Intelligent Security Automation hexadite.com The Transaction Block from django.db import transaction with transaction.atomic(): # query and/or change data... with transaction.atomic(): # runs an “inner” transaction Used to define the beginning and end of a transaction. We can leverage this to define a clear “scope of work” in code. NOTE: With async, don’t yield within a transaction block
  • 15. Intelligent Security Automation hexadite.com Enter ClosingAtomic """ from (our) transaction.py """ class _ClosingAtomic(object): def __init__(self, base_atomic): self._atomic = base_atomic def __enter__(self): self._atomic.__enter__() def __exit__(self, exc_type, exc_val, exc_tb): # end actual transaction self._atomic.__exit__(exc_type, exc_val, exc_tb) # get connection conn = django.db.transaction.get_connection(self._atomic.using) # if db connection is not closed, and this is the last transaction - close connection if conn.connection is not None and not conn.in_atomic_block: conn.close()
  • 16. Intelligent Security Automation hexadite.com Our Own “Atomic” """ from (our) transaction.py """ class _ClosingAtomic(object): """ Open/Closes an atomic transaction, on last transaction close - terminates the DB connection. """ def closing_atomic(using=None, savepoint=True): """ ... """ return _ClosingAtomic(django.db.transaction.atomic(using=using, savepoint=savepoint)) # default atomic transaction with closing atomic = closing_atomic
  • 17. Intelligent Security Automation hexadite.com Enter Pooling • Django middleware (connection pooling within a process) • External Connection pooling
  • 18. Intelligent Security Automation hexadite.com PgBouncer (https://pgbouncer.github.io) “pool_mode” Specifies when a server connection can be reused by other clients. • session: Server is released back to pool after client disconnects. Default. • transaction: Server is released back to pool after transaction finishes. • statement: Server is released back to pool after query finishes. PostgreSQL PgBouncerApps hundreds fixed ~40
  • 19. Intelligent Security Automation hexadite.com Enter CleanupAtomic """ from (our) transaction.py """ class _CleanupAtomic(object): ... def __enter__(self): conn = django.db.transaction.get_connection(self._atomic.using) # if this is the first transaction block - cleanup connection if unusable if not conn.in_atomic_block: conn.close_if_unusable_or_obsolete() self._atomic.__enter__() def __exit__(self, exc_type, exc_val, exc_tb): self._atomic.__exit__(exc_type, exc_val, exc_tb) conn = django.db.transaction.get_connection(self._atomic.using) # if this is the last transaction block - cleanup connection if unusable if not conn.in_atomic_block: conn.close_if_unusable_or_obsolete()
  • 20. Intelligent Security Automation hexadite.com Putting It All Together def cleanup_atomic(using=None, savepoint=True): return _CleanupAtomic(django.db.transaction.atomic(...)) # default atomic transaction with cleanup atomic = cleanup_atomic ... with atomic(): # exiting this context will trigger the “cleanup” with atomic(): # exiting this context affects inner transaction (no “cleanup”) • PgBouncer can “multiplex” many connections passing through only X transactions • No constant connection closing • Uses the CONN_MAX_AGE if set • Usage is applicable for request handling and long running services • Default Django autocommit is not destructive
  • 21. Intelligent Security Automation hexadite.com Django Postgres tweaks & tricks
  • 22. Intelligent Security Automation hexadite.com Text Indexing (PostgreSQL) """ from django.db.backends.postgresql.schema """ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor): def _create_like_index_sql(self, model, field): … if db_type.startswith('varchar'): return self._create_index_sql(..., suffix='_like') elif db_type.startswith('text'): return self._create_index_sql(..., suffix='_like') ... def _alter_field(self, model, old_field, new_field, old_type, new_type, old_db_params, new_db_params, strict=False): ... self._create_like_index_sql(model, new_field) ... • Fields with database column types varchar and text need a second index that specifies their operator class , which is needed when performing correct LIKE operations, outside the C locale
  • 23. Intelligent Security Automation hexadite.com Text Indexing (Custom Fields) """ from (our) fields.py """ class TextFieldIndexControlled(TextField): ... class CharFieldIndexControlled(CharField): def __init__(self, *args, **kwargs): self.like_index = kwargs.pop('like_index', True) super(CharFieldIndexControlled, self).__init__(*args, **kwargs) def deconstruct(self): name, path, args, kwargs = super(CharFieldIndexControlled, self).deconstruct() # Only include 'like_index' if it's not the default if self.like_index != True: kwargs['like_index'] = self.like_index return name, path, args, kwargs
  • 24. Intelligent Security Automation hexadite.com Text Indexing (SchemaEditor) """ from (our) schema.py """ class DatabaseSchemaEditor(schema.DatabaseSchemaEditor): def _create_like_index_sql(self, model, field): if not getattr(field, 'like_index', True): # if like_index is False explicitly , don't create return None return super(DatabaseSchemaEditor, self)._create_like_index_sql(model, field) def _alter_field(self, model, old_field, new_field, old_type, new_type, old_db_params, new_db_params, strict=False): ... # ADD YOU LOGIC HERE _create_like_index_sql(..) ... • SchemaEditor class is responsible for emitting schema-changing statements to the database
  • 25. Intelligent Security Automation hexadite.com Text Indexing (DatabaseWrapper) """ from (our) base.py """ from django.db.backends.postgresql_psycopg2 import base from schema import DatabaseSchemaEditor class DatabaseWrapper(base.DatabaseWrapper): SchemaEditorClass = DatabaseSchemaEditor # our schema editor DataBaseWrapper is a class that represent the DB connection in Django
  • 26. Intelligent Security Automation hexadite.com Text Indexing (Database Engine) """ from (our) settings.py """ # https://docs.djangoproject.com/en/1.10/ref/settings/#databases DATABASES = { 'default': { 'ENGINE': 'our.backends.postgresql_psycopg2', 'HOST': '127.0.0.1', 'NAME': 'db', 'USER': 'user', 'PASSWORD': 'password', 'CONN_MAX_AGE': 300, }, }
  • 27. Intelligent Security Automation hexadite.com Bulk delete Django needs to fetch objects into memory to send signals and handle cascades. However, if there are no cascades and no signals, then Django may take a fast-path and delete objects without fetching into memory. For large deletes this can result in significantly reduced memory usage. https://docs.djangoproject.com/en/1.10/ref/models/querysets/#delete
  • 28. Intelligent Security Automation hexadite.com QuerySets Iterator """ from (our) iterators.py """ def querysets_bulk_iterator(qs, batchsize=500, gc_collect=True, nullify_each_iteration=False): start = 0 end = batchsize last_element = max(qs.count(), batchsize) while start <= last_element: if nullify_each_iteration: yield qs.order_by('pk')[:batchsize] else: yield qs.order_by('pk')[start:end] start += batchsize end += batchsize if gc_collect: gc.collect() raise StopIteration • gc.collect() explicitly tell to the garbage collector start to collect. • when done with each yielded queryset need to call del() on the queryset
  • 29. Intelligent Security Automation hexadite.com Foreign Keys class User(models.Model): name = models.CharField() class Order(models.Model): user = models.ForeignKey(User, related_name="orders", db_constraint=False, db_index=False) • Maintain integrity and consistency of data • Dramatic slow down on writes • Django has out of the box solution db_constraint=False • Indexing may also not be required db_index=False
  • 30. Intelligent Security Automation hexadite.com PostgresSQL Tunings • models.PositiveIntegerField • Find useless, unused indexes and delete them. • Use “ANALYZE” and “EXPLAIN” to optimize PostgreSQL queries. • Vacuum database. • Analyse database. • Tune PostgreSQL server configuration.
  • 31. Intelligent Security Automation hexadite.com Running uTests with DB
  • 32. Intelligent Security Automation hexadite.com Best Practice • Regular utest: mock data calls, will allow best performance • Django utest: Use in memory sqlite, performs all DB operations much faster. What if our DAL/BL uses some custom capabilities? • Array Fields • JSON Field query • etc
  • 33. Intelligent Security Automation hexadite.com Test DB Use a predefined suffix: • Allows isolation • Multiple tests can run on same machine """ from (test) settings.py """ import os TEST_DB_SUFFIX = os.getenv( 'OUR_TEST_DB_SUFFIX', '') DATABASES = { 'default': { 'ENGINE': 'our.backends.postgresql_psycopg2', 'HOST': '127.0.0.1', 'PORT': '5432', 'NAME': 'db' + TEST_DB_SUFFIX, 'TEST': {'NAME': 'test_db' + TEST_DB_SUFFIX}, 'USER': 'user', 'PASSWORD': 'password', 'CONN_MAX_AGE': 300, # persistent connections for 5 minutes }, }
  • 34. Intelligent Security Automation hexadite.com Q&A Thank You :) max@hexadite.com jenya@hexadite.com
  • 35. Intelligent Security Automation hexadite.com Optional Slides
  • 36. Intelligent Security Automation hexadite.com Delayed Migrations
  • 37. Intelligent Security Automation hexadite.com Data Migration # -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import migrations def update_usernames(apps, schema_editor): User = apps.get_model('app', 'User') User.objects.update(name=Upper(F('name'))) class Migration(migrations.Migration): dependencies = [ ('app', '0001_initial'), ] operations = [ migrations.RunPython(update_usernames), ] • Data Migration - change or loading of data. Should be done manually. • For large data sets could take a lot of time.
  • 38. Intelligent Security Automation hexadite.com Delayed Migration # -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import migrations def update_usernames_delayed(apps, schema_editor): User = apps.get_model('app', 'User') User.objects.update(name=Upper(F('name'))) class Migration(migrations.Migration): dependencies = [ ('app', '0001_initial'), ] operations = [ # REGULAR DJANGO MIGRATION OPERATIONS ] delayed_operations = [ migrations.RunPython(update_usernames_delayed), ] • delayed_operations won’t run with regular operations
  • 39. Intelligent Security Automation hexadite.com Delayed Migration (Migrate Command) MIGRATIONS_DUMPS_PATH = os.path.join(os.path.dirname(__file__), 'migrations') MIGRATIONS_PATH = os.path.join(os.path.dirname(__file__), 'migrations', 'delayed_migrations.json') class Command(CommandMigration): def handle(self, *args, **options): self.delayed_migrations_to_run = [] super(Command, self).handle(*args, **options) if self.delayed_migrations_to_run: with open(MIGRATIONS_PATH, 'wb') as f: json.dump(self.delayed_migrations_to_run, f) def migration_progress_callback(self, action, migration=None, fake=False): if action == 'apply_success' and not fake: if hasattr(migration, 'delayed_operations'): self.delayed_migrations_to_run.append("%s.%s" % (migration.app_label, migration.name)) return super(Command, self).migration_progress_callback(action, migration, fake) • Add custom migrate command which will be use delayed_operations • Run all your migrations with this command
  • 40. Intelligent Security Automation hexadite.com Delayed Migration (Command) class Command(CommandMigration): def handle(self, *args, **options): self.executor = MigrationExecutor(self.connection, self.migration_progress_callback) state = ProjectState(real_apps=list(self.loader.unmigrated_apps)) states = self.build_migration_states(plan, state) try: for migration in plan: self.apply_migration(states[migration], migration) plan.remove(migration) finally: self.update_migrations_state(plan) • Run custom “delayed” migration when you need
  • 41. Intelligent Security Automation hexadite.com Delayed Migration (Usage) 1. manage.py custom_migrate 2. manage.py custom_delayed_migrate

Editor's Notes

  1. Cyber analyst thinking at the speed of automation Modeled after the investigative and decision-making skills of top cyber analysts and driven by artificial intelligence, Hexadite Automated Incident Response Solution (AIRS™) remediates threats and compresses weeks of work into minutes. With analysts free to focus on the most advanced threats, Hexadite optimizes overtaxed security resources for increased productivity, reduced costs and stronger overall security.
  2. 3yr old startup, working mainly with Python (2.7) stack (Angular2 frontend)
  3. Presentation is updated for Django 1.10.5 and PostgresSQL 9.5
  4. Here we are going to give an overview of why we went with Django in general
  5. Complex solution for web apps: templates, forms, orm, etc. Secure: Django provides good security protection out of the box Batteries Included: A lot of functionality provided out of the box + third party packages that can help to accelerate development Predefined structures: urls, apps, models
  6. Monolithic application: You always get all django apps, you cannot off the features you don’t need
  7. Specific consideration to use Django ORM with web-apps and with backend services
  8. Application design, maintainability: you don’t deal with your DB, like every ORM Code and Business-Logic reuse: using Django ORM in web apps and re-use same logic and ORM in backend services
  9. Our issues with connection handling in service applications
  10. Thread Local has the advantage of avoiding handling with locks (and multi-threading sync overhead in general) The total active connections is equal to total number of active threads that ever accessed the DB (across all relevant processes)
  11. CONN_MAX_AGE Default: 0 The lifetime of a database connection, in seconds. Use 0 to close database connections at the end of each request — Django’s historical behavior — and None for unlimited persistent connections.
  12. “Connections Leak” any thread may create a connection which can stay persistent without the thread ever requiring it again or remain in a bad state.
  13. Our atomic wrapper for connections closing on last transaction block When working with async libs such as asyncio/trollius yielding within a transaction block will have unexpected results as the state of the connection will be passed to an undetermined code path.
  14. Our atomic wrapper for connections closing on last transaction block
  15. The Good: Defining our own “atomic” allows us to use it across our code base with an easy way to tweak and change behavior in the future Connections are cleaned up (closed) The Bad: Opening and closing connections on end of every transaction is “expensive” and may be unnecessary Any code that does not use transaction.atomic() may still “leak” conections
  16. A middleware solution is not optimal if an external pooling solution is possible, as it allows a better separation of concerns where each component does “one thing”
  17. PgBouncer allows multiplexing hundreds of connections, re-using a pre-established connection pool to the DB. We selected the “transaction” mode this allows us to support both actual transactions and the default autocommit (see https://docs.djangoproject.com/en/1.10/topics/db/transactions/ )
  18. Our atomic wrapper for connections cleanup. First and last transaction block will call close_if_unusable_or_obsolete(): reset transaction state and close connections past their lifetime.
  19. Our atomic wrapper for connections closing on last transaction block (uses close_if_unusable_or_obsolete() )
  20. 2 indexes per each varchar and text fields, more indexes == slower inserts , updates. In case we don’t want to use them, we can remove them after creation with simple sql query or prevent their creation
  21. First stage is to create a Char/Text field definition that adds a new option “like_index” deconstruct() is called to produce the migration files content
  22. change logic in alter field of our custom editor, skipps producing the “like” index if forced off (like_index == False)
  23. In order to add custom schema editor to our project , we need to change django database engine and in order to do that we need to change the DatabaseWarpper the class that represent connection.
  24. In order to add custom schema editor to our project , we need to change django database engine and in order to do that we need to change the DataBaseWarpper the class that represent connection.
  25. set nullify to True if you delete the queryset
  26. every time your insert or update row with foreign key database should to check if this key exists (and index the value) impact depends on DB Indexing: In cases we always filter by more than one field, it may be redundant to index all fields - even if those are “foreign keys”
  27. useful references PositiveIntegerField will add a constraint in DB - in general check the actual schema that gets created (when first using a new field type)
  28. Using a real DB has its issues, but can be a better fit when we want to test some related BL and make sure it works in production.
  29. More optionals topics
  30. it’s a problem when you want to separate schema and data migrations but still to preserve migrations mechanism
  31. python manage.py migrate will be applied only for operations, for delayed_operations we will save migrations execution plan
  32. with the migration progress we will update the delayed execution path in proper order, in the end execution path is saved to file ( different approach could be applied, database for example)
  33. run delayed migrations when you need a lot of code is missing here..