LEARN THE REALLY HARD WAY Anthony Bastardi

ADVICE FROM AN OLD PROGRAMMER [Use] code as your secret weapon...People who can code in biology, medicine, government, sociology, physics, history, and mathematics are respected and can do amazing things to advance those disciplines. Learn Python the Hard Way, Zed Shaw

I believe that the ability to easily build high quality web applications is of critical importance for the growth of a free and open society...As you will learn in the following pages, web2py tries to lower the barrier of entry to web development... web2py: Complete Reference Manual, 6th Edition, Massimo Di Pierro

ANSWERING QUESTIONS

SOME BENEFITS OF ANSWERING QUESTIONS Get exposure to real-world problems. Get exposure to all aspects of web development. Discover common pitfalls. Explaining/teaching leads to deeper understanding. Make serendipitous discoveries. Develop debugging and code review skills. Collect usable code. Help other people.

HOW?

READ THE SOURCE The ultimate API documentation. Pick up Python idioms and patterns. On-ramp to making contributions.

USE THE WEB2PY SHELL Experiment safely. Inspect/explore objects. Quickly iterate to build code.

WEB2PY WSGI APPLICATION

WSGIBASE OVERVIEW globals– Request, Response, Session rewrite.url_in– Routing Handle static files Additional set-up (cookies, session, update Request) main.serve_controller– Execute app code compileapp build_environment run_models_in> restricted.restricted run_controller_in> restricted.restricted run_view_in> restricted.restricted Wrap up (commit/rollback, close session, handle errors, etc.) http.HTTP– Return response * Note, all modules above are in the gluon namespace.

main.wsgibase def wsgibase(environ, responder): eget = environ.get current.__dict__.clear() request = Request(environ) response = Response() session = Session()

globals.Request class Request(Storage): def __init__(self, env): Storage.__init__(self) self.env = Storage(env) self.env.web2py_path = global_settings.applications_parent self.env.update(global_settings) self.cookies = Cookie.SimpleCookie() self._get_vars = None self._post_vars = None self._vars = None self._body = None self.folder = None self.application = None self.function = None self.args = List() self.extension = 'html' self.now = datetime.datetime.now() self.utcnow = datetime.datetime.utcnow() self.is_restful = False self.is_https = False self.is_local = False self.global_settings = settings.global_settings

main.wsgibase try: try: try: fixup_missing_path_info(environ) (static_file, version, environ) = url_in(request, environ) response.status = env.web2py_status_code or response.status if static_file: if eget('QUERY_STRING', '').startswith('attachment'): response.headers['Content-Disposition'] \ = 'attachment' if version: response.headers['Cache-Control'] = 'max-age=315360000' response.headers[ 'Expires'] = 'Thu, 31 Dec 2037 23:59:59 GMT' response.stream(static_file, request=request)

main.wsgibase # ################################################## # run controller # ################################################## if global_settings.debugging and app != "admin": import gluon.debug # activate the debugger gluon.debug.dbg.do_debug(mainpyfile=request.folder) serve_controller(request, response, session)

main.serve_controller def serve_controller(request, response, session): # ################################################## # build environment for controller and view # ################################################## environment = build_environment(request, response, session) response.view = '%s/%s.%s' % (request.controller, request.function, request.extension) # ################################################## # process models, controller and view (if required) # ################################################## run_models_in(environment) response._view_environment = copy.copy(environment) page = run_controller_in(request.controller, request.function, environment) if isinstance(page, dict): response._vars = page response._view_environment.update(page) run_view_in(response._view_environment) page = response.body.getvalue()

compileapp _base_environment_ = dict((k, getattr(html, k)) for k in html.__all__) _base_environment_.update( (k, getattr(validators, k)) for k in validators.__all__) _base_environment_['__builtins__'] = __builtins__ _base_environment_['HTTP'] = HTTP _base_environment_['redirect'] = redirect _base_environment_['DAL'] = DAL _base_environment_['Field'] = Field _base_environment_['SQLDB'] = SQLDB # for backward compatibility _base_environment_['SQLField'] = SQLField # for backward compatibility _base_environment_['SQLFORM'] = SQLFORM _base_environment_['SQLTABLE'] = SQLTABLE _base_environment_['LOAD'] = LOAD

