Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Writing a Django e-commerce framework

Writing a Django e-commerce framework

From OSCON 2012. This presentation discusses the reasons for writing an e-commerce framework and details a number of techniques for customising Django apps.

David Winterbottom

July 18, 2012
Tweet

More Decks by David Winterbottom

Other Decks in Programming

Transcript

  1. Writing  a  Django  
    e-­‐commerce  
    framework
    OSCON  2012
    Friday, 20 July 12

    View full-size slide

  2. Me
    •David  Winterbottom  /  @codeinthehole
    •Tangent  Labs,  London
    •Head  of  E-­‐commerce  team
    •Python  hacker
    •commandlinefu.com,  django-­‐oscar
    Friday, 20 July 12

    View full-size slide

  3. Synopsis
    •Motivation
    •Oscar  -­‐  what  problem  does  it  solve?
    •Design  decisions  -­‐  customisation  techniques
    •E-­‐commerce  tips/advice
    Friday, 20 July 12

    View full-size slide

  4. Motivation
    Friday, 20 July 12

    View full-size slide

  5. •5  years  of  e-­‐commerce  projects
    •PHP  =>  Python  /  Django
    •Lots  of  war  stories
    Tangent  Labs
    Friday, 20 July 12

    View full-size slide

  6. Books
    Friday, 20 July 12

    View full-size slide

  7. Bookshop  domain
    •Millions  of  products
    •ISBNs,  BIC/BISAC  categories,  authors,  publishers
    •Automated  feed-­‐driven  processing
    •Catalogue
    •Stock
    •Rich  data
    Friday, 20 July 12

    View full-size slide

  8. Two  tier  structure
    •Application  tier  -­‐  serves  HTTP  requests
    •Processing  tier:
    •Download  and  import  feeds
    •Data  cleaning  and  processing
    •Periodic  jobs  for  fulfilment
    Friday, 20 July 12

    View full-size slide

  9. Variations
    •New  fulfilment  partners
    •Stock/availability  logic
    •Multiple  payment  partners
    •Split-­‐payment  sources
    •Multibuy  offers,  vouchers
    •eBooks!
    Friday, 20 July 12

    View full-size slide

  10. PHP  framework
    •Home-­‐rolled  web  framework
    •Customisation  via  include  path  overrides
    •Lots  of  duplication
    •Hard  to  upgrade
    Friday, 20 July 12

    View full-size slide

  11. Nailvarnish
    Friday, 20 July 12

    View full-size slide

  12. T-­‐shirts
    Friday, 20 July 12

    View full-size slide

  13. Digital  music
    Friday, 20 July 12

    View full-size slide

  14. Bar  equipment
    Friday, 20 July 12

    View full-size slide

  15. New  requirements
    •Product  variations  -­‐  colours,  sizes  etc
    •New  fulfilment  processes:  
    •webservices  /  warehouses
    •Per-­‐customer  prices
    Friday, 20 July 12

    View full-size slide

  16. B2B
    •Sales  reps,  customer  hierarchies
    •Tax  rules
    •Managed  budgets
    •Integration  with  “enterprise”  partners
    Friday, 20 July 12

    View full-size slide

  17. •Original  assumptions  all  broken
    •Domains  vary  wildly
    •Lots  of  work-­‐arounds
    Friday, 20 July 12

    View full-size slide

  18. Oscar
    Friday, 20 July 12

    View full-size slide

  19. Requirements
    •Lean  -­‐  as  few  assumptions  as  possible
    •Models  domain  
    •without  duplication
    •without  too  much  meta-­‐data
    Friday, 20 July 12

    View full-size slide

  20. Friday, 20 July 12

    View full-size slide

  21. Domain  modelling
    •Implementation  deeply  
    connected  to  core  business  
    concepts
    •“...where  powerful  new  
    features  unfold  as  corollaries  to  
    older  features.”
    Friday, 20 July 12

    View full-size slide

  22. Friday, 20 July 12

    View full-size slide

  23. Lots  of  others
    •Satchmo  
    •Lightning-­‐Fast-­‐Shop
    •Satchless
    •Django-­‐shop
    •Plata,  Mamona,  Cartridge,  ...
    •http://djangopackages.com/grids/g/ecommerce/
    Friday, 20 July 12

    View full-size slide

  24. Design  decisions
    Friday, 20 July 12

    View full-size slide

  25. Python
    •Decimal  support
    •**kwargs
    •Mixins
    Friday, 20 July 12

    View full-size slide

  26. Friday, 20 July 12

    View full-size slide

  27. Web  framework
    •Well-­‐thought  out  structure
    •Templating,  HTTP,  security,  caching,  ...
    •Class-­‐based  views
    Friday, 20 July 12

    View full-size slide

  28. Models
    •Models  drive  the  design
    •Capture  domain  logic
    •Foundation  for  rest  of  application
    Friday, 20 July 12

    View full-size slide

  29. Eco-­‐system
    •Haystack  (search)
    •South  (database  migrations)
    •Celery  (job  queue)
    •Internal  libraries
    Friday, 20 July 12

    View full-size slide

  30. Customisation
    Friday, 20 July 12

    View full-size slide

  31. DEBUG = True
    settings.py
    Friday, 20 July 12

    View full-size slide

  32. AUTH_PROFILE_MODULE =
    ‘customer.Profile’
    settings.py
    Friday, 20 July 12

    View full-size slide

  33. Different  approach
    •Key  idea:
    •Having  the  same  name/identifier  as  your  parent  
    •Subclass  and  override
    Friday, 20 July 12

    View full-size slide

  34.  Templates
    Friday, 20 July 12

    View full-size slide

  35. Friday, 20 July 12

    View full-size slide

  36. TEMPLATE_LOADERS = (
    'django.template.loaders.filesystem.Loader',
    'django.template.loaders.app_directories.Loader',
    )
    TEMPLATE_DIRS = (
    '/var/www/project/templates/',
    )
    Replace
    Friday, 20 July 12

    View full-size slide

  37. TEMPLATE_LOADERS = (
    'django.template.loaders.filesystem.Loader',
    'django.template.loaders.app_directories.Loader',
    )
    TEMPLATE_DIRS = (
    '/var/www/project/templates/'
    '/path/to/oscar/',
    )
    Override
    parent  of  Oscar’s  
    template  directory
    Friday, 20 July 12

    View full-size slide

  38. # base.html
    {% extends 'templates/base.html' %}
    {% block scripts %}

    {% endblock %}
    Override
    Friday, 20 July 12

    View full-size slide

  39. # base.html
    {% extends 'templates/base.html' %}
    {% block scripts %}

    {{ block.super }}
    {% endblock %}
    Extend
    Friday, 20 July 12

    View full-size slide

  40. Recap
    •Filename  is  the  ID
    •Use  include-­‐path  trick  to  “subclass”  parent  
    •Use  blocks  to  provide  hook  points
    •...but,  don’t  go  too  far
    Friday, 20 July 12

    View full-size slide

  41. Apps
    Friday, 20 July 12

    View full-size slide

  42. from django.db.loading import get_model
    Line = get_model('basket', 'Line')
    Dynamic  loading  1
    INSTALLED_APPS = (
    'oscar.apps.basket'
    )
    Friday, 20 July 12

    View full-size slide

  43. from django.db.loading import get_model
    Line = get_model('basket', 'Line')
    Dynamic  loading  1
    INSTALLED_APPS = (
    'oscar.apps.basket'
    )
    ‘App  label’
    Friday, 20 July 12

    View full-size slide

  44. INSTALLED_APPS = (
    'oscar',
    'oscar.apps.catalogue',
    'oscar.apps.basket',
    'oscar.apps.checkout',
    'oscar.apps.order',
    ...
    )
    Friday, 20 July 12

    View full-size slide

  45. INSTALLED_APPS = (
    'oscar',
    'oscar.apps.catalogue',
    'myproject.basket',
    'oscar.apps.checkout',
    'oscar.apps.order',
    ...
    )
    Same  app  label  as  
    parent  app
    Friday, 20 July 12

    View full-size slide

  46. # myproject/basket/models.py
    from django.db import models
    from oscar.apps.basket.abstract_models import \
    AbstractLine
    class Line(AbstractLine):
    cost_centre = models.CharField(max_length=64)
    from oscar.apps.basket.models import *
    Friday, 20 July 12

    View full-size slide

  47. INSTALLED_APPS = (
    'oscar',
    'oscar.apps.catalogue',
    'oscar.apps.basket',
    'oscar.apps.checkout',
    'oscar.apps.order',
    ...
    )
    templatetags
    management  commands
    Friday, 20 July 12

    View full-size slide

  48. Recap
    •App  label    is  the  ID
    •Models  can  overridden  and  extended
    Friday, 20 July 12

    View full-size slide

  49. from oscar.core.loading import get_class
    OrderCreator = get_class('order.utils', 'OrderCreator')
    Dynamic  loading  2
    Friday, 20 July 12

    View full-size slide

  50. # order/utils.py
    from oscar.apps.order.utils import OrderCreator as \
    CoreOrderCreator
    class OrderCreator(CoreOrderCreator):
    def allocate_stock(self, line):
    # Override/extend method
    ...
    Friday, 20 July 12

    View full-size slide

  51. Recap
    •(App  module,  class  name)    is  the  ID
    •Any  class  can  be  overridden  or  extended
    Friday, 20 July 12

    View full-size slide

  52. Tips  and  advice
    Friday, 20 July 12

    View full-size slide

  53. Log  everything
    ...except  sensitive  customer  details.
    Friday, 20 July 12

    View full-size slide

  54. Audit  models
    Friday, 20 July 12

    View full-size slide

  55. from django.db import models
    class NielsenDataFile(models.Model):
    filepath = models.CharField(max_length=128)
    PENDING, FAILED, PROCESSED = range(3)
    status = models.IntegerField(default=PENDING)
    num_valid_records = models.IntegerField()
    num_invalid_records = models.IntegerField()
    date_downloaded = models.DateTimeField(null=True)
    date_processed = models.DateTimeField(null=True)
    Friday, 20 July 12

    View full-size slide

  56. •High  and  low  thresholds
    •It’s  always  your  fault  when  things  go  wrong
    Monitor  everything
    Friday, 20 July 12

    View full-size slide

  57. Service  layers
    •Avoid  views  talking  to  your  models  directly
    •See  ‘Facade’  design  pattern
    •Anti-­‐corruption  layers
    Friday, 20 July 12

    View full-size slide

  58. Generic  vs  bespoke
    •“If  you’re  using  a  framework,  you  aren’t  doing  good  
    modelling”
    •Capture  the  domain  correctly  
    •It’s  ok  to  throw  away  the  framework
    Friday, 20 July 12

    View full-size slide

  59. Summary
    •Django  is  great  for  modelling  complex  domains
    •Writing  customisable  django  apps  isn’t  easy
    •Oscar’s  future:  
    •NoSQL  -­‐  no  more  EAV
    Friday, 20 July 12

    View full-size slide

  60. Image  credits
    Books:
    http://www.flickr.com/photos/th3ph17/3091294342/
    Nail varnish:
    http://www.flickr.com/photos/kqedquest/831547339/
    T-shirts:
    http://www.flickr.com/photos/blazerman/177165473/
    Friday, 20 July 12

    View full-size slide