1. Trang chủ
  2. » Công Nghệ Thông Tin

Web to py enterprise web framework - p 9 pot

10 293 0
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 10
Dung lượng 230,08 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

The value of the hypertext reference href attribute is: ịẹ, the URL within the same application and controller as the current request r=request, calling the function called "show",f="sho

Trang 1

contains the The value of the hypertext reference (href attribute) is:

ịẹ, the URL within the same application and controller as the current request

r=request, calling the function called "show",f="show", and passing a single argument to the function,args=imagẹid

LI, A, etc are web2py helpers that map to the corresponding HTML tags Their unnamed arguments are interpreted as objects to be serialized and inserted in the tag’s innerHTML Named arguments starting with an underscore (for example href) are interpreted as tag attributes but without the underscorẹ For example href is thehrefattribute, classis the class

attribute, etc

As an example, the following statement:

1 {{=LI(Ắsomething', _href=URL(r=request, f='show', args=123))}}

is rendered as:

1 <li><a href="/images/default/show/123">something</a></li>

A handful of helpers (INPUT,TEXTAREA,OPTIONandSELECT) also support some special named attributes not starting with underscore (value, andrequires) They are important for building custom forms and will be discussed later

Go back to the [EDIT] pagẹ It now indicates that "default.py exposes index" By clicking on "index", you can visit the newly created page:

1 http://127.0.0.1:8000/images/default/index

which looks like:

Trang 2

66 OVERVIEW

If you click on the image name link, you are directed to:

1 http://127.0.0.1:8000/images/default/show/1

and this results in an error, since you have not yet created an action called

"show" in controller "default.py"

Let’s edit the "default.py" controller and replace its content with:

1 def index():

2 images = db().select(db.image.ALL, orderby=db.image.title)

3 return dict(images=images)

4

5 def show():

6 image = db(db.image.id==request.args(0)).select()[0]

7 form = SQLFORM(db.comment)

8 form.vars.image_id = image.id

9 if form.accepts(request.vars, session):

11 comments = db(db.comment.image_id==image.id).select()

12 return dict(image=image, comments=comments, form=form)

13

14 def download():

15 return response.download(request, db)

The controller contains two actions: "show" and "download" The "show" action selects the image with the id parsed from the request args and all comments related to the image "show" then passes everything to the view

"default/show.html"

The image id referenced by:

in "default/index.html", can be accessed as: request.args(0) from the

"show" action

The "download" action expects a filename in request.args(0), builds a path to the location where that file is supposed to be, and sends it back to the client If the file is too large, it streams the file without incurring any memory overhead

Trang 3

• Line 9 processes the submitted form (the submitted form variables are in request.vars) within the current session (the session is used to prevent double submissions, and to enforce navigation) If the submitted form variables are validated, the new comment is inserted in thedb.comment

table; otherwise the form is modified to include error messages (for example, if the author’s email address is invalid) This is all done in line 9!

• Line 10 is only executed if the form is accepted, after the record is

inserted into the database table response.flash is a web2py vari-able that is displayed in the views and used to notify the visitor that something happened

• Line 11 selects all comments that reference the current image

The "download" action is already defined in the "default.py" controller of the scaffolding application.

The "download" action does not return a dictionary, so it does not need a

view The "show" action, though, should have a view, so return to admin and

create a new view called "default/show.html" by typing "default/show" in the create view form:

Trang 4

68 OVERVIEW

Edit this new file and replace its content with the following:

1 {{extend 'layout.html'}}

2 <h1>Image: {{=image.title}}</h1>

3 <center>

4 <img width="200px"

5 src="{{=URL(r=request, f='download', args=image.file)}}" />

6 </center>

7 {{if len(comments):}}

8 <h2>Comments</h2><br /><p>

9 {{for comment in comments:}}

10 <p>{{=comment.author}} says <i>{{=comment.body}}</i></p>

11 {{pass}}</p>

12 {{else:}}

13 <h2>No comments posted yet</h2>

14 {{pass}}

15 <h2>Post a comment</h2>

16 {{=form}}

This view displays the image.file by calling the "download" action inside

an<img />tag If there are comments, it loops over them and displays each one

Here is how everything will appear to a visitor

Trang 5

When a visitor submits a comment via this page, the comment is stored in the database and appended at the bottom of the page

3.7 Adding CRUD

web2pyalso provides a CRUD (Create/Read/Update/Delete) API that sim-plifies forms even more To use CRUD it is necessary to define it somewhere, such as in module "db.py":

1 from gluon.tools import Crud

2 crud = Crud(globals(), db)

These two lines are already in the scaffolding application.

Thecrudobject provides high-level methods, for example:

1 form = crud.create( )

that can be used to replace the programming pattern:

1 form = SQLFORM( )

2 if form.accepts( ):

Trang 6

70 OVERVIEW

Here, we rewrite the previous "show" action using crud:

1 def show():

2 image = db(db.image.id==request.args(0)).select()[0]

3 db.comment.image_id.default = image.id

4 form = crud.create(db.image, next=URL(r=request, args=image.id),

6 comments = db(db.comment.image_id==image.id).select()

7 return dict(image=image, comments=comments, form=form)

Thenextargument ofcrud.createis the URL to redirect to after the form is accepted Themessageargument is the one to be displayed upon acceptance You can read more about CRUD in Chapter 7

3.8 Adding Authentication

The web2py API for Role-Based Access Control is quite sophisticated, but for now we will limit ourselves to restricting access to the show action to authenticated users, deferring a more detailed discussion to Chapter 8

To limit access to authenticated users, we need to complete three steps In

a model, for example "db.py", we need to add:

1 from gluon.tools import Auth

2 auth = Auth(globals(), db)

3 auth.define_tables()

In our controller, we need to add one action:

1 def user():

2 return dict(form=auth())

Finally, we decorate the functions that we want to restrict, for example:

1 @auth.requires_login()

2 def show():

3 image = db(db.image.id==request.args(0)).select()[0]

4 db.comment.image_id.default = image.id

5 form = crud.create(db.image, next=URL(r=request, args=image.id),

7 comments = db(db.comment.image_id==image.id).select()

8 return dict(image=image, comments=comments, form=form)

Any attempt to access

1 http://127.0.0.1:8000/images/default/show/[image_id]

will require login If the user is not logged it, the user will be redirected to

1 http://127.0.0.1:8000/images/default/user/login

Trang 7

Theuserfunction also exposes, among others, the following actions:

1 http://127.0.0.1:8000/images/default/user/logout

2 http://127.0.0.1:8000/images/default/user/register

3 http://127.0.0.1:8000/images/default/user/profile

4 http://127.0.0.1:8000/images/default/user/change_password

Now, a first time user needs to register in order to be able to login and read/post comments

Both theauthobject and theuserfunction are already defined in the scaffolding application Theauthobject is highly customiz-able and can deal with email verification, registration approvals, CAPTCHA, and alternate login methods via plugins.

3.9 A Wiki

In this section, we build a wiki The visitor will be able to create pages, search them (by title), and edit them The visitor will also be able to post comments (exactly as in the previous applications), and also post documents (as attachments to the pages) and link them from the pages As a convention,

we adopt the Markdown syntax for our wiki syntax We will also implement

a search page with Ajax, an RSS feed for the pages, and a handler to search the pages via XML-RPC [44]

The following diagram lists the actions that we need to implement and the links we intend to build among them

Trang 8

72 OVERVIEW

index

''O O O O O O

create

search

ajax

R R R R

img

bg find

p p p p p p

Start by creating a new scaffolding app, naming it "mywiki"

The model must contain three tables: page, comment, and document Both comment and document reference page because they belong to page

A document contains a file field of type upload as in the previous images application

Here is the complete model:

1 db = DAL('sqlite://storage.db')

2

3 from gluon.tools import *

4 auth = Auth(globals(),db)

5 auth.define_tables()

6 crud = Crud(globals(),db)

7

8 if auth.is_logged_in():

9 user_id = auth.user id

10 else:

11 user_id = None

12

13 db.define_table('page',

18

19 db.define_table('comment',

24

25 db.define_table('document',

31

32 db.page.title.requires = [IS_NOT_EMPTY(), IS_NOT_IN_DB(db, 'page title')]

33 db.page.body.requires = IS_NOT_EMPTY()

Trang 9

49 db.document.name.requires = [IS_NOT_EMPTY(), IS_NOT_IN_DB(db, ' document.name')]

50 db.document.page_id.readable = False

51 db.document.page_id.writable = False

52 db.document.created_by.readable = False

53 db.document.created_by.writable = False

54 db.document.created_on.readable = False

55 db.document.created_on.writable = False

Edit the controller "default.py" and create the following actions:

• index: list all wiki pages

• create: post another wiki page

• show: show a wiki page and its comments, and append comments

• edit: edit an existing page

• documents: manage the documents attached to a page

• download: download a document (as in the images example)

• search: display a search box and, via an Ajax callback, return all

matching titles as the visitor types

• bg find: the Ajax callback function It returns the HTML that gets

embedded in the search page while the visitor types

Here is the "default.py" controller:

1 def index():

2 """ this controller returns a dictionary rendered by the view

4 >>> index().has_key('pages')

6 """

7 pages = db().select(db.page.id, db.page.title,

Trang 10

74 OVERVIEW

10

11 @auth.requires_login()

12 def create():

13 "creates a new empty wiki page"

14 form = crud.create(db.page, next = URL(r=request, f='index'))

15 return dict(form=form)

16

17 def show():

18 "shows a wiki page"

19 thispage = db.page[request.args(0)]

20 if not thispage:

22 db.comment.page_id.default = thispage.id

23 if user_id:

24 form = crud.create(db.comment)

25 else:

27 pagecomments = db(db.comment.page_id==thispage.id).select()

28 return dict(page=thispage, comments=pagecomments, form=form) 29

30 @auth.requires_login()

31 def edit():

32 "edit an existing wiki page"

33 thispage = db.page[request.args(0)]

34 if not thispage:

36 form = crud.update(db.page, thispage,

37 next = URL(r=request, f='show', args=request.args))

38 return dict(form=form)

39

40 @auth.requires_login()

41 def documents():

42 "lists all documents attached to a certain page"

43 thispage = db.page[request.args(0)]

44 if not thispage:

46 db.document.page_id.default = thispage.id

47 form = crud.create(db.document)

48 pagedocuments = db(db.document.page_id==thispage.id).select()

49 return dict(page=thispage, documents=pagedocuments, form=form) 50

51 def user():

52 return dict(form=auth())

53

54 def download():

55 "allows downloading of documents"

56 return response.download(request, db)

57

58 def search():

59 "an ajax wiki search page"

60 return dict(form=FORM(INPUT(_id='keyword',

61 _onkeyup="ajax('bg_find', ['keyword'], 'target');")),

62 target_div=DIV(_id='target'))

63

64 def bg_find():

65 "an ajax callback that returns a <ul> of links to wiki pages"

Ngày đăng: 06/07/2014, 19:20

TỪ KHÓA LIÊN QUAN