TublogDev
Last edited June 23, 2009
More by E.T »
全局计数器用来作 Paging...
重构要做的事情
用 djangoform 代替原有的 form
将数据的读写从 view 函数中分离出来
改善 API 代码的用户认证、数据读写
pager 增加 query 参数
重新设计 model,将 post 和 page 合并为 Entry,用 type = 'post' 或 type = 'page' 区别
用 tag 代替 分类,清理 view.py 中的代码
去掉原先的sidebar
换掉现有的RTE
用 app.yaml 简化用户认证和静态文件处理
优化 url
MetaWeblog API: MetaWeblog API Specification
www.metaweblogapi.com/metaweblog-api-specification...

MetaWeblog API Specification

Introduction

The MetaWeblog API is an application programming interface that enables software to read and write weblog posts stored on a web server. The API has been implemented as an XML-RPC web service, so there are implementations supporting the API available in many popular programming languages.

The MetaWeblog API is designed to extend the Blogger API, a blogging API that only can read and write the text of weblog posts. An additional API was needed to read and write elements such as a blog post's title, file enclosures, and categories.

Most software that supports the Blogger API also supports the MetaWeblog API, and vice versa.

Data Types

The API employs the data types defined in XML-RPC, including the scalar types base64, boolean, int and string and the composite types array and struct.

Error Handling

Applications that implement the API should use the fault-response scheme defined by XML-RPC. For example, trying to read, write, or edit a post without providing a valid username and password should generate a fault. Applications should display the error string to the user in a dialog box or server log, as appropriate.

Use of RSS 2.0

The API uses a struct to represent a blog post. Within the struct, the components of the post are represented by the elements of an item in the RSS syndication format, adopting the same name and usage as their RSS counterparts. Items in RSS can be extended by elements from namespaces, so the same is permitted in the MetaWeblog API.

There's one exception: Categories are represented by a member named categories in the MetaWeblog API, unlike the RSS element which is named category.

Common Parameters

Several of the API's methods employ the same parameters: blogId, password, postId, publish, and username.

The blogId, password, publish and username parameters are the same as the ones in the Blogger API. The blogId parameter is a string that contains a unique identifier for a blog. The username and password parameters are strings that contain authentication credentials to access that particular blog. The publish parameter is a boolean that's "true" if the blog update should be published immediately and "false" if it should be stored as a draft and not published.

The postId parameter also follows the Blogger API. It is a string that contains an ID for the post, which is returned by the MetaWeblog API's newPost method and can be used as a parameter in the editPost and getPost methods.

Reading and Writing Blog Posts

There are three methods that can be called in the API to read and write blog posts:

  • metaWeblog.newPost(string blogId, string username, string password, struct content, boolean publish), which returns a string
  • metaWeblog.editPost(string postId, string username, string password, struct content, boolean publish), which returns the boolean true
  • metaWeblog.getPost(string postId, string username, string password), which returns a struct

The content parameter of the newPost and editPost methods represents the content of a blog post and is a struct, not a string as it is in the corresponding methods of the Blogger API. The defined members of the struct are the elements of an item in RSS.

The three basic members of the struct are the post's title, link and description. For blogging tools that don't support titles and links, the description member holds all of the post's content.

Some elements of an RSS item have attributes such as the enclosure element, which has length, type and url attributes that describe a media file. To represent this in the MetaWeblog API, the value of the member should be a struct with names matching the attribute names.

<member>
  <name>enclosure</name>
  <value>
    <struct>
      <member>
        <name>length</name>
        <value>
          <i4>2597380</i4>
        </value>
      </member>
      <member>
        <name>type</name>
        <value>audio/mpeg</value>
      </member>
      <member>
        <name>url</name>
        <value>http://example.com/audio/pollen.mp3</value>
      </member>
    </struct>
  </value>
</member>

The categories member holds a blog post's categories as an array of strings, with each string representing the name of a category. If a category is not defined on the blog, the category should be ignored rather than triggering an error.

In calls to newPost or editPost, the struct may contain a member named flNotOnHomePage that contains the boolean "true" if the blog post must be excluded from the blog's home page and only appears on category pages. If this member is equal to "false" or not present, the post must be included on the home page. Some blogging tools may not support this functionality.