compileapp.build_environmen t def build_environment(request, response, session, store_current=True): environment = dict(_base_environment_) if not request.env: request.env = Storage() response.models_to_run = [ r'^\w+\.py$', r'^%s/\w+\.py$' % request.controller, r'^%s/%s/\w+\.py$' % (request.controller, request.function) ] t = environment['T'] = translator(os.path.join(request.folder,'languages'), request.env.http_accept_language) c = environment['cache'] = Cache(request)

compileapp.build_environmen t environment['request'] = request environment['response'] = response environment['session'] = session environment['local_import'] = \ lambda name, reload=False, app=request.application:\ local_import_aux(name, reload, app) BaseAdapter.set_folder(pjoin(request.folder, 'databases')) response._view_environment = copy.copy(environment) custom_import_install() return environment

compileapp.models_to_run def run_models_in(environment): """ Runs all models (in the app specified by the current folder) It tries pre-compiled models first before compiling them. """ folder = environment['request'].folder c = environment['request'].controller f = environment['request'].function response = environment['response'] path = pjoin(folder, 'models') cpath = pjoin(folder, 'compiled') compiled = os.path.exists(cpath) if compiled: models = sorted(listdir(cpath, '^models[_.][\w.]+\.pyc$', 0), model_cmp) else: models = sorted(listdir(path, '^\w+\.py$', 0, sort=False), model_cmp_sep) models_to_run = None

compileapp.models_to_run for model in models: if response.models_to_run != models_to_run: regex = models_to_run = response.models_to_run[:] if isinstance(regex, list): regex = re_compile('|'.join(regex)) if models_to_run: if compiled: n = len(cpath)+8 fname = model[n:-4].replace('.','/')+'.py' else: n = len(path)+1 fname = model[n:].replace(os.path.sep,'/') if not regex.search(fname) and c != 'appadmin': continue elif compiled: code = read_pyc(model) elif is_gae: code = getcfs(model, model, lambda: compile2(read_file(model), model)) else: code = getcfs(model, model, None) restricted(code, environment, layer=model)

restricted.restricted def restricted(code, environment=None, layer='Unknown'): """ Runs code in environment and returns the output. If an exception occurs in code it raises a RestrictedError containing the traceback. """ if environment is None: environment = {} environment['__file__'] = layer environment['__name__'] = '__restricted__' try: if isinstance(code, types.CodeType): ccode = code else: ccode = compile2(code, layer) exec ccode in environment except HTTP: raise except RestrictedError: raise except Exception, error: etype, evalue, tb = sys.exc_info() if __debug__ and 'WINGDB_ACTIVE' in os.environ: sys.excepthook(etype, evalue, tb) output = "%s %s" % (etype, evalue) raise RestrictedError(layer, code, output, environment)

main.serve_controller # ################################################## # set default headers it not set # ################################################## default_headers = [ ('Content-Type', contenttype('.' + request.extension)), ('Cache-Control', 'no-store, no-cache, must-revalidate, post-check=0, pre-check=0'), ('Expires', time.strftime('%a, %d %b %Y %H:%M:%S GMT', time.gmtime())), ('Pragma', 'no-cache')] for key, value in default_headers: response.headers.setdefault(key, value) raise HTTP(response.status, page, **response.headers)

main.wsgibase serve_controller(request, response, session) except HTTP, http_response: if static_file: return http_response.to(responder, env=env) if request.body: request.body.close() if hasattr(current,'request'): session._try_store_in_db(request, response) if response.do_not_commit is True: BaseAdapter.close_all_instances(None) elif response.custom_commit: BaseAdapter.close_all_instances(response.custom_commit) else: BaseAdapter.close_all_instances('commit')

main.wsgibase except RestrictedError, e: if request.body: request.body.close() # ################################################## # on application error, rollback database # ################################################## # log tickets before rollback if not in DB if not request.tickets_db: ticket = e.log(request) or 'unknown' if response._custom_rollback: response._custom_rollback() else: BaseAdapter.close_all_instances('rollback') if request.tickets_db: ticket = e.log(request) or 'unknown' http_response = \ HTTP(500, rwthread.routes.error_message_ticket % dict(ticket=ticket), web2py_error='ticket %s' % ticket)

main.wsgibase finally: if response and hasattr(response, 'session_file') \ and response.session_file: response.session_file.close() session._unlock(response) http_response, new_environ = try_rewrite_on_error( http_response, request, environ, ticket) if not http_response: return wsgibase(new_environ, responder) if global_settings.web2py_crontype == 'soft': newcron.softcron(global_settings.applications_parent).start() return http_response.to(responder, env=env)

