• ALL
  • LEETCODE
  • RSS
  • TastyPie Note 1

    2016年5月10日

    Flow Through The Request/Response Cycle

    Tastypie can be thought of as a set of class-based view that provide the API functionality. All routing/middleware/response-handling aspectss are the same as a typical Django app. Where the differs is in the view itself.

    Walking through what a GET request to a list endpoint looks like:

    • The Resource.urls are checked by Django’s url resolvers.

    • On a match for the list view, Resource.wrap_view('dispatch_list') is called. wrap_view provides basic error handling & allows for returning serilized errors.

    • Because dispatch_list was passed to wrap_view, Resource.dispatch_list is called next. This is a thin wrapper around Resource.dispatch.

    • dispatch does a bunch of havy lifting. It ensures:

      • the requested HTTP method is in allowed_methos (method_check).
      • the class has a method that can handle the request(get_list)
      • the user is authenticated(is_authenticated)
      • the user has no exceeded their throttle(throttle_check).

      At this point, dispatch actually calls the requested method (get_list).

    • get_list does the actual work of API. It does:

      • A fetch of the available objects via Resource.obj_get_list. In the case of ModelResource, this builds the ORM filters to apply (ModelResource.build_filters). It then gets the QuerySet via ModelResource.get_object_list (which performs Resource.authorized_read_list to possibly limit the set the user can work with) and applies the built filters to it.
      • It then sorts the objects based on user input (ModelResource.apply_sorting).
      • Then it paginates the results using the supplied Paginator & pulls out the data to be serialized.
      • The objects in the page have full_dehydrate applied to each of them, causing Tastypie to traslate the raw object data into the fields the endpoint supports.
      • Finally, it calls Resource.create_response.
    • create_response is a shortcut method that:

      • Determines the desired response format (Resource.determine_format).
      • Serializes the data given to it in the proper format.
      • Returns a Django HttpResponse (200 OK) with the serialized data.
    • We bubble back up the call stack to dispatch. The last thing dispatch does is potentially store that a request occured for future throttling (Resource.log_throttled_access) then either returns the HttpResponse or wraps whatever data came back in a response (so Django doesn’t freak out).

  • Tastypie

    2016年5月4日

    Resources in Tastypie

    Resources are the heart of Tastypie. By defining a resource we can actually convert a model into an API stream. The data is automatically converted into API response.

    Understanding the process of creating a resource.

    1. Import ModelResource from Tastypie.
    2. Import models from services app
    3. Create custom resource by inheriting ModelResource and link app model in inner Meta class of resource.

    Add API URL in the urls.py of app.

    Dehydrating the JSON data

    flow

    Dehydration in Tastypie means making alterations before sending data to the client. Suppose we need to send capitalized product names instead of small letters. Now we see two kinds of dehydrate methods.

    Dehydrate_field method

    This dehydrate_field is uesd to modify field on the response JSON.

    Dehydrate method

    Dehydrate method is useful for aadding additional fields to bundle (response data).

    Similarly using hydrate method we can alter the bundle data which is generated from request at the time of PUT or POST methods.

  • Django Manager Method

    2016年4月25日

    Django Manager

    Django 里会为每一个 model 生成一个 Manager,默认名字为 objects,一般情况下对 model 进行的处理都是通过 model.objects.XXX( ) 来进行的。其实是调用了 model 的 manager 的方法,而 manager 之中的方法是 QuerySet 方法的代理,QuerySet 方法是对数据库操作的封装。

    eg.

    1
    2
    3
    4
    5
    from django.db import models

    class Person(models.Model):
    ...
    people = models.Manager()

    上面这个 model,Person.objects会产生一个AttributeError,但是Person.people就可以正常操作。因为默认的 manager 已经变成 people,objects 这个 manager 没有重新声明,不起作用。

    自定义 Manager

    通常需要自定义 manager 的情况有两点:

    1. 需要修改/扩展 Django 的 manager 方法
    2. 需要修改返回的 QuerySet

    默认 Manager

    如果使用自定义的 manager 需要注意的是,Django 将 model 中定义的第一个 manager 认为是默认 manager,而且 Django 框架中会用到默认 manager。

    笨方法是使用自定义 manager 的时候,对于 model 依然提供 objects 这个默认 manager,并放在第一个。

    eg.

    1
    2
    3
    4
    5
    6
    class Book(models.Model):
    title = models.CharField(max_length=100)
    author = models.CharField(max_length=50)

    objects = models.Manager() # default manager
    custom_objects = CustomBOokManager() # custom manager

    source

  • Flask Day 2

    2016年2月16日

    To handle web forms we use Flask-WTF . So we need to write a config file (file config.py):

    1
    2
    WTF_CSRF_ENABLED = True
    SECRET_KEY = 'you-will-never-guess'

    And then you need to use this config (file app/__init__.py):

    1
    2
    3
    4
    5
    6
    from flask import Flask

    app = Flask(__name__)
    app.config.from_object('config')

    from app import views

    Let’s build a simple form (file app/forms.app):

    1
    2
    3
    4
    5
    6
    7
    from flask.ext.wtf import Form
    from wtforms import StringField, BooleanField
    from wtforms.validators import DataRequired

    class LoginForm(Form):
    openid = StringField('openid', validators=[DataRequired()])
    remember_me = BooleanField('remember_me', default=False)

    The DataRequired() is a validator that checks the field is empty or not.

    After that, we need a HTML page to show the form (file app/templates/login.html):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    <!-- extend from base layout -->
    {% extends "base.html" %}

    {% block content %}
    <h1>Sign In</h1>
    <form action="" method="post" name="login">
    {{ form.hidden_tag() }}
    <p>
    Please enter your OpenID:<br>
    {{ form.openid(size=80) }}<br>
    </p>
    <p>{{ form.remember_me }} Remember Me</p>
    <p><input type="submit" value="Sign In"></p>
    </form>
    {% endblock %}

    The final step is to code a view function that renders the template and receiving data from form (file app/views.py):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    from flask import render_template, flash, redirect
    from app import app
    from .forms import LoginForm

    # index view function suppressed for brevity

    app.route('/login', methods=['GET', 'POST'])
    def login():
    form = LoginForm()
    if form.validate_on_submit():
    flash('Login requested for OpenID="%s", remember_me=%s' %
    (form.openid.data, str(form.remember_me.data)))
    return redirect('/index')
    return render_template('login.html',
    title='Sign In',
    form=form)
  • Flask Day 1

    2016年2月15日

    “Hello World” in Flask

    Create a folder named microblog (or whatever you want). Then cd into that folder and run following prompt in terminal:

    1
    $ python3 -m venv flask

    Now you’ll have a folder named flask inside microblog, containing a private version of Python interpreter.

    And you should install flask and extensions by the commands below:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    $ flask/bin/pip install flask
    $ flask/bin/pip install flask-login
    $ flask/bin/pip install flask-openid
    $ flask/bin/pip install flask-mail
    $ flask/bin/pip install flask-sqlalchemy
    $ flask/bin/pip install sqlalchemy-migrate
    $ flask/bin/pip install flask-whooshalchemy
    $ flask/bin/pip install flask-wtf
    $ flask/bin/pip install flask-babel
    $ flask/bin/pip install guess_language
    $ flask/bin/pip install flipflop
    $ flask/bin/pip install coverage

    After that, let’s create the basic structure for our application: app app/static app/templates tmp.

    1. app — where the application package is
    2. static — stores static files like images, javascripts, and css.
    3. templates — where templates will go.

    Then you can start with __init__.py which should put into app folder (file app/__init__.py):

    1
    2
    3
    4
    from flask import Flask

    app = Flask(__name__)
    from app import views

    The views are the handlers that response to requests from web browsers or other clients. Each view function is mapped to one or more request URLs.

    Let’s see what a views function looks like (file app/views.py):

    1
    2
    3
    4
    from flask import Flask

    app = Flask(__name__)
    from app import views

    Finally we should create a script to starts up the web server with our application(file run.py):

    1
    2
    3
    #!flask/bin/python
    from app import app
    app.run(debug=True)

    To indicating that is an executable file you need to run this in terminal:

    1
    $ chmod a+x run.py

    Now the file structure should look like:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    microblog\
    flask\
    <virtual environment files>
    app\
    static\
    templates\
    __init__.py
    views.py
    tmp\
    run.py

    Then start to write the template (file app/templates/index.html):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <html>

    <head>
    <title>{{ title }} - microblog</title>
    </head>

    <body>
    <h1>Hello, {{ user.nickname }}!</h1>
    </body>

    </html>

    Now let’s write the view function that uses this template (file app/views.py):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    from flask import render_template
    from app import app

    @app.route('/')
    @app.route('/index')
    def index():
    user = {'nickname': 'ching'} # fake user
    return render_template('index.html',
    title='Home',
    user=user)

    render_template function is what we import from Flask framework to render the template. It uses Jinja2 templating engine.

  • First Post

    2016年2月12日

    This is the very first post I wrote,

    with Typora & Hexo.