The getPost method returns a struct that functions identically to the struct sent as a parameter to the newPost and editPost methods.

A server implementing this API must ignore all elements that it doesn't support.

Reading Multiple Blog Posts

The following method retrieves recent posts from a blog:

  • metaWeblog.getRecentPosts(string blogId, string username, string password, integer numberOfPosts), which returns an array of structs

Each struct in the array returned by the method represents a recent blog post and holds the same members as a call to metaWeblog.getPost.

The numberOfPosts parameter retrieves blog posts in reverse chronological order, so if numberOfPosts equals 1, the most recent post is retrieved; if it equals 2, the two most-recent posts are retrieved, and so on. If the numberOfPosts parameter is larger than the number of posts in the blog, all of the posts are retrieved.

Reading Categories

The following method retrieves a list of categories defined by a blog:

  • metaWeblog.getCategories(string blogId, string username, string password), which returns a struct

The struct returned by the method contains one struct describing each category with three strings as members: description, htmlUrl and rssUrl.

Uploading Files

The following method transfers a file such as an image, audio or video to a blog:

  • metaWeblog.newMediaObject(string blogId, string username, string password, struct content), which returns a struct

The blogId, password and username parameters are the same ones employed in other methods of this API.

The content struct must contain at least three members: bits, name and type.

The name member is a string that holds the filename to assign the object on the blog server. If the name is the same as an existing file, implementers may replace the file.

The type member is a string that identifies the MIME media type of the file, such as "audio/mpeg" for an MPEG audio file, "image/jpeg" for a JPEG graphic or "video/quicktime" for an Apple QuickTime video.

The bits member is a base64-encoded binary value containing the content of the object.

The struct may contain other elements, which should be ignored by blogging tools that do not support them.

If the file transfer is successful, the newMediaObject method returns a struct that contains a member called url that represents the URL of the file. This URL must employ either the HTTP or FTP protocol.

This method fails with an error if the file could not be transferred successfully.

Examples

Here's an example request using the API:

<methodCall>
  <methodName>metaWeblog.getPost</methodName>
  <params>
    <param>
      <value><i4>1320</i4></value>
    </param>
    <param>
      <value>John Q. Public</value>
    </param>
    <param>
      <value><base64>cGFzc3dvcmQ=</base64></value>
    </param>
  </params>
</methodCall>

Here's an example response.

<?xml version="1.0"?>
<methodResponse>
  <params>
    <param>
      <value>
        <struct>
          <member>
            <name>categories</name>
            <value>
              <array>
                <data>
                  <value>Television</value>
                  <value>Politics</value>
                </data>
              </array>
            </value>
          </member>
          <member>
            <name>dateCreated</name>
            <value><dateTime.iso8601>20080919T11:52:41</dateTime.iso8601></value>
          </member>
          <member>
            <name>description</name>
            <value>I'm still not over the death of All My Children's Dixie Cooney Chandler Martin Bodine Martin, who
              died in 2007 after eating poisoned peanut butter pancakes meant for her daughter-in-law.</value>
          </member>
          <member>
            <name>enclosure</name>
            <value>
              <struct>
                <member>
                  <name>length</name>
                  <value><i4>2597380</i4></value>
                </member>
                <member>
                  <name>type</name>
                  <value>audio/mpeg</value>
                </member>
                <member>
                  <name>url</name>
                  <value>http://www.example.com/audio/pollen_story.mp3</value>
                </member>
              </struct>
            </value>
          </member>
          <member>
            <name>link</name>
            <value>http://www.example.com/2108/cady-mcclain</value>
          </member>
          <member>
            <name>permaLink</name>
            <value>http://www.example.com/2108/cady-mcclain</value>
          </member>
          <member>
            <name>postid</name>
            <value><i4>2108</i4></value>
          </member>
          <member>
            <name>title</name>
            <value>Cady McClain</value>
          </member>
          <member>
            <name>userid</name>
            <value><i4>1320</i4></value>
          </member>
        </struct>
      </value>
    </param>
  </params>
