Who is this fool?!A little about me
Graphic ArtPhotographyWeb DesignDjangoVFXJavaScriptPrint DesignSoftwareDigital MediaCSSPythonFlash / Flex
PERL & JavaScript
Django = HotPileOfAwesome( yes=True )Django.build_web_app( fast=True )
Django.make_an_app()>>> TrueDjango.log_in_user()>>> TrueDjango.comment_on_my_model()>>> TrueDjango.message_my_user(user='myuser')>>> TrueDjango.send_emails( emails=['me@mail.com'] )>>> TrueDjango.do_complex_SQL( please=True )>>> No Problem!
Django.make_a_thumbnail()>>> Thumbnail?Django.send_text_message()>>> Email Exception: no such thingDjango.search_all_my_stuff()>>> WTF?Django.get_data_in_under_75_queries()>>> Whoa...Django.alter_table(model='MyModel')>>> Let's not get crazyDjango.be_restful( now=True )>>> you meanrequest.POST
I've Got an app for that!
Searching
SearchingFind Stuff - Fast
SearchingFind Stuff - Fast( without crushing my DB )
Haystackhaystacksearch.orgDjapiancode.google.com/p/djapian/Sphinxdjango-sphinx ( github )
DjangoMyModel.objects.filter( text__icontains='word' )OR MyModel.objects.filter( text__search='word' )Problems:single model
slow
mysql
manual DB configsHaystackclassPostIndex( 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 ) defget_queryset( self ): return Post.objects.all() defprepare_url( self, obj ): return obj.get_absolute_url() site.register(Post, PostIndex)
HaystackSearchQuerySet().filter( SQ(field=True) | SQ(field__relation="something") ~SQ(field=False) )>>> [ <SearchResult>, <SearchResult>, <SearchResult> ]
XapianclassArticleIndexer( Indexer ):fields = ['title','body']tags = [('title','title', 3),('body', 'as_plain_text', 1)]space.add_index(Article, ArticleIndexer, attach_as='indexer')
Xapianfromdjapian.indexer import CompositeIndexerflags = xapian.QueryParser.FLAG_PARTIAL| \xapian.QueryParser.FLAG_WILDCARDindexers = [ 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>
HaystackXapianIndex filesClass Based IndexCustomize Text For IndexingLink to Indexed ObjectIndex Fields, Methods & RelationsStemming, Facetting, Highlighting, SpellingPluggable 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 FilteringREST API
REST APIExposing Your Data
REST APIExposing Your Data( In a meaningful way )
Djangodefview_func( reqeuest, *args, **kwargs): request.GET request.POST request.FILESProblems:PUT & DELETE not translated
Can't restrict access based on HTTP methods
Serialization is left up to you
Manual auth
Tons of URLsPISTONbitbucket.org/jespern/django-pistonTASTYPIEtoastdriven.github.com/django-tastypie/
PistonclassMyHandler( BaseHandler ): methods_allowed =( 'GET', 'PUT') model = MyModel classMyOtherHandler( BaseHandler ): methods_allowed =( 'GET', 'PUT') model = MyOtherModelfields = ('title','content',('author',('username',) ) )exclude = ('id', re.compile(r'^private_'))defread( self, request):return [ x for x in MyOtherModel.objects.select_related() ]defupdate( self, request ):...
TastypieclassMyResource( ModelResource ):fk_field = fields.ForiegnKey( OtherResource, 'fk_field' ) classMeta:authentication = ApiKeyAuthentication() queryset = MyModel.object.all()resource_name = 'resource'fields = ['title', 'content', ]allowed_methods = [ 'get' ]filtering = {'somfield': ('exact', 'startswith')}defdehydrate_FOO( self, bundle ):return bundle.data[ 'FOO' ] = 'What I want'
Tastypie - Client SidenewRequest.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
PISTONTASTYPIEMultiple FormatsThrottlingAll HTTP MethodsAuthenticationArbitrary Data ResourcesHighly ConfigurableDjango-like
Built in fields
Auto Meta Data
Resource URIs
ORM ablities ( client )
API Key Auth
Object Caching ( backends )
De / Re hydrations hooks
Validation Via Forms
Deep ORM Ties
Data Streaming
OAuth / contrib Auth
URI Templates
Auto API DocsREADY IN MINUTES
DATABASE
DJANGO-SOUTHsouth.aeracode.orgQUERYSET-TRANSFORMgithub.com/jbalogh/django-queryset-transformDJANGO-SELECTREVERSEcode.google.com/p/django-selectreverse
SOUTH
SOUTHDatabase Migrations
DJANGO$ python manage.py syncdb
DJANGO$ python manage.py syncdb>>> You have a new Database!
DJANGOclassMyModel( models.Model):relation = models.ForiegnKey( Model2 )
DJANGOclassMyModel( models.Model ):relation = models.ForiegnKey( Model2 )classMyModel( models.Model ):relation = models.ManyToMany( Model2 )
DJANGO$ python manage.py syncdb
DJANGO$ python manage.py syncdb>>> Sucks to be you!
WTF?!
DJANGO$ python manage.py syncdb>>> Sucks to be you!Problem:syncdb doesn't really sync your db. Migrations must be done manually.For everyedatabase / set up.SOUTHMigrations are a set of sequential .py filesdb agnosticHandle most relation typesRolls migrations forward Handles Dependancies / Reverse DependanciesCan convert existing apps Overrides existing syncdb commandDJANGOclassMyModel( models.Model ):relation = models.ForiegnKey( Model2 )classMyModel( models.Model ):relation = models.ManyToMany( Model2 )
DJANGOclassMyModel( models.Model ):relation = models.ForiegnKey( Model2 )classMyModel( models.Model ):relation = models.ManyToMany( Model2 )
SOUTH$ python manage.py schemamigration <yourapp>>>> Sweet, run migrate
SOUTH$ python manage.py migrate <yourapp>>>> Done.
SOUTH
QUERYSET-TRANSFORMgithub.com/jbalogh/django-queryset-transform( n + 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%}
QUERYSET-TRANSFORMdeflookup_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, [])
QUERYSET-TRANSFORMqs = Item.objects.filter(name__contains = 'e').transform(lookup_tags)
QUERYSET-TRANSFORMfrom django.db import connectionlen( connection.queries )>>> 2
DJANGO-SELECTREVERSEcode.google.com/p/django-selectreverse
DJANGO-SELECTREVERSETries prefetching on reverse relationsmodel_instance.other_model_set.all()
CONTENT MANAGEMENT
DJANGO-CMSwww.django-cms.orgWEBCUBE-CMSwww.webcubecms.comSATCHMOwww.satchmoproject.com
WEBCUBE-CMS
WEBCUBE-CMSFeature Complete
WEBCUBE-CMSFeature CompleteRobust & Flexible
WEBCUBE-CMSFeature CompleteRobust & Flexible( Commercial License )
$12,000
$12,000
+ $300 / mo
WTF?!
DJANGO-CMS
PROCONHeavily 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 wonkySATCHMO
SATCHMOE-Commerce-y CMS
Django Admin
DJANGO-GRAPPELLIcode.google.com/p/django-grappelliDJANGO-FILEBROWSEcode.google.com/p/django-filebrowserDJANGO-ADMIN TOOLSbitbucket.org/izi/django-admin-tools
GRAPPELLI
GRAPPELLI
GRAPPELLI
FILEBROWSER
FILEBROWSER
FILEBROWSER
FILEBROWSER
ADMIN TOOLS
ADMIN TOOLS
ADMIN TOOLS
Image Management
DJANGO-IMAGEKITbitbucket.org/jdriscoll/django-imagekitDJANGO-PHOTOLOGUEcode.google.com/p/django-photologueSORL-THUMBNAILthumbnail.sorl.net/
DJANGOclassMyModel( models.Model ):image = models.ImageField(upload_to='/' )
DJANGOclassMyModel( models.Model ):image = models.ImageField( upload_to='/' )thumb = models.ImageField( upload_to='/' )

Meetup django common_problems(1)