127

Meetup django common_problems(1)

Embed Size (px)

DESCRIPTION

Slides from 5/11/2011 Milwaukee Django User Group Meetup

Citation preview

Page 1: Meetup django common_problems(1)
Page 2: Meetup django common_problems(1)

Who is this fool?!A little about me

Page 3: Meetup django common_problems(1)

Python

DjangoJavaScript

VFX

Print DesignSoftwar

e

Web Design

Flash / Flex

Photography

CSS

Graphic Art

Digital Media

Page 4: Meetup django common_problems(1)
Page 5: Meetup django common_problems(1)

PERL & JavaScript

Page 6: Meetup django common_problems(1)
Page 7: Meetup django common_problems(1)

Django = HotPileOfAwesome( yes=True )Django.build_web_app( fast=True )

Page 8: Meetup django common_problems(1)

Django.make_an_app()>>> True

Django.log_in_user()>>> True

Django.comment_on_my_model()>>> True

Django.message_my_user(user='myuser')>>> True

Django.send_emails( emails=['[email protected]'] )>>> True

Django.do_complex_SQL( please=True )>>> No Problem!

Page 9: Meetup django common_problems(1)

Django.make_a_thumbnail()>>> Thumbnail?

Django.send_text_message()>>> Email Exception: no such thing

Django.search_all_my_stuff()>>> WTF?

Django.get_data_in_under_75_queries()>>> Whoa...

Django.alter_table(model='MyModel')>>> Let's not get crazy

Django.be_restful( now=True )>>> you mean request.POST

Page 10: Meetup django common_problems(1)

I've Got an app for that!

Page 11: Meetup django common_problems(1)

Searching

Page 12: Meetup django common_problems(1)

SearchingFind Stuff - Fast

Page 13: Meetup django common_problems(1)

SearchingFind Stuff - Fast

( without crushing my DB )

Page 14: Meetup django common_problems(1)

Haystack

Djapian

Sphinx

haystacksearch.org

code.google.com/p/djapian/

django-sphinx ( github )

Page 15: Meetup django common_problems(1)

MyModel.objects.filter( text__icontains='word' )

OR MyModel.objects.filter( text__search='word' )

Problems:• single model • slow• mysql• manual DB configs

Django

Page 16: Meetup django common_problems(1)

Haystackclass PostIndex( SearchIndex ): body = CharField(document = True, model_attr = 'body') title = CharField( model_attr = 'title') author = CharField( model_attr = 'author__get_full_name') text = CharField( use_template = True )

def get_queryset( self ): return Post.objects.all()

def prepare_url( self, obj ): return obj.get_absolute_url()

site.register(Post, PostIndex)

Page 17: Meetup django common_problems(1)

HaystackSearchQuerySet() .filter( SQ(field=True) | SQ(field__relation="something") ~SQ(field=False) )

>>> [ <SearchResult>, <SearchResult>, <SearchResult> ]

Page 18: Meetup django common_problems(1)

Xapianclass ArticleIndexer( Indexer ): fields = ['title','body'] tags = [ ('title','title', 3), ('body', 'as_plain_text', 1) ]space.add_index(Article, ArticleIndexer, attach_as='indexer')

Page 19: Meetup django common_problems(1)

Xapianfrom djapian.indexer import CompositeIndexer

flags = xapian.QueryParser.FLAG_PARTIAL| \ xapian.QueryParser.FLAG_WILDCARD

indexers = [ Model_1.indexer, Model_2.indexer ]comp = CompositeIndexer( *indexers )

s = comp.search( `a phrase` ).flags( flags )>>> [ <hit:score=100>,<hit:score=98> ]

$ s[0].instance>>> <ModelInstance:Model>

Page 20: Meetup django common_problems(1)

• Pluggable Architecture• Whole Word Matching• Loads all indexers• Multiple Index Hooks• Stored fields• Django-like Syntax• Templates & Tags• Views, Forms & Fields

• Wildcard Matching• Partial word matching• Doesn't Load All indexers• Interactive shell• Close to the metal

( Control )• Watches Models for

changes• Pre-index Filtering

Haystack XapianIndex files

Class Based IndexCustomize Text For Indexing