</methodResponse>

Transmitting Elements with Attributes

The members of the struct used as a parameter to the editPost and newPost methods are borrowed from item elements in RSS. Most of the core elements of RSS lack attributes, so they can be represented simply in a struct. The enclosure and source elements have attributes and are structured as defined previously in this document.

For other elements that have attributes, the following rules apply:

  1. If an element has attributes, represent the element as a struct and include the attributes as child elements of the struct.
  2. If an element has both attributes and a value, make the element a struct, include the attributes as child elements, and create a child element for the value with the name _value (note the underscore).
  3. If an element comes from a namespace, include a struct as a child element whose name is the namespace URI and put the namespace elements inside that struct.

Because of these rules, no element can be passed through the MetaWeblog API that has an attribute named _value.

Comments

The Blogger API provides an appkey parameter that enables vendors to assign a developers key that can be used to track and potentially limit usage of the API. Though the MetaWeblog API doesn't employ this parameter in any of its methods, an appkey element can be added to the content struct parameter in the editPost, newPost and newMediaObject methods.

Copyright

This document is available under the terms of the Creative Commons Attribution/Share Alike license and has been authored by MetaWeblog API.

RFC: MetaWeblog API
www.xmlrpc.com/metaWeblogApi

RFC: MetaWeblog API

Thu, Mar 14, 2002; by Dave Winer.

Document status 

This document was updated on 8/8/03, to incorporate all the RFCs related to the MetaWeblog API. The earlier version of the document is archived here. It has been reviewed by members of the MetaWeblog API mail list, and feedback has been incorporated.

On 8/24/03, I posted a last call for comments, and received several and incorporated some.

As of 8/26/03, this document is deployable. There may be changes, but they will be clearly documented, and will only clarify the spec, in no way will they change the format or protocol. It is now safe to deploy applications based on this spec.

What is the MetaWeblog API? 

The MetaWeblog API (MWA) is a programming interface that allows external programs to get and set the text and attributes of weblog posts. It builds on the popular XML-RPC communication protocol, with implementations available in many popular programming environments.

Relationship between MetaWeblog API and the Blogger API 

The MetaWeblog API is designed to enhance the Blogger API, which was limited in that it could only get and set the text of weblog posts. By the time MWA was introduced, in spring 2002, many weblog tools had more data stored with each post, and without an API that understood the extra data, content creation and editing tools could not access the data.

At the time of this writing, summer 2003, most popular weblog tools and editors support both the Blogger API and the MetaWeblog API.

Relationship between MetaWeblog API and RSS 2.0 

The MetaWeblog API uses an XML-RPC struct to represent a weblog post. Rather than invent a new vocabulary for the metadata of a weblog post, we use the vocabulary for an item in RSS 2.0. So you can refer to a post's title, link and description; or its author, comments, enclosure, guid, etc using the already-familiar names given to those elements in RSS 2.0. Further since RSS 2.0 is extensible, so is the MetaWeblog API. We have designed conventions for representing attributes and namespaces in MWA.

Basic entry-points 

There are three basic entry-points in the API:

metaWeblog.newPost (blogid, username, password, struct, publish) returns string

metaWeblog.editPost (postid, username, password, struct, publish) returns true

metaWeblog.getPost (postid, username, password) returns struct

The blogid, username, password and publish params are as in the Blogger API. newPost returns a string representation of the post id, again as defined by the Blogger API. The struct is where the juice is.

The struct 

In newPost and editPost, content is not a string, as it is in the Blogger API, it's a struct. The defined members of struct are the elements of <item> in RSS 2.0, providing a rich variety of item-level metadata, with well-understood applications.

The three basic elements are title, link and description. For blogging tools that don't support titles and links, the description element holds what the Blogger API refers to as "content."

Where an element has attributes, for example, enclosure, pass a struct with sub-elements whose names match the names of the attributes according to the RSS 2.0 spec, url, length and type.

For the source element, pass a struct with sub-elements, url and name.

For categories, pass an array of strings of names of categories that the post belongs to, named categories. On the server side, it's not an error if the category doesn't exist, only record categories for ones that do exist.