http.HTTP def to(self, responder, env=None): env = env or {} status = self.status headers = self.headers if status in defined_status: status = '%d %s' % (status, defined_status[status]) elif isinstance(status, int): status = '%d UNKNOWN ERROR' % status else: status = str(status) if not regex_status.match(status): status = '500 %s' % (defined_status[500])

http.HTTP rheaders = [] for k, v in headers.iteritems(): if isinstance(v, list): rheaders += [(k, str(item)) for item in v] elif not v is None: rheaders.append((k, str(v))) responder(status, rheaders) if env.get('request_method', '') == 'HEAD': return [''] elif isinstance(body, str): return [body] elif hasattr(body, '__iter__'): return body else: return [str(body)]

LOCATIONS OF GLOBAL API OBJECTS cache: cache compileapp: LOAD dal: DAL, Field globals: request, response, session http: HTTP, redirect html: HTML helpers, URL languages: T sqlhtml: SQLFORM, SQLFORM.grid, SQLTABLE validators: All validators

http://web2py.readthedocs.com Docs » Welcome to web2py’s API documentation!

Welcome to web2py’s API documentation! Contents: admin

Module

Utility functions for the Admin application cache Module Basic caching classes and methods cfs Module Functions required to execute app components compileapp Module Functions required to execute app components contenttype Module custom_import

Module

Support for smart import syntax for web2py applications dal Module debug

 Read the Docs

Module

Debugger support classes decoder Module v: latest 

fileutils

Module

And now, the web2py shell...

BONUS ROUND SECRET FEATURES

ADD AND REMOVE CLASSES FROM HTML HELPERS mydiv.add_class('new_class') mydiv.remove_class('old_class')

CONDITIONAL EXTEND AND INCLUDE IN TEMPLATES {{extend 'mylayout.html' if some_condition else None}} {{include 'myview.html' if some_condition else None}}

Warning: Views with a conditional extend/include cannot be compiled.

CLONE A FIELD db.define_table('table2', db.table1.field1.clone(...))

SQL STRING AS QUERY db("mytable.start_date < NOW()").select(db.mytable.ALL)

ADD METHODS TO DAL TABLES @db.person.add_method.just_men @db.animal.add_method.just_males def get_just_gender_equals_m(self): return self._db(self.gender == 'm').select() db.person.just_men() db.animal.just_males()

SELECT FOR UPDATE db(query).select(..., for_update=True)

CUSTOM PROCESSOR FOR QUERY RESULTS db(query).select(..., processor=lambda rows, fields, colnames: ...)

CATCH DATABASE ERRORS

try: db.mytable.insert(**fields) except (db._adapter.driver.IntegrityError, db._adapter.driver.OperationalError) as e: pass

or db.mytable._on_insert_error = my_insert_error_handler db.mytable._on_update_error = my_update_error_handler

CONVERT FORMS form.as_dict() form.as_json() form.as_xml() form.as_yaml()

ADDITIONAL IS_IN_DBARGUMENTS IS_IN_DB(..., groupby=..., orderby=..., sort=...)

ajaxFUNCTION ARGUMENTS // Second argument can be a jQuery selector instead of a list of names. ajax('/myapp/default/myaction', '.some_selector', 'target'); // Third argument can be a function instead of an ID or ':eval'. ajax('/myapp/default/myaction', [], function(server_response) {...});

THE END

the really hard way -

LEARN. THE REALLY HARD WAY. Anthony Bastardi ... those disciplines. Learn Python the Hard Way, Zed Shaw .... local_import_aux(name,reload,app).

410KB Sizes 0 Downloads 103 Views

Recommend Documents

Learn Python the Hard Way - Meetup
By going through this book and copying each example exactly, you will be training your brain to ... music theory, ear training, songs, and anything else I can. ...... give to a human. You print them, save them to files, send them to web servers, all

Download Learn More Python 3 the Hard Way
Sep 23, 2017 - ... Step for New. Python Programmers (Zed Shaw s Hard Way Series) Full eBook ... hours of online videos, where ... programmer's text editor.

Watch The Hard Way (1991) Full Movie Online.pdf
Watch The Hard Way (1991) Full Movie Online.pdf. Watch The Hard Way (1991) Full Movie Online.pdf. Open. Extract. Open with. Sign In. Main menu.

Doing It The Hard Way Tory Lane
pdf.Elmentalista 7x06.Cartoon network game pc.Her familywe'reafforded the pleasure ofalarge home ... Psd poster templates. ... The bridge us s02e04 web-dl.