Moving from Django Apps to Services

  • 776 views
Uploaded on

Slides from a talk on moving from Django applications to using services which enable better maintainability and scaling.

Slides from a talk on moving from Django applications to using services which enable better maintainability and scaling.

  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
776
On Slideshare
0
From Embeds
0
Number of Embeds
0

Actions

Shares
Downloads
15
Comments
0
Likes
3

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. Django Apps to Services
  • 2. Craig Kerstiens @craigkerstiens work at @heroku
  • 3. DjangoProject A collection of configuration and apps for a particular Website. (per Django Project)
  • 4. DjangoProject A collection of configuration and apps for a particular Website.App A web application that does something. I.e. Weblog, Poll, Ticket system (per Django Project)
  • 5. TableTable Table Table Table Table Table Table Table TableTable Table Table TableTable Table Table Table Table Table Table
  • 6. TableTable Table Table Table Table Table Table Table TableTable Table Table TableTable Table Table Table Table Table Table
  • 7. TableTable Table Table p Table Table Table p Table A Table TableTable Table Table TableTable Table Table Table Table Table Table
  • 8. Monolithic Monster
  • 9. Monolithic Monster$ ls mysitemodels.pyviews.pyforms.pyadmin.py
  • 10. Monolithic Monster$ ls mysite $ wc -l models.pymodels.py 2557 models.pyviews.py $ wc -l view.spyforms.py 14241 views.pyadmin.py
  • 11. Monolithic Monster $ ls mysite $ wc -l models.py models.py 2557 models.py views.py $ wc -l view.spy forms.py 14241 views.py admin.pyhttp://www.slideshare.net/jacobian/the-best-and-worst-of-django
  • 12. Within Django
  • 13. Within DjangoProject
  • 14. Within DjangoProject App App App
  • 15. Within DjangoProject Tickets App FAQ App FaqCreator App
  • 16. Within Django cd myproject && find . manage.pyProject requirements.txt settings.py urls.py ./faq/admin.py ./faq/forms.py Tickets App ./faq/models.py ./faq/urls.py ./faq/views.py ./faqcreator/admin.py FAQ App ./faqcreator/forms.py ./faqcreator/models.py ./faqcreator/urls.py ./faqcreator/views.py ./tickets/admin.py FaqCreator App ./tickets/forms.py ./tickets/models.py ./tickets/urls.py ./tickets/views.py
  • 17. Reusability
  • 18. cd myproject && find . Reusability
  • 19. cd myproject && find . Reusability manage.py requirements.txt settings.py urls.py ./faq/admin.py ./faq/forms.py ./faq/models.py ./faq/urls.py ./faq/views.py ./faqcreator/admin.py ./faqcreator/forms.py ./faqcreator/models.py ./faqcreator/urls.py ./faqcreator/views.py ./tickets/admin.py ./tickets/forms.py ./tickets/models.py ./tickets/urls.py ./tickets/views.py
  • 20. cd myproject && find . Reusability cd myproject && find . manage.py requirements.txt manage.py settings.py requirements.txt urls.py settings.py ./faq/admin.py urls.py --> ./faq/forms.py ./faq/models.py cat myproject/requirements.txt ./faq/urls.py ./faq/views.py faq==0.1 ./faqcreator/admin.py faqcreator==0.1 ./faqcreator/forms.py tickets==0.1 ./faqcreator/models.py ./faqcreator/urls.py ./faqcreator/views.py ./tickets/admin.py ./tickets/forms.py ./tickets/models.py ./tickets/urls.py ./tickets/views.py
  • 21. REUSABILITY means faster features due to DRY(Don’t Repeat Yourself )
  • 22. REUSABILITY means faster features due to DRY(Don’t Repeat Yourself )REUSABILITY does not always mean SCALABILITYor MAINTAINABILITY
  • 23. DjangoProject A collection of configuration and apps for a particular Website.App A web application that does something. I.e. Weblog, Poll, Ticket system (per Django Project)
  • 24. DjangoProject A collection of configuration and apps for a particular Website.App A web application that does something. I.e. Weblog, Poll, Ticket systemService Method of communication over the web. Web APIs allow combination of multiple services
  • 25. Tech imitate TeamsProject Company Tickets App Support FAQ App Knowledge Base FaqCreator App
  • 26. Teams SupportKnowledge Base
  • 27. Teams Grow App Support AppKnowledge Base
  • 28. Teams Grow App Support AppKnowledge Base Billing
  • 29. Teams Grow App Support Marketing AppKnowledge Base Billing
  • 30. Teams Grow App Support Marketing API AppKnowledge Base Analytics Front End Billing Mobile Social
  • 31. Apps Grow App Support Marketing API p s App A pKnowledge Base Analytics Front End3 App Billing Mobile Social
  • 32. Apps Grow App Support p App s Marketing App API A p 9 AppKnowledge Base App Analytics App Front End App Billing App Mobile App Social
  • 33. Apps Grow Support p s Marketing API Ap seKnowledge Base 9 deb a Analytics Front End Billing C o Mobile Social 1
  • 34. SOA To the Rescue
  • 35. SOA To the Rescue
  • 36. SOA To the Rescue Photo by Paul Downey (psd on flickr)
  • 37. ServiceDefined contract for communicating
  • 38. ServiceDefined contract for communicating$ curl -O $FAQ_API/create/ -X “question=my question source=123”
  • 39. In Python
  • 40. In Pythondata = { ‘question’: “my question”, ‘source’: 123}requests.POST(os.environ[‘FAQ_API’] + ‘/create/’, data=data)
  • 41. More than just API
  • 42. More than just APIwww.google.com
  • 43. More than just APIwww.google.commail.google.com
  • 44. More than just APIwww.google.commail.google.comcalendar.google.com
  • 45. More than just APIwww.google.commail.google.comcalendar.google.com..............google.com
  • 46. Types of Services
  • 47. Types of Servicessite
  • 48. Types of Servicessitesubdomain
  • 49. Types of ServicessitesubdomainAPI
  • 50. Types of ServicessitesubdomainAPI - no auth required
  • 51. Types of ServicessitesubdomainAPI - no auth required - API auth required
  • 52. Types of ServicessitesubdomainAPI - no auth required - API auth required - user auth required
  • 53. Where to Start App Support App Marketing App API AppKnowledge Base App Analytics App Front End App Billing App Mobile App Social
  • 54. Where to Start App Support App Marketing API AppKnowledge Base Analytics Front End Billing Mobile App Social
  • 55. 1 JavascriptMany pages
  • 56. LA POSTA
  • 57. Within Django cd myproject && find . manage.pyProject requirements.txt settings.py urls.py ./faq/admin.py ./faq/forms.py Tickets App ./faq/models.py ./faq/urls.py ./faq/views.py ./faqcreator/admin.py FAQ App ./faqcreator/forms.py ./faqcreator/models.py ./faqcreator/urls.py ./faqcreator/views.py ./tickets/admin.py FaqCreator App ./tickets/forms.py ./tickets/models.py ./tickets/urls.py ./tickets/views.py
  • 58. Apps Depend on Other Apps
  • 59. Apps Depend on Other Appsfaq creator
  • 60. Apps Depend on Other Appsfaq creator faq app
  • 61. Apps Depend on Other Appsfaq creator faq appticket
  • 62. Apps Depend on Other Appsfaq creator faq appticket faq app
  • 63. Apps Depend on Other Appsfaq creator faq app version == 0.1ticket faq app version == 0.2
  • 64. Apps Depend on Other Appspip install faq==0.1pip install faq==0.2pip freezefaq==0.2
  • 65. Apps Depend on Other Appsfaq creator faq app version == 0.1ticket faq app version == 0.2
  • 66. Back to APIs
  • 67. What’s a serviceProvider API_HOST= http://127.0.0.1
  • 68. What’s a serviceProvider API_HOST= http://127.0.0.1Endpoint /v1/create/
  • 69. What’s a serviceProvider API_HOST= http://127.0.0.1Endpoint /v1/create/Contract { ‘question’: ‘foo bar’, ‘source’: 123 }
  • 70. App
  • 71. AppURLs Views Models
  • 72. AppURLs Views Models ServiceProvider Endpoint Contract
  • 73. A SERVICE means REUSABILITYand enables SCALABILITY andMAINTAINABILITY
  • 74. Where to start
  • 75. Where to start1. If you’re monolithic, break up the apps first
  • 76. Where to start1. If you’re monolithic, break up the apps first2. Port something that doesn’t require user
  • 77. Where to start1. If you’re monolithic, break up the apps first2. Port something that doesn’t require user3. Port where you have many dependencies
  • 78. Porting an App models.pyclass Faq(models.Model): title = models.CharField(max_length=100) source = models.IntegerField(blank=True, null=True) description = models.TextField() solution = models.TextField() def __unicode__(self): return self.title
  • 79. Porting an App faqcreator/views.pyfrom faq.models import faqi = Faq(title=‘foo’, description=‘bar’, solution=’la posta’)i.save()
  • 80. Turn it into an API
  • 81. Turn it into an API1. pip install django-tastypie
  • 82. Turn it into an API1. pip install django-tastypie2. add tastypie to INSTALLED_APPS
  • 83. Turn it into an API1. pip install django-tastypie2. add tastypie to INSTALLED_APPS3. define your APIs
  • 84. Create your APIfrom faq/api.py tastypie.resources import ModelResourcefrom faq.models import Faqfrom django.contrib.auth.models import Userfrom tastypie.authentication import BasicAuthentication, DjangoAuthorizationfrom tastypie.authorization import Authorizationclass FaqResource(ModelResource): class Meta: queryset = Faq.objects.all() resource_name = faq list_allowed_methods = [get, post] authentication = BasicAuthentication() authorization = Authorization() def obj_create(self, bundle, request=None, **kwargs): return super(FaqResource, self).obj_create(bundle, request, user=request.user) def apply_authorization_limits(self, request, object_list): return object_list.filter(user=request.user)
  • 85. Create your API api.pyclass FaqResource(ModelResource): class Meta: queryset = Faq.objects.all() resource_name = faq list_allowed_methods = [get, post] authentication = BasicAuthentication() authorization = Authorization() def obj_create(self, bundle, request=None, **kwargs): return super(FaqResource, self).obj_create( bundle, request, user=request.user) def apply_authorization_limits(self, request, object_list): return object_list.filter(user=request.user)
  • 86. Create your API api.pyclass FaqResource(ModelResource): class Meta: queryset = Faq.objects.all() resource_name = faq list_allowed_methods = [get, post] authentication = BasicAuthentication() authorization = Authorization() def obj_create(self, bundle, request=None, **kwargs): return super(FaqResource, self).obj_create( bundle, request, user=request.user) def apply_authorization_limits(self, request, object_list): return object_list.filter(user=request.user)
  • 87. Create your API api.pyclass FaqResource(ModelResource): class Meta: queryset = Faq.objects.all() resource_name = faq list_allowed_methods = [get, post] authentication = BasicAuthentication() authorization = Authorization() def obj_create(self, bundle, request=None, **kwargs): return super(FaqResource, self).obj_create( bundle, request, user=request.user) def apply_authorization_limits(self, request, object_list): return object_list.filter(user=request.user)
  • 88. Create your API api.pyclass FaqResource(ModelResource): class Meta: queryset = Faq.objects.all() resource_name = faq list_allowed_methods = [get, post] authentication = BasicAuthentication() authorization = Authorization() def obj_create(self, bundle, request=None, **kwargs): return super(FaqResource, self).obj_create( bundle, request, user=request.user) def apply_authorization_limits(self, request, object_list): return object_list.filter(user=request.user)
  • 89. Create your API api.pyclass FaqResource(ModelResource): class Meta: queryset = Faq.objects.all() resource_name = faq list_allowed_methods = [get, post] authentication = BasicAuthentication() authorization = Authorization() def obj_create(self, bundle, request=None, **kwargs): return super(FaqResource, self).obj_create( bundle, request, user=request.user) def apply_authorization_limits(self, request, object_list): return object_list.filter(user=request.user)
  • 90. Create your API api.pyclass FaqResource(ModelResource): class Meta: queryset = Faq.objects.all() resource_name = faq list_allowed_methods = [get, post] authentication = BasicAuthentication() authorization = Authorization() def obj_create(self, bundle, request=None, **kwargs): return super(FaqResource, self).obj_create( bundle, request, user=request.user) def apply_authorization_limits(self, request, object_list): return object_list.filter(user=request.user)
  • 91. Create your API urls.pyfrom faq.api import FaqResourcefrom tastypie.api import Apiv1_api = Api(api_name=v1)v1_api.register(FaqResource())urlpatterns = patterns(, url(r^api/, include(v1_api.urls)),)
  • 92. Use your APIcurl -H "Content-Type: application/json" --user admin:testing -X POST --data {"title": "New FAQ", "source": "1", "description": "foo", "solution": "bar"} http://127.0.0.1:8000/api/v1/faq/
  • 93. Use it in Python
  • 94. Use it in Pythondata = { title: New FAQ, source: 1, description: foo, solution: bar}r = requests.post(os.environ[‘FAQ_API’] + "api/v1/faq/", data=data, auth=(admin, testing))
  • 95. Version Bump
  • 96. Version Bumpdata = { title: New FAQ, source: 1, description: foo, solution: bar, related: [123, 456]}r = requests.post(os.environ[‘FAQ_API’] + "api/v2/faq/", data=data, auth=(admin, testing))
  • 97. Version Bump
  • 98. Version Bumpdata = { title: New FAQ, source: 1, description: foo, solution: bar, related: [123, 456]}r = requests.post(os.environ[‘FAQ_API’] + "api/v2/faq/", data=data, auth=(admin, testing))
  • 99. In our Applicationfaq_creator/views.py ticket/views.py
  • 100. In our Application faq_creator/views.pyr = requests.post(os.environ[‘FAQ_API’] + "api/v2/faq/", data=data, auth=(admin, testing)) ticket/views.pyr = requests.post(os.environ[‘FAQ_API’] + "api/v1/faq/", data=data, auth=(admin, testing))
  • 101. cd myproject && find . Reusability cd myproject && find . manage.py requirements.txt manage.py settings.py requirements.txt urls.py settings.py ./faq/admin.py urls.py --> ./faq/forms.py ./faq/models.py cat myproject/requirements.txt ./faq/urls.py ./faq/views.py faq==0.1 ./faqcreator/admin.py faqcreator==0.1 ./faqcreator/forms.py tickets==0.1 ./faqcreator/models.py ./faqcreator/urls.py ./faqcreator/views.py ./tickets/admin.py ./tickets/forms.py ./tickets/models.py ./tickets/urls.py ./tickets/views.py
  • 102. Maintainability/Scalability/Agilitycd myproject && find . ls projects manage.py faq-service requirements.txt myproject settings.py cd faq-service && find . urls.py manage.py requirements.txtcat myproject/requirements.txt faq==0.1 --> settings.py urls.py cd myproject && find . faqcreator==0.1 tickets==0.1 manage.py requirements.txt settings.py urls.py cat myproject/requirements.txt faqcreator==0.1 tickets==0.1
  • 103. Maintainability/Scalability/Agility
  • 104. Maintainability/Scalability/Agility Faq Project - Its own Django project - 1 Django app - Own database - Own deployment
  • 105. Maintainability/Scalability/AgilityMy Project Faq Project - Contained Django Project - Its own Django project - 2 Django apps - 1 Django app - Own database - Own database - Own deployment - Own deployment
  • 106. Take aways
  • 107. Take aways1. Start non-critical (Cheat)2. Create services where theres app reuse3. Create services where theres pain4. Start small
  • 108. Others
  • 109. Others1. Expect APIs to fail2. Flask is great for APIs3. Make it easy to setup/test
  • 110. Fin. Resourceshttp://www.craigkerstiens.comhttp://bit.ly/djangoappstoservices/http://www.12factor.nethttp://github.com/craigkerstiens/