In getPost, the returned value is a struct, as with the Blogger API, but it contains extra elements corresponding to the struct passed to newPost and editPost.

The server must ignore all elements that it doesn't understand.

In a call to metaWeblog.newPost or metaWeblog.editPost, if the struct contains a boolean named flNotOnHomePage, then the post does not appear on the home page, and only appears on the specified category pages.

Request and response 

Here's an example of a request and a response.

Here's the post that this request is getting info about.

metaWeblog.newMediaObject 

metaWeblog.newMediaObject (blogid, username, password, struct) returns struct

The blogid, username and password params are as in the Blogger API.

The struct must contain at least three elements, name, type and bits.

name is a string, it may be used to determine the name of the file that stores the object, or to display it in a list of objects. It determines how the weblog refers to the object. If the name is the same as an existing object stored in the weblog, it may replace the existing object.

type is a string, it indicates the type of the object, it's a standard MIME type, like audio/mpeg or image/jpeg or video/quicktime.

bits is a base64-encoded binary value containing the content of the object.

The struct may contain other elements, which may or may not be stored by the content management system.

If newMediaObject fails, it throws an error. If it succeeds, it returns a struct, which must contain at least one element, url, which is the url through which the object can be accessed. It must be either an FTP or HTTP url.

metaWeblog.getCategories 

metaWeblog.getCategories (blogid, username, password) returns struct

The struct returned contains one struct for each category, containing the following elements: description, htmlUrl and rssUrl.

This entry-point allows editing tools to offer category-routing as a feature.

metaWeblog.getRecentPosts 

metaWeblog.getRecentPosts (blogid, username, password, numberOfPosts) returns array of structs

Each struct represents a recent weblog post, containing the same information that a call to metaWeblog.getPost would return.

If numberOfPosts is 1, you get the most recent post. If it's 2 you also get the second most recent post, as the second array element. If numberOfPosts is greater than the number of posts in the weblog you get all the posts in the weblog.

Transmitting elements with attributes 

The members of the struct passed in newPost and editPost come from the elements of items in RSS 2.0. The most commonly used core elements have no attributes, so it's clear how to include them in the struct. However, some elements, such as source, enclosure and category, may have attributes and a value. Here are a simple set of rules for elements that have attributes and a value. Note that these rules do not apply to enclosure and source, which are provided for specifically above.

1. If an element has attributes, then represent the element with a struct, and include the attributes as sub-elements of the struct.

2. If an element has both attributes and a value, make the element a struct, include the attributes as sub-elements, and create a sub-element for the value with the name _value. Note that this means that no element can be passed through the API that has an attribute whose name is _value.

Transmitting elements from namespaces 

RSS 2.0 allows for the use of namespaces. If you wish to transmit an element that is part of a namespace include a sub-struct in the struct passed to newPost and editPost whose name is the URL that specifies the namespace. The sub-element(s) of the struct are the value(s) from the namespace that you wish to transmit.

Comments 

The Blogger API provides a parameter called appkey that allows vendors to assign a key to developers so they can track and possibly limit usage of the API for certain tools. The MetaWeblog API doesn't specifically provide a parameter for an appkey. Applications that wish to transmit an appkey should add an element to the struct called appkey and set its value to the appkey that should be associated with the call.

Applications should use the fault-response scheme defined by XML-RPC. For example, trying to create, get, or edit a post without a valid username-password should generate a fault. Client applications should display the error string, as appropriate, to the user, for example, in a dialog, or in a server log.

Thanks 

Thanks to Michael Bernstein for help editing this spec in summer 2003.

References 

RSS 2.0; Dave Winer; 9/02.

RFC: MetaWeblog API; Dave Winer; 3/02.

Blogger API; Evan Williams; 8/01.

ManilaRPC; Andre Radke, Brent Simmons, Dave Winer; 1999.

XML-RPC; Dave Winer; 1998

future development
    管理界面
    页面评论
    评论回复
    存档
    分类 / tag
    API
    Theme support
   
1.0:
api auth
potential bugs
full link support
category support
simplify templates
refactor sidebar code
make stable designs of models

