about this talk
- general information about the conference
- will go briefly through some of the topics
- links will be provided
the history
- the first edition took place in Prague in 2009
- in 2013 it took place in Warsaw
- this year it was Copenhagen
in numbers
- 3 conference days
- 30 talks, 10 workshops
- lightning talks
- network drinks
- 2 sprint days
- 400 attendees
about the conference
- no simultaneous talks
- code of conduct
- photo policy
- the ++ rule
- the pacman rule
is it worth it ?
is it worth it ?
- travel
- meet active community members
- learn about the latest developments
- attend the sprints and contribute
- relaxed and welcoming atmosphere
is it worth it ?
- travel
- meet active community members
- learn about the latest developments
- attend the sprints and contribute
- relaxed and welcoming atmosphere
- not many deeply technical talks
- not all talks directly related to django
- a lot of talks about the django community
- all the talks are streamed and available on youtube
...but keep in mind that
serverless
or Functions as a Service (FaaS)
Serverless computing (or serverless for short), is an execution model where the cloud provider is responsible for executing a piece of code by dynamically allocating the resources. And only charging for the amount of resources used to run the code. The code is typically run inside stateless containers that can be triggered by a variety of events including http requests, database events, queuing services, monitoring alerts, file uploads, scheduled events (cron jobs), etc. The code that is sent to the cloud provider for execution is usually in the form of a function. Hence serverless is sometimes referred to as “Functions as a Service” or “FaaS”.
serverless
or Functions as a Service (FaaS)
- Complete abstraction of servers away from the developer
- Billing based on consumption and executions, not server instance sizes
- Services that are event-driven and instantaneously scalable
basic premises:
- AWS Lambda
- Azure Functions
- Google Functions
well known providers:
serverless
zappa
Deploy your WSGI apps on AWS Lambda
With Zappa, each request is given its own virtual HTTP "server" by Amazon API Gateway. AWS handles the horizontal scaling automatically, so no requests ever time out. After your app returns, the "server" dies.
serverless
zappa
- No more tedious web server configuration!
- No more paying for 24/7 server uptime!
- No more worrying about load balancing / scalability!
- No more worrying about web server security!
serverless
zappa up and running
async
- Python is at a big crossroads. Python 3.5 introduced the async/await keywords
- the async model provides high throughput services, non-blocking HTTP requests.
- only async functions can call other async functions
async
wsgi vs asgi
WSGI is an inherently thread-concurrency interface, so it cannot do any async context switching inside
ASGI has an async interface, and includes more than just HTTP request/responses, and is very much more general purpose and highly adabtable.
async
asgi servers
Daphne, Hypercorn, and Uvicorn
asgi frameworks
Starlette, Responder, FastAPI
async
asgi server benefits
- High raw throughput
- WebSockets and other real time communications
- Server Sent Events
- HTTP/2 server push
- Background tasks
- Clock and timer tasks
async
starlette - hello world
from starlette.applications import Starlette
from starlette.responses import JSONResponse
import uvicorn
app = Starlette(debug=True)
@app.route('/')
async def homepage(request):
return JSONResponse({'hello': 'world'})
if __name__ == '__main__':
uvicorn.run(app, host='0.0.0.0', port=8000)
async
starlette - db request
@app.route("/notes", methods=["GET"])
async def list_notes(request):
query = notes.select()
results = await database.fetch_all(query)
content = [
{
"text": result["text"],
"completed": result["completed"]
}
for result in results
]
return JSONResponse(content)
async
starlette
- uvicorn is an ASGI web server
- starlette is an ASGI web framework or toolkit
- databases is an async database interface
- orm is an async ORM
- typesystem provides type validation
- requests-async can handle any outgoing requests
async
django async roadmap
https://www.aeracode.org/2018/06/04/django-async-roadmap/
- Django 3.0: Rewrite the internal request handling stack to be entirely asynchronous, add async middleware, forms, caching, sessions, auth. Start deprecation process for any APIs that are becoming async-only.
- Django 3.1: Continue improving async support, potential async templating changes
- Django 3.2: Finish deprecation process and have a mostly-async Django.
logging
logging
- treat logs as events
- add structure and context
- trace logs across multiple services
- format as json (for ELK or graylog)
import logging
logger = logging.getLogger(__name__)
logger.error(f'Failed to perform operation on object #{object.id} for user #{user.id}')
what logging usually looks like:
ideas:
logging
structlog
import structlog
logger = structlog.getLogger()
logger.error('transaction_failed',
user=user.id, target_user=target_user.id, transaction=transaction.id)
2018-04-20 16:20.13 transaction_failed user=324 target_user=134 transaction=150
- easier to test for occurence
- message less likely to change (log based alerts are more reliable)
logging
structlog
logger.bind(user=user.id, target_user=target_user.id)
...
logger.bind(transaction=transaction.id)
...
logger.info('transaction_initiated')
2018-04-20 16:20.13 transaction_initiated user=324 target_user=134 transaction=150
...
logger.error('transaction_failed')
2018-04-20 16:21.15 transaction_failed user=324 target_user=134 transaction=150
- bind/rebind loggers to provided context for subsequent logs
logging
trace logs across multiple services
import uuid, structlog
logger = structlog.get_logger('structlog')
def structlog_middleware(get_response): # Use as first middleware
def _inner(request):
request.trace_id = request.headers.get('x_trace_id') or str(uuid.uuid4)
logger.bind(trace_id=request.trace_id)
return get_response(request)
return _inner
def structlog_user_middleware(get_response): # Use after authentication middleware
def _inner(request):
if request.user.is_authenticated:
logger.bind(logger, user.id)
return get_response(request)
return _inner
logging
https://gitlab.com/MarkusH/django-structlog/tree/master/bank/bank
django orm
django orm
subqueries django >= 1.11
>>> from django.db.models import OuterRef, Subquery
>>> newest = Comment.objects.filter(post=OuterRef('pk')).order_by('-created_at')
>>> Post.objects.annotate(newest_commenter_email=Subquery(newest.values('email')[:1]))
SELECT "post"."id", (
SELECT U0."email"
FROM "comment" U0
WHERE U0."post_id" = ("post"."id")
ORDER BY U0."created_at" DESC LIMIT 1
) AS "newest_commenter_email" FROM "post"
django orm
queryset.explain django >= 2.1
>>> print(Blog.objects.filter(title='My Blog').explain(verbose=True))
Seq Scan on public.blog (cost=0.00..35.50 rows=10 width=12) (actual time=0.004..0.004 rows=10 loops=1)
Output: id, title
Filter: (blog.title = 'My Blog'::bpchar)
Planning time: 0.064 ms
Execution time: 0.058 ms
django orm
UniqueConstraint django >= 2.2
class Order(Model):
...
class Meta:
constraints = [
UniqueConstraint(
name='limit_pending_orders',
fields=['customer', 'is_shipped'],
condition=Q(is_shipped=False)
)
]
django orm
CheckConstraint django >= 2.2
class MontlyBudget(Model):
class Meta:
constraints = [
CheckConstraint(
check=Q(month__in=range(1, 13)),
name='check_valid_month',
)
]
]
django orm
bulk_update django >= 2.2
>>> objs = [
... Entry.objects.create(headline='Entry 1'),
... Entry.objects.create(headline='Entry 2'),
... ]
>>> objs[0].headline = 'This is entry 1'
>>> objs[1].headline = 'This is entry 2'
>>> Entry.objects.bulk_update(objs, ['headline'])
django orm
partial index django >= 2.2
class Article(models.Model):
title = models.CharField(max_length=1000)
upvotes = models.IntegerField()
class Meta:
indexes = [
models.Index(
fields=['upvotes'],
name='upvotes_idx',
condition=Q(upvotes__gt=100)
)
]
django orm
windows functions django >= 2.0
from django.db.models import Avg, F, Window
from django.db.models.functions import ExtractYear
# annotate each movie with the average rating
# for the movies by the same studio in the same genre
Movie.objects.annotate(
avg_rating=Window(
expression=Avg('rating'),
partition_by=[F('studio'), F('genre')],
order_by=ExtractYear('released').asc(),
),
)
security headers
security headers
X-XSS-Protection
In Django: set SECURE_BROWSER_XSS_FILTER = True and include the SecurityMiddleware in your middlewares.
stops pages from loading when they detect reflected cross-site scripting
security headers
Strict-Transport-Security
In Django: set SECURE_HSTS_SECONDS to and include SecurityMiddleware.
Note: If you break your HTTPS after having set this flag, any browser that has seen is will not be able to see your website again.
Lets a web site tell browsers that it should only be accessed using HTTPS, instead of using HTTP.
security headers
X-Frame-Options
In Django: X_FRAME_OPTIONS = 'DENY' (or use whitelisting), and include the XFrameOptionsMiddleware.
Can be used to indicate whether or not a browser should be allowed to render a page in an inframe
security headers
Content-Security-Policy
In Django: Mozilla provides django-csp, add CSPMiddleware, and then set a couple of values, e.g.CSP_DEFAULT_SRC = 'self'.
img-src *; # images from anywhere
script-src userscripts.example.com # scripts only from here
security headers
Feature-Policy
New and not yet supported in all browsers – this header lets you disable browser feature, like autoplay, geolocation, camera, etc.
In Django: Install django-feature-policy, add FeaturePolicyMiddleware and set FEATURE_POLICY.
security headers
https://securityheaders.com/
tools
tools
- black
- opinionated python formatter
- endorsed by many open source projects
- strict subset of PEP 8
tools
- pipenv
- Automatically finds your project home, recursively, by looking for a Pipfile.
- Automatically creates a virtualenv in a standard location
- Automatically adds/removes packages to a Pipfile when they are un/installed
- Automatically loads .env files, if they exist.
- alternative to pipenv
tools
- graphene
- python GraphQL framework
- with django integration
- strawberry-graphql (alternative to graphene)
tools
- django-migration-linter
- Detect backward incompatible migrations
Thank you
- https://2019.djangocon.eu/
- https://www.flickr.com/photos/djangocon/
- https://www.youtube.com/channel/UCr7bPKCES6rP1UbX0dTVv-Q
DjangoCon Europe 2019
By zqzak
DjangoCon Europe 2019
- 301