Your SlideShare is downloading. ×
0
The Three line MVC    application  and introducing Giotto
Table on contentsFirst part: Why high level code organization schemes areimportantSecond part: All about MVCThird Part: Gi...
My experiences1. Started web development in 20072. Wrote code without any kind of architectural pattern at all3. This was ...
Non-MVC code
Flightlogg.in            Was originally PHP (non-MVC)            Now is django (mostly MVC) View: HTML/Javascript Controll...
Why?1. Flexibility2. Organization
Imagine...1 app1 django view, 9000 lines of code
Imagine...We want to fix this. Refactor!!step 1:   1000 functions, 9 lines each
Imagine...step 2:   100 classes, 10 functions each
And then...App Models  class  class Views  class  class Controllers  class  class
Overview1. Models - The application2. Controllers - The interface   a. ties your application (model) to the outside world3...
Models1. Usually the biggest part of your application2. Business Logic3. Not just database tables4. Should be completely c...
Views1. All about formatting output from model.2. Templates/HTML3. Serializers4. Should be independent of any controllers ...
Controllers1. How the data gets to and from the user2. Apache, nginx, varnish, django middleware, mod_wsgi areall technica...
An example controllerdef new_flight_controller(request):  total_time = request.POST[total_time]  landings = request.POST[l...
An example controllerdef new_flight_controller(request):  total_time = request.POST[total_time]  landings = request.POST[l...
Another example controllerclass NewFlightCommand(BaseCommand):   option_list = BaseCommand.option_list + (        make_opt...
Dont put non-controller code inside acontroller!def to_decimal(input):  """  >>> to_decimal(3:30)  3.5  >>> to_decimal(3.5...
This code is not controller code!def controller(request):  total_time = to_decimal(request.GET[total_time]) # bad!  landin...
The three line MVC application!def mini_controller(request):  return {total_time: request.GET[total_time],         landing...
The MVC color-wheel                   Model  Middleware                                    ModelViews /                   ...
ModelViews1. Projection of a Model (subclass) intended for use in a set ofviews2. Atomic elements that should not hinder t...
ModelViewsclass HTMLFlight(Flight):   def as_tr(self):     """     >>> HTMLFlight.objects.get(pk=234321).as_tr()     <tr i...
ModelViewdef list_flights_controller(request, format):  if format == json:      return JSONFlight, flights.json  elif form...
ModelViewflights.html:    <table class="whatever">        {{ Flight.header }}        {% for flight in flights %}        {{...
Good models are easy to testclass BaseFlightFailedTest(object):   exc = Flight.InvalidFlightData   def test(self):     for...
Tips:1. Dont pass request objects into the model   a. It couples your model to HTTP requests   b. Models should only work ...
Giotto!- New python web development framework!!- Absolutely nothing has been started yet.- Doesnt let you violate MVC.- Th...
Giotto Feature@interfaces(http-get, commandline)class ShowFlightsForUser(Feature):   """   Show flights for a given user  ...
Giotto Interfaces@interfaces(http-put, commandline)class NewFlight(Feature):   """   Create a new flight   """   controlle...
Giotto Modelsclass Manager(models.Manager)   def show_for_user(self, user):     return self.filter(user=user)  def create(...
Accessing featurescommand line:  $ ./giotto.py app feature format [args]http-get   POST app.com/feature.format HTTP/1.1   ...
Controllers handle everything for you@interfaces(http-get, commandline)class ShowRouteForFlight(Feature):   """   Get the ...
Giotto ViewsTake only a single model instance as the only context (obj)Views can return anything, as long as the controlle...
Giotto Viewsclass SingleRouteView(View):   def png(self, route):     "Given a route, return as a png image"     return ima...
Models, controllers and views
Upcoming SlideShare
Loading in...5
×

Models, controllers and views

151

Published on

Published in: Technology, Business
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
151
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
2
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Transcript of "Models, controllers and views"

  1. 1. The Three line MVC application and introducing Giotto
  2. 2. Table on contentsFirst part: Why high level code organization schemes areimportantSecond part: All about MVCThird Part: Giotto!
  3. 3. My experiences1. Started web development in 20072. Wrote code without any kind of architectural pattern at all3. This was very frustrating, but I didnt know any better4. Realized its taking too long to get stuff fixed and its not fun5. Learned first hand that not using MVC is a pain
  4. 4. Non-MVC code
  5. 5. Flightlogg.in Was originally PHP (non-MVC) Now is django (mostly MVC) View: HTML/Javascript Controller: Standard HTTP GET/POST Model: Flight Storage and flight data analysis.
  6. 6. Why?1. Flexibility2. Organization
  7. 7. Imagine...1 app1 django view, 9000 lines of code
  8. 8. Imagine...We want to fix this. Refactor!!step 1: 1000 functions, 9 lines each
  9. 9. Imagine...step 2: 100 classes, 10 functions each
  10. 10. And then...App Models class class Views class class Controllers class class
  11. 11. Overview1. Models - The application2. Controllers - The interface a. ties your application (model) to the outside world3. Views - The presentation of the output to the user
  12. 12. Models1. Usually the biggest part of your application2. Business Logic3. Not just database tables4. Should be completely controller independent
  13. 13. Views1. All about formatting output from model.2. Templates/HTML3. Serializers4. Should be independent of any controllers (templates areportable)
  14. 14. Controllers1. How the data gets to and from the user2. Apache, nginx, varnish, django middleware, mod_wsgi areall technically part of the controller.3. What goes into my controller? a. High level Model code b. High level View code c. final interface level operations
  15. 15. An example controllerdef new_flight_controller(request): total_time = request.POST[total_time] landings = request.POST[landings] user = request.user flight = Flight.new_flight(user, total_time, landings) try: flight.save() except: raise HttpResponseError("invalid flight data") return render_to_response( context={flights: Flight.objects.filter(request.user)} template=flights.html)
  16. 16. An example controllerdef new_flight_controller(request): total_time = request.POST[total_time] landings = request.POST[landings] Interface operations user = request.user flight = Flight.new_flight(user, total_time, landings) try: High level model code flight.save() except: raise HttpResponseError("invalid flight data") return render_to_response( context={flights: Flight.objects.filter(request.user)} template=flights.html) High level view code
  17. 17. Another example controllerclass NewFlightCommand(BaseCommand): option_list = BaseCommand.option_list + ( make_option(--total_time, -t, dest=total_time), make_option(--landings, -l, dest=landings), make_option(--user, -u, dest=user) ) def handle(self, *args, **options): flight = Flight.new_flight(**options) try: flight.save() except: print "Invalid flight data" print "Flight saved!"
  18. 18. Dont put non-controller code inside acontroller!def to_decimal(input): """ >>> to_decimal(3:30) 3.5 >>> to_decimal(3.5) 3.5 >>> to_decimal(3:12) 3.2 """This is not a controller function! Not high level model code, nothigh level view code, and not interface specific!!!
  19. 19. This code is not controller code!def controller(request): total_time = to_decimal(request.GET[total_time]) # bad! landings = request.GET[landings] user = request.user flight = Flight.new_flight(user, total_time, landings) try: flight.save() except: raise HttpResponseError("invalid flight data") return render_to_response( context={flights: Flight.objects.filter(request.user)} template=flights.html)
  20. 20. The three line MVC application!def mini_controller(request): return {total_time: request.GET[total_time], landings: request.GET[landings], user: request.user}def new_flight(request): args = mini_controller(request) flight = Flight.new_flight(*args).save() return render_to_response(view_flight.html, {flight: flight})
  21. 21. The MVC color-wheel Model Middleware ModelViews / Forms Controller View Context processors
  22. 22. ModelViews1. Projection of a Model (subclass) intended for use in a set ofviews2. Atomic elements that should not hinder the real views abilityto do its job.
  23. 23. ModelViewsclass HTMLFlight(Flight): def as_tr(self): """ >>> HTMLFlight.objects.get(pk=234321).as_tr() <tr id="flight_234321"><td class="total_time">3.5</td>... """class JSONFlight(Flight): def as_json(self): """ >>> JSONFlight.objects.get(pk=56216).as_json() {id: 56216, plane: {tailnumber: "N63NE", type: "SA-227"... """
  24. 24. ModelViewdef list_flights_controller(request, format): if format == json: return JSONFlight, flights.json elif format == html: return HTMLFlight, flights.htmldef list_flights(request, format): Flight, view = list_flights_controller(request, format) flights = Flight.objects.filter(user=request.user) return render_to_response({flights: flights}, view)
  25. 25. ModelViewflights.html: <table class="whatever"> {{ Flight.header }} {% for flight in flights %} {{ flight.as_tr }} {% endfor %} </table>flights.json:{user: {{ request.user }}, flights: {% for flight in flights %} {{ flight.as_json }}, {% endfor %}}
  26. 26. Good models are easy to testclass BaseFlightFailedTest(object): exc = Flight.InvalidFlightData def test(self): for kwargs in self.kwarg_set: self.assertRaises(Flight.new_flight(**kwargs), self.exc)class TotalGreatestTest(TestCase, BaseFlightFailedTest): exc = Flight.TotalMustBeGreatest kwarg_set = [{total_time: 3:50, pic: 9.6}, {total_time: 1.0, night: 2.3}]class NoNightTime(TestCase, BaseFlightFailedTest) kwarg_set = [{total_time: 1, night: 0, night_landings: 5}]
  27. 27. Tips:1. Dont pass request objects into the model a. It couples your model to HTTP requests b. Models should only work with raw data2. Try to avoid putting business logic into a controller a. It makes it hard to reuse models3. Pass in only one model object to a view. a. if you have trouble doing this, your models may be wrong b. helps keep the templates reusable.4. Make an attempt to re-write all your controllers to beexactly 3 lines.
  28. 28. Giotto!- New python web development framework!!- Absolutely nothing has been started yet.- Doesnt let you violate MVC.- There should be one-- and preferably only one --obvious wayto do it.- "MV" framework. (micro controllers)- Completely automatic urls- plugins for features- plugins for controller backends. (commandline, http-get, etc)
  29. 29. Giotto Feature@interfaces(http-get, commandline)class ShowFlightsForUser(Feature): """ Show flights for a given user """ controller = {user: Input.data.user} model = Flight.objects.show_for_user view = ShowFlightsurl for feature:{% http-get ShowFlightsForUser.html 59 %} ->Logbook.com/flights/ShowFlightsForUser.html?user=59
  30. 30. Giotto Interfaces@interfaces(http-put, commandline)class NewFlight(Feature): """ Create a new flight """ controller = {user: Input.data.user, total_time: Input.data... model = Logbook.Flight.create view = SingleFlightUsing the feature: $ ./giotto.py logbook NewFlight --user=chris --total_time=3 ...or PUT /new_flight.json HTTP/1.1 user=chris&total_time=3 ...
  31. 31. Giotto Modelsclass Manager(models.Manager) def show_for_user(self, user): return self.filter(user=user) def create(self, *args, **kwargs): # logic goes here return Flight(**kwargs)class Flight(models.Model): attribute = models.Field() objects = Manager()
  32. 32. Accessing featurescommand line: $ ./giotto.py app feature format [args]http-get POST app.com/feature.format HTTP/1.1 [args]sms text "feature format [args]" to 3558526The controller backend handles transporting data to/from theuser
  33. 33. Controllers handle everything for you@interfaces(http-get, commandline)class ShowRouteForFlight(Feature): """ Get the route for a single flight """ controller = Flight.id model = Flight.route view = SingleRouteView
  34. 34. Giotto ViewsTake only a single model instance as the only context (obj)Views can return anything, as long as the controller backendknows how to handle it.templates make links to application features:<a href="{% url_get ShowFlightsForUser obj.user %}"> see {{ obj.user }}s flights!</a>
  35. 35. Giotto Viewsclass SingleRouteView(View): def png(self, route): "Given a route, return as a png image" return image_file def kml(self, route): return kml_string def html(self, route): return jinja2.render({obj: route}, route.html){% http-get RouteForFlight.kml 36426 %}{% http-get RouteForFlight.html 36426 %}giotto logbook RouteForFlight png 36426 | file.png
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

Ă—