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

Oscar and the Art of Transactional Django Applications

Oscar and the Art of Transactional Django Applications

Oscar is a Django e-commerce framework designed for flexibility. Based on years of hard-earned experience, it employs a range of techniques that allow developers to customise any part of the core. In this way it can be used to build a diverse array of transactional applications. This talk will examine Oscar and the techniques it employs for deep customisation. Further, common patterns of robust e-commerce applications will be examined.

David Winterbottom

January 06, 2015
Tweet

More Decks by David Winterbottom

Other Decks in Programming

Transcript

  1. Only special customers can see those products Sales reps can

    pay for multiple orders with one payment Sometimes you only pay tax on half a product!
  2. Raison d'être • Make my life easier • Help Tangent

    be more efficient • Build complex, maintainable 
 e-commerce sites
  3. My current platform is too slow My current platform won’t

    let me do X I hate my current platform!
  4. >>> strategy = selector.strategy(request) >>> info = strategy.fetch_for_product(
 product) >>>

    info.price.incl_tax
 Decimal(’22.60')
 >>> info.price.currency
 'GBP' >>> info.availability.message
 "In stock" >>> info.availability.is_available_to_buy
 True
  5. from django.conf.urls import patterns, include from django.contrib import admin admin.autodiscover()

    urlpatterns = patterns('', (r'^admin/', include(admin.site.urls)), )
  6. from django.conf.urls import patterns, include from django.contrib import admin admin.autodiscover()

    urlpatterns = patterns('', (r'^admin/', include(admin.site.urls)), )
  7. from django.conf.urls import * from oscar.app import application urlpatterns =

    patterns('', url(r'', include(application.urls)) )
  8. from django.conf.urls import * from oscar.app import application urlpatterns =

    patterns('', url(r'', include(application.urls)) )
  9. from oscar.core.application import Application class Shop(Application): catalogue_app = get_class('catalogue.app', 'application')

    ... def get_urls(self): urls = [ url(r'^catalogue/', include(self.catalogue_app.urls)), ... ] return urls application = Shop()
  10. from oscar.apps.checkout import app from . import views class CheckoutApplication(app.CheckoutApplication):

    # Replace a view class payment_details_view = views.PaymentDetailsView def get_urls(self): # Tinker with URLs etc ...
  11. Oscar • For difficult e-commerce problems • Designed for flexibility

    • Anything can be customised • Customisation techniques drawn from Django itself
  12. from django.db import models class PartnerFeedFile(models.Model): filename = models.CharField(max_length=255) PENDING,

    PROCESSED, FAILED = ( 'Pending', 'Processed', 'Failed') STATUSES = ( (PENDING, PENDING), (PROCESSED, PROCESSED), (FAILED, FAILED), ) status = models.CharField( max_length=64, choices=STATUSES, default=PENDING) num_records = models.PositiveIntegerField() date_start_processing = models.DateTimeField(null=True) date_end_processing = models.DateTimeField(null=True)
  13. from django.db import models class RequestResponse(models.Model): ... raw_request = models.TextField(max_length=512)

    raw_response = models.TextField(max_length=512) response_time = models.FloatField() date_created = models.DateTimeField( auto_now_add=True)
  14. from django.db import transaction def external_api_call(request): # 1. Save something

    # 2. Make an API call and save audit # 3. Save something else
  15. from django.db import transaction def external_api_call(request): Foo.objects.create(name="Before") with transaction.atomic(): #

    Make some external API call AuditModel.objects.create(...) Foo.objects.create(name="After")
  16. DATABASES = { 'default': { ... 'ATOMIC_REQUESTS': True } }

    db = DATABASES['default'].copy() db['ATOMIC_REQUESTS'] = False DATABASE['autocommit'] = db
  17. Boundaries • REST interface? • Never… • …modify a model

    field • …call save() dabapps.com/blog/django-models-and-encapsulation/