Link to Indexed ObjectIndex Fields, Methods & Relations

Stemming, Facetting, Highlighting, Spelling

Page 21: Meetup django common_problems(1)

REST API

Page 22: Meetup django common_problems(1)

REST APIExposing Your Data

Page 23: Meetup django common_problems(1)

REST APIExposing Your Data( In a meaningful way )

Page 24: Meetup django common_problems(1)

def view_func( reqeuest, *args, **kwargs): request.GET request.POST request.FILES

Problems:• PUT & DELETE not translated• Can't restrict access based on HTTP

methods• Serialization is left up to you• Manual auth• Tons of URLs

Django

Page 25: Meetup django common_problems(1)

PISTON

TASTYPIE

bitbucket.org/jespern/django-piston

toastdriven.github.com/django-tastypie/

Page 26: Meetup django common_problems(1)

Pistonclass MyHandler( BaseHandler ): methods_allowed =( 'GET', 'PUT') model = MyModel

class MyOtherHandler( BaseHandler ): methods_allowed =( 'GET', 'PUT') model = MyOtherModel fields = ('title','content',('author',('username',) ) ) exclude = ('id', re.compile(r'^private_')) def read( self, request): return [ x for x in MyOtherModel.objects.select_related() ]

def update( self, request ): ...

Page 27: Meetup django common_problems(1)

Tastypieclass MyResource( ModelResource ): fk_field = fields.ForiegnKey( OtherResource, 'fk_field' ) class Meta: authentication = ApiKeyAuthentication() queryset = MyModel.object.all() resource_name = 'resource' fields = ['title', 'content', ] allowed_methods = [ 'get' ] filtering = { 'somfield': ('exact', 'startswith') } def dehydrate_FOO( self, bundle ): return bundle.data[ 'FOO' ] = 'What I want'

Page 28: Meetup django common_problems(1)