1.1:
theme support
fit for extension

1.2:
optimization
support uploading imgs to picasa

1.3:
more integration with google services
support importing from other blogs / blog engines
favicon
zipserve
/google/appengine/ext/admin (下水道)
login: admin
slug 简化url
memcache

property 等修饰符的使用可简化编码

URL and file path patterns use POSIX extended regular expression syntax, excluding collating elements and collation classes. Back-references to grouped matches (e.g. \1) are supported, as are these Perl extensions: \w \W \s \S \d \D (This is similar to Codesite search, plus back-reference support.)

__getattr__ 与 __getattribute__的区别
http://docs.python.org/reference/datamodel.html#object.__getattribute__

Iterator objects also need to implement this method; they are required to return themselves. For more information on iterator objects, see Iterator Types.
http://docs.python.org/reference/datamodel.html#object.__iter__

活用 getattr 等内置函数

Property 的 multiline default choices参数
db.StringProperty(multiline=False,default='Micolog')

dict 式的格式化字符串
'%(year)s/%(month)s/%(day)s/%(postname)s.html'

Model.get_by_key_name

categorie_keys=db.ListProperty(db.Key)

auto_now: 最后修改时间
auto_now_add: 创建时间

entry_parent=db.IntegerProperty(default=0)#When level=0 show on main menu.
menu_order=db.IntegerProperty(default=0)
entrytype = ‘post' | 'page'

EmailProperty

@property
def shortcontent(self,len=20):
        return self.content[:len]


待查:Sitemap_NotifySearch

logging 模块

__metaclass__
http://docs.python.org/reference/datamodel.html#customizing-class-creation

urllib.unquote(urllib.unquote(value)).decode('utf8') 很诡异

其实我的 Pager 写得蛮好的嘛 (不考虑效率的话)
改成这样好一点 def __init__(self, model=None,query=None, items_per_page=10):

基于类的dispatcher可能还是方便一点

username = args[pos+0]
password = args[pos+1]
args = args[0:pos]+args[pos+2:]
@checkauth(pos=2)  (in api_rpc.py) 这种写法未免太……






Uliweb提供了多种扩展的能力:

  • plugin扩展。这是一种插件处理机制。Uliweb已经预设了一些调用点,这些调用点会在特殊的地方 被执行。你可以针对这些调用点编写相应的处理,并且将其放在settings.py中,当Uliweb在启动 时会自动对其进行采集,当程序运行到调用点位置时,自动调用对应的插件函数。
  • middleware扩展。它与Django的机制完全类似。你可以在配置文件中配置middleware类。每个 middleware可以处理请求和响应对象。
  • views模块的初始化处理。在views模块中,如果你写了一个名为__begin__的函数,它将在执行 要处理的view函数之前被处理,它相当于一个入口。因此你可以在这里面做一些模块级别的处理, 比如检查用户的权限。因此建议你根据功能将view函数分到不同的模块中。
在Uliweb中,一个view函数是运行在某种环境中的,当需要调用view函数时,在调用前,我会向 函数的func_globals属性中注入一些对象,这些对象就可以直接在函数中使用了,你不再需要导入。
settings 是定义在所有有效的app settings.py文件中的配置项。注意,一个配置项的名称必须是 大写的。


views模块的初始化处理。在views模块中,如果你写了一个名为__begin__的函数,它将在执行 要处理的view函数之前被处理,它相当于一个入口。因此你可以在这里面做一些模块级别的处理, 比如检查用户的权限。因此建议你根据功能将view函数分到不同的模块中。
Key.from_path ?
google sitemap meta tag support
def post_struct(post):
    link = full_url(post.get_absolute_url())
    categories = post.tags.all()
    struct = {
        'postid': post.id,
        'title': post.title,
        'link': link,
        'permaLink': link,
        'description': post.body,
        'categories': [c.name for c in categories],
        'userid': post.author.id,
        }
    if post.pub_date:
        struct['dateCreated'] = format_date(post.pub_date)
    return struct
The content on this page is provided by a Google Notebook user, and Google assumes no responsibility for this content.