Upload
flywindy
View
125
Download
3
Tags:
Embed Size (px)
Citation preview
Best Practices for Django 1.6
TWO SCOOPS OF DJANGO
Ch. 24: Logging: What's It For, Anyway? Ch. 25: Signals: Use Cases and Avoidance Techniques
Michelle Leu @flywindy 2015/04/21
ABOUT THIS BOOK• Best practices
• Django 1.6
• Not really for new comer
• Author:
• Daniel Greenfeld & Audrey Roy
• Django Packages 2
LOGGING• Django uses Python’s builtin logging module to
perform system logging.
• Application Logs vs. Other Logs
• App logs: any log file containing data logged from your Python web application
• Why Bother With Logging?
• debug, tracking, security…
4
Log Catastrophes With CRITICAL
LOG LEVEL
Use the CRITICAL log level only when something catastrophic occurs that
requires urgent attention.
5
Log Production Errors With ERROR
LOG LEVEL
Use the ERROR log level whenever you need to log an error that is
worthy of being emailed to you or your site admins.
6
Log Production Errors With ERROR
LOG LEVEL
7
logger.error("Internal Server Error: %s", request.path, exc_info=exc_info, extra={ "status_code": 500, "request": request } )
Log Lower-Priority Problems With WARNING
LOG LEVEL
This level is good for logging events that are unusual and potentially bad,
but not as bad as ERROR-level events.
8
Log Lower-Priority Problems With WARNING
LOG LEVEL
9
logger.warning("Forbidden (%s): %s", REASON_NO_CSRF_COOKIE, request.path, extra={ "status_code": 403, "request": request, } )
Log Useful State Information With INFO
LOG LEVEL
Use this level to log any details that may be particularly important when
analysis is needed.
10
Log Debug-Related Messages to DEBUG
LOG LEVEL
In development, we recommend using DEBUG and occasionally INFO
level logging wherever you’d consider throwing a print statement
into your code for debugging
11
LOG TRACEBACKS• Python’s logging module supports this:
• Logger.exception() automatically includes the traceback and logs at ERROR level.
• For other log levels, use the optional exc_info keyword argument.
12
ONE LOGGER PER MODULE• Whenever you use logging in another module,
don’t import and reuse a logger from elsewhere. Instead, define a new logger specific to the module.
• What this gives you is the ability to turn on and off only the specific loggers that you currently need.
13
LOG LOCALLY• Default settings file is configured to email ERROR
and higher log messages to whomever you list in ADMINS.
• Writing logs of level INFO and higher to rotating log files on disk.
14
Sentry
THIRD-PARTY TOOLS
Sentry is a modern error logging and aggregation platform.
The primary implementation is in Python, but it contains a full API for sending events from
any language, in any application.
15
SENTRY1. pip install raven
2. Django configuration
3. python manage.py raven test~demo~
16
# settings.py # ...
# Set your DSN value RAVEN_CONFIG = { 'dsn': 'SENTRY_DSN', }
# Add raven to the list of installed apps INSTALLED_APPS = INSTALLED_APPS + ( # ... 'raven.contrib.django.raven_compat', )
OTHER TIPS• Colorizing your log output helps you spot
important messages at a glance. Ex: logutils
• loggly.com (http://loggly.com/) simplifies log management and provides excellent query tools.
• PagerDuty (http://www.pagerduty.com/) alert you and your team repeatedly until you’ve taken action.
17
Don’t wait until it’s too late to add logging.
SUMMARY
You’ll be grateful for your logs if and when your site fails.
18
WHAT IS SIGNALS• Django includes a “signal dispatcher” which helps
allow decoupled applications get notified when actions occur elsewhere in the framework.
22
SenderReceiver
ReceiverReceiver
!
WHAT IS SIGNALS• Django provides a set of built-in signals. These
include some useful notifications: • django.db.models.signals.pre_save &
django.db.models.signals.post_save
• django.db.models.signals.m2m_changed
• django.core.signals.request_started & django.core.signals.request_finished
23
Use signals as a last resort.
WHY NOT?
• Signals are being dispatched everywhere and hopefully getting received somewhere.
• Not like Celery, Signals are synchronous and blocking.
24
WHEN TO USE• Your signal receiver needs to make changes to
more than one model.
• You want to dispatch the same signal from multiple apps and have them handled the same way by a common receiver.
• You want to invalidate a cache after a model save.
• You have an unusual scenario that needs a callback, and there’s no other way to handle it besides using a signal.
25
WHEN TO AVOID• The signal relates to one particular model and can
be moved into one of that model’s methods, possibly called by save().
• The signal can be replaced with a custom model manager method.
• The signal relates to a particular view and can be moved into that view.
26
\
29
# events/managers.py from django.db import models class EventManager(models.Manager): def create_event(self, title, start, end, creator): event = self.model(title=title, start=start, end=end, creator=creator) event.notify_admins() return event
# events/models.py # ... from model_utils.models import TimeStampedModel from .managers import EventManager MSG = "{user} submitted a new event!" class Event(TimeStampedModel): # ... title = models.CharField(max_length=100) # ... objects = EventManager()
def notify_admins(self): # create the subject creator = self.creator subject = MSG.format(user=creator.get_full_name()) # create the message message = """TITLE: {title} START: {start} END: {end}""".format(title=self.title, start=self.start, end=self.end) # Send to the admins! mail_admins(subject=subject, message=message, fail_silently=False)
Instead of calling create(), we call a
create_event() method.
AVOIDANCE TECHNIQUES
30
• Validate Your Model Elsewhere
• If validating through a ModelForm, try overriding your model’s clean() method instead.
• Override Your Model’s Save or Delete Method Instead
REFERENCE• http://twoscoopspress.org/products/two-scoops-of-django-1-6
• https://docs.djangoproject.com/en/1.8/topics/logging/
• https://docs.python.org/3/library/logging.html
• https://app.getsentry.com/docs/platforms/django/
• http://raven.readthedocs.org/en/latest/integrations/django.html
• https://docs.djangoproject.com/en/1.8/topics/signals/
31