Tastypie - Client Sidenew Request.JSONP({ url:'http://www.yoursite.com/api/resource' ,method:'get' ,data:{ username:'billyblanks' ,api_key:'5eb63bbbe01eeed093cb22bb8f5acdc3' ,title__startswith:"Hello World" } ,onSuccess: function( data ){ console.info( data.meta ); console.log( data.objects ):}).send();

http://www.yoursite.com/api/resource/1http://www.yoursite.com/api/resource/set/1;5http://www.yoursite.com/api/resource/?format=xml

Page 29: Meetup django common_problems(1)

• Validation Via Forms• Deep ORM Ties• Data Streaming• OAuth / contrib Auth• URI Templates• Auto API Docs

• Django-like• Built in fields• Auto Meta Data• Resource URIs• ORM ablities ( client )• API Key Auth• Object Caching

( backends )• De / Re hydrations hooks

PISTON TASTYPIEMultiple Formats

ThrottlingAll HTTP Methods

AuthenticationArbitrary Data Resources

Highly Configurable

Page 30: Meetup django common_problems(1)

READY IN MINUTES

Page 31: Meetup django common_problems(1)

DATABASE

Page 32: Meetup django common_problems(1)

QUERYSET-TRANSFORM

DJANGO-SELECTREVERSE

github.com/jbalogh/django-queryset-transform

code.google.com/p/django-selectreverse

DJANGO-SOUTHsouth.aeracode.org

Page 33: Meetup django common_problems(1)

SOUTH

Page 34: Meetup django common_problems(1)

SOUTHDatabase Migrations

Page 35: Meetup django common_problems(1)

DJANGO$ python manage.py syncdb

Page 36: Meetup django common_problems(1)

DJANGO$ python manage.py syncdb

>>> You have a new Database!

Page 37: Meetup django common_problems(1)

DJANGOclass MyModel( models.Model): relation = models.ForiegnKey( Model2 )

Page 38: Meetup django common_problems(1)

DJANGOclass MyModel( models.Model ): relation = models.ForiegnKey( Model2 )

class MyModel( models.Model ): relation = models.ManyToMany( Model2 )

Page 39: Meetup django common_problems(1)

DJANGO$ python manage.py syncdb

Page 40: Meetup django common_problems(1)

DJANGO$ python manage.py syncdb

>>> Sucks to be you!

Page 41: Meetup django common_problems(1)

WTF?!

Page 42: Meetup django common_problems(1)

DJANGO$ python manage.py syncdb

>>> Sucks to be you!

syncdb doesn't really sync your db. Migrations must be done manually.

• For everyedatabase / set up.

Problem:

Page 43: Meetup django common_problems(1)

SOUTHMigrations are a set of sequential .py filesdb agnosticHandle most relation typesRolls migrations forward Handles Dependancies / Reverse DependanciesCan convert existing apps

• Overrides existing syncdb command

Page 44: Meetup django common_problems(1)

DJANGOclass MyModel( models.Model ): relation = models.ForiegnKey( Model2 )

class MyModel( models.Model ): relation = models.ManyToMany( Model2 )

Page 45: Meetup django common_problems(1)

DJANGOclass MyModel( models.Model ): relation = models.ForiegnKey( Model2 )

class MyModel( models.Model ): relation = models.ManyToMany( Model2 )

Page 46: Meetup django common_problems(1)

SOUTH$ python manage.py schemamigration <yourapp>

>>> Sweet, run migrate

Page 47: Meetup django common_problems(1)

SOUTH$ python manage.py migrate <yourapp>

>>> Done.

Page 48: Meetup django common_problems(1)

SOUTH

Page 49: Meetup django common_problems(1)

QUERYSET-TRANSFORM

github.com/jbalogh/django-queryset-transform

( n + 1 )

Page 50: Meetup django common_problems(1)

QUERYSET-TRANSFORM{% for object in object_list %}

{% for object in object.things.all %} {% if object.relation %} {{ object.relation.field.text }} {% else %} {{ object.other_relation }} {% endif %} {% endfor %}

{% empty %} no soup for you{% endfor %}

Page 51: Meetup django common_problems(1)
Page 52: Meetup django common_problems(1)

QUERYSET-TRANSFORMdef lookup_tags(item_qs):

item_pks = [item.pk for item in item_qs] m2mfield = Item._meta.get_field_by_name('tags')[0] tags_for_item = \ Tag.objects.filter( item__in = item_pks) .extra(select = {'item_id': '%s.%s' % ( m2mfield.m2m_db_table(), m2mfield.m2m_column_name() ) }) tag_dict = {} for tag in tags_for_item: tag_dict.setdefault(tag.item_id, []).append(tag)

for item in item_qs: item.fetched_tags = tag_dict.get(item.pk, [])

Page 53: Meetup django common_problems(1)

QUERYSET-TRANSFORM

qs = Item.objects.filter(

name__contains = 'e'

).transform(lookup_tags)

Page 54: Meetup django common_problems(1)

QUERYSET-TRANSFORM

from django.db import connection

len( connection.queries )

>>> 2

Page 55: Meetup django common_problems(1)

DJANGO-SELECTREVERSEcode.google.com/p/django-selectreverse

Page 56: Meetup django common_problems(1)

DJANGO-SELECTREVERSE

model_instance.other_model_set.all()

Tries prefetching on reverse relations

Page 57: Meetup django common_problems(1)

CONTENT MANAGEMENT

Page 58: Meetup django common_problems(1)

DJANGO-CMS

SATCHMO

www.django-cms.org

www.satchmoproject.com

www.webcubecms.com

WEBCUBE-CMS

Page 59: Meetup django common_problems(1)

WEBCUBE-CMS

Page 60: Meetup django common_problems(1)

Feature Complete

WEBCUBE-CMS

Page 61: Meetup django common_problems(1)

Feature Complete

WEBCUBE-CMSRobust & Flexible

Page 62: Meetup django common_problems(1)

Feature Complete

WEBCUBE-CMSRobust & Flexible( Commercial License )

Page 63: Meetup django common_problems(1)

$12,000

Page 64: Meetup django common_problems(1)

$12,000

Page 65: Meetup django common_problems(1)
Page 66: Meetup django common_problems(1)

+ $300 / mo

Page 67: Meetup django common_problems(1)

WTF?!

Page 68: Meetup django common_problems(1)

DJANGO-CMS

Page 69: Meetup django common_problems(1)
Page 70: Meetup django common_problems(1)

• Heavily Customised Admin

• Plugin Support• Template Switching• Menu Control• Translations• Front-End Editing

( latest )• Moderation• Template Tags• Lots of settings

• Lots Of Settings ( again )

• Another Learning Curve• Plone Paradox• Plugins a little wonky

PRO CON

Page 71: Meetup django common_problems(1)

SATCHMO

Page 72: Meetup django common_problems(1)

SATCHMOE-Commerce-y CMS

Page 73: Meetup django common_problems(1)

Django Admin

Page 74: Meetup django common_problems(1)

DJANGO-GRAPPELLI

DJANGO-FILEBROWSE

code.google.com/p/django-grappelli

code.google.com/p/django-filebrowser

DJANGO-ADMIN TOOLSbitbucket.org/izi/django-admin-tools

Page 75: Meetup django common_problems(1)

GRAPPELLI

Page 76: Meetup django common_problems(1)

GRAPPELLI

Page 77: Meetup django common_problems(1)

GRAPPELLI

Page 78: Meetup django common_problems(1)

FILEBROWSER

Page 79: Meetup django common_problems(1)

FILEBROWSER

Page 80: Meetup django common_problems(1)

FILEBROWSER

Page 81: Meetup django common_problems(1)

FILEBROWSER

Page 82: Meetup django common_problems(1)

ADMIN TOOLS

Page 83: Meetup django common_problems(1)

ADMIN TOOLS

Page 84: Meetup django common_problems(1)

ADMIN TOOLS

Page 85: Meetup django common_problems(1)

Image Management

Page 86: Meetup django common_problems(1)

DJANGO-IMAGEKIT

DJANGO-PHOTOLOGUE

bitbucket.org/jdriscoll/django-imagekit

code.google.com/p/django-photologue

SORL-THUMBNAILthumbnail.sorl.net/

Page 87: Meetup django common_problems(1)

DJANGOclass MyModel( models.Model ): image = models.ImageField(upload_to='/' )

Page 88: Meetup django common_problems(1)

DJANGOclass MyModel( models.Model ): image = models.ImageField( upload_to='/' ) thumb = models.ImageField( upload_to='/' )

Page 89: Meetup django common_problems(1)

DJANGOclass MyModel( models.Model ): image = models.ImageField( upload_to='/' ) thumb = models.ImageField( upload_to='/' )

>>> MyModel.objects.get(pk=1)>>> MyModel.objects.image.url>>> MyModel.objects.thumb.url

Page 90: Meetup django common_problems(1)

ImageField

Page 91: Meetup django common_problems(1)

ImageFieldIt Kinda Sucks

Page 92: Meetup django common_problems(1)

IMAGEKITEvolution Of Photologue

Page 93: Meetup django common_problems(1)

IMAGEKITclass Photo( ImageModel ): name = models.CharField(max_length=100) image = models.ImageField(upload_to='photos') views = models.PositiveIntegerField(default=0)

class IKOptions: #define the ImageKit options spec_module = 'myapp.specs' cache_dir = 'photos' image_field = 'image' save_count_as = 'views'

Page 94: Meetup django common_problems(1)

IMAGEKITclass ResizeThumb( processors.Resize ): width = 100 height = 75 crop = True

class ResizeDisplay( processors.Resize ): width = 600

# now we can define our thumbnail specclass Thumbnail( ImageSpec ): access_as = 'thumbnail_image' pre_cache = True processors = [ ResizeThumb ]

class Display( ImageSpec ): increment_count = True processors = [ ResizeDisplay ]

Page 95: Meetup django common_problems(1)

IMAGEKIT

$ photo = Photo.objects.get( pk =1 )

$ photo.display.url>>> u'/path/to/media/photo_display.jpg'

$ photo.thumbnail.width>>> 100

Page 96: Meetup django common_problems(1)

• Only 1 Model• DB Friendly• Format Adjustment• Color Adjustment• Transposing

• Galleries out of the box• Bulk Upload• Admin Integration• Pre-cache command• Very DB Dependant• 4 Models ( 2 Solid )• Templates / Views / Urls• Exif Support

IMAGEKIT PHOTLOGUECaching

Template FriendlyHighly Configurable

Management Commands

Page 97: Meetup django common_problems(1)

EXIF TAGSISSUE 153

( shameless plug )

Page 98: Meetup django common_problems(1)

• Only 1 Model• DB Friendly• Format Adjustment• Color Adjustment• Transposing

• Galleries out of the box• Bulk Upload• Admin Integration• Pre-cache command• Very DB Dependant• 4 Models ( 2 Solid )• Exif Support

IMAGEKIT PHOTLOGUECaching

Template FriendlyHighly Configurable

Management Commands

Beware of View Counts

Page 99: Meetup django common_problems(1)

ImageField

Page 100: Meetup django common_problems(1)

ImageFieldIt's Kinda Messy

Page 101: Meetup django common_problems(1)

SORL

Page 102: Meetup django common_problems(1)

SORLfrom sorl.thumbnail import ImageField

class MyModel( models.Model ): iamge = ImageField( upload_to="/folder" )

Page 103: Meetup django common_problems(1)

SORL{% load thumbnail %}

{% thumbnail obj.image "1000x600" crop='top' as im %} <img src="{{ im.url }}" />

{% endthumbnail %}

Page 104: Meetup django common_problems(1)

MESSAGING

Page 105: Meetup django common_problems(1)

User - to - UserMessaging

Page 106: Meetup django common_problems(1)

DJANGO-POSTMAN

DJANGO-MESSAGES

bitbucket.org/psam/django-postman

code.google.com/p/django-messages

DJANGO-SMScode.google.com/p/django-sms

Page 107: Meetup django common_problems(1)

DJANGO-SMS

Page 108: Meetup django common_problems(1)

DJANGO-SMS1. User Enters Phone #2. User Selects Carrier

Page 109: Meetup django common_problems(1)

THATS IT

Page 110: Meetup django common_problems(1)

FREE

Page 111: Meetup django common_problems(1)

UTILS

Page 112: Meetup django common_problems(1)

DJANGO-EXTENSIONS

DEBUG-TOOLBAR

HOTSAUCE

github.com/django-extensions/django-extensions

github.com/robhudson/django-debug-toolbar

github.com/ericflo/django-paginationDJANGO-PAGINATION

( self plug )

DJANGO-MAINTENANCEMODEpypi.python.org/pypi/django-maintenancemode

DJANGO-GUARDIANgithub.com/lukaszb/django-guardian

Page 113: Meetup django common_problems(1)

DJANGO-EXTENSIONS

$ python manage.py dumpscript>>> your_app.py

$ python manage.py runscript>>> your_app.pyc

$ python manage.py runserver_plus>>> Debugger baked right in

$ python manage.py shell_plus>>> AutoLoad Models

$ python manage.py show_urls>>> /your/endpoint/:id project.app.views.view_func

21 Commands 4 Fields 2 Models 1 Admin Extension ( FK AutoComplete )

Page 114: Meetup django common_problems(1)

RUNSERVER_PLUS

Page 115: Meetup django common_problems(1)

DEBUG TOOLBAR

Page 116: Meetup django common_problems(1)

DEBUG TOOLBAR

Page 117: Meetup django common_problems(1)

MAINTENANCEMODE

Page 118: Meetup django common_problems(1)

MAINTENANCEMODEMAINTENANCE_MODE = True

Page 119: Meetup django common_problems(1)

MAINTENANCEMODEMAINTENANCE_MODE = True

Page 120: Meetup django common_problems(1)

MAINTENANCEMODEMAINTENANCE_MODE = True

Page 121: Meetup django common_problems(1)

HOTSAUCE

Page 122: Meetup django common_problems(1)

HOTSAUCEI Put That $*!T On Everything

Page 123: Meetup django common_problems(1)

HOTSAUCE

Page 124: Meetup django common_problems(1)

HOTSAUCE

Page 125: Meetup django common_problems(1)

HOTSAUCE

Model A

title

content

QueueItem

title

content

title

content

Model A

ChangeSet

ChangeSet

ChangeSet

ChangeSet

Page 126: Meetup django common_problems(1)

HOTSAUCE

Page 127: Meetup django common_problems(1)