Web to py enterprise web framework - p 20 pdf

10 194 0
Web to py enterprise web framework - p 20 pdf

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

Thông tin tài liệu

OTHER OPERATORS 175 6.10 Other Operators web2py has other operators that provide an API to access equivalent SQL operators. Let’s define another table "log" to store security events, their timestamp and severity, where the severity is an integer number. 1 >>> db.define_table('log', Field('event'), 2 Field('timestamp', 'datetime'), 3 Field('severity', 'integer')) As before, insert a few events, a "port scan", an "xss injection" and an "unauthorized login". For the sake of the example, you can log events with the same timestamp but with different severities (1, 2, 3 respectively). 1 >>> import datetime 2 >>> now = datetime.datetime.now() 3 >>> print db.log.insert(event='port scan', timestamp=now, severity=1) 4 1 5 >>> print db.log.insert(event='xss injection', timestamp=now, severity=2) 6 2 7 >>> print db.log.insert(event='unauthorized login', timestamp=now, severity=3) 8 3 like, upper, lower Fields have a like operator that you can use to match strings: 1 >>> for row in db(db.log.event.like('port%')).select(): 2 print row.event 3 port scan Here "port%" indicates a string starting with "port". The percent sign char- acter, "%", is a wild-card character that means "any sequence of characters". Similarly, you can use upper and lower methods to convert the value of the field to upper or lower case, and you can also combine them with the like operator. 1 >>> for row in db(db.log.event.upper().like('PORT%')).select(): 2 print row.event 3 port scan year, month, day, hour, minutes, seconds The date and datetime fields haveday, month and year methods. The datetime and time fields have hour, minutes and seconds methods. Here is an example: 176 THE DATABASE ABSTRACTION LAYER 1 >>> for row in db(db.log.timestamp.year()==2009).select(): 2 print row.event 3 port scan 4 xss injection 5 unauthorized login belongs The SQL IN operator is realized via the belongs method which returns true when the field value belongs to the specified set (list of tuples): 1 >>> for row in db(db.log.severity.belongs((1, 2))).select(): 2 print row.event 3 port scan 4 xss injection The DAL also allows a nested select as the argument of the belongs opera- tor. The only caveat is that the nested select has to be a select, not a select, and only one field has to be selected explicitly, the one that defines the set. 1 >>> bad_days = db(db.log.severity==3)._select(db.log.timestamp) 2 >>> for row in db(db.log.timestamp.belongs(bad_days)).select(): 3 print row.event 4 port scan 5 xss injection 6 unauthorized login Previously, you have used the count operator to count records. Similarly, you can use the sum operator to add (sum) the values of a specific field from a group of records. As in the case of count, the result of a sum is retrieved via the extra dictionary. 1 >>> sum = db.log.severity.sum() 2 >>> print db().select(sum)[0]._extra[sum] 3 6 6.11 Caching Selects The select method also takes a cache argument, which defaults to None. For caching purposes, it should be set to a tuple where the first element is the cache model (cache.ram, cache.disk, etc.), and the second element is the expiration time in seconds. In the following example, you see a controller that caches a select on the previously defined db.log table. The actual select fetches data from the back- end database no more frequently than once every 60 seconds and stores the SHORTCUTS 177 result in cache.ram. If the next call to this controller occurs in less than 60 seconds since the last database IO, it simply fetches the previous data from cache.ram. 1 def cache_db_select(): 2 logs = db().select(db.log.ALL, cache=(cache.ram, 60)) 3 return dict(logs=logs) The results of a select are complex, unpickleable objects; they cannot be stored in a session and cannot be cached in any other way than the one explained here. 6.12 Shortcuts The DAL supports various code-simplifying shortcuts. In particular: 1 db.mytable[id] returns the record with the given id if it exists. If the id does not exist, it returns None. 1 del db.mytable[id] deletes the record with the given id, if it exists. 1 db.mytable[0] = dict(myfield='somevalue') creates a new record with field values specified by the dictionary on the right hand side. 1 db.mytable[id] = dict(myfield='somevalue') updates an existing record with field values specified by the dictionary on the right hand side. 6.13 Self-Reference and Aliases It is possible to define tables with fields that refer to themselves although the usual notation may fail. The following code would be wrong because it uses a variable db.person before it is defined: 1 db.define_table('person', 2 Field('name'), 3 Field('father_id', db.person), 4 Field('mother_id', db.person)) The solution consists of using an alternate notation 178 THE DATABASE ABSTRACTION LAYER 1 db.define_table('person', 2 Field('name'), 3 Field('father_id', 'reference person'), 4 Field('mother_id', 'reference person')) In fact db.tablename and "reference tablename" are equivalent field types. If the table refers to itself, then it is not possible to perform a JOIN to select a person and its parents without use of the SQL "AS" keyword. This is achieved in web2py using the with alias. Here is an example: 1 >>> Father = db.person.with_alias('father') 2 >>> Mother = db.person.with_alias('mother') 3 >>> db.person.insert(name='Massimo') 4 1 5 >>> db.person.insert(name='Claudia') 6 2 7 >>> db.person.insert(name='Marco', father_id=1, mother_id=2) 8 3 9 >>> rows = db().select(db.person.name, Father.name, Mother.name, 10 left=(Father.on(Father.id==db.person.father_id), 11 Mother.on(Mother.id==db.person.mother_id))) 12 >>> for row in rows: 13 print row.person.name, row.father.name, row.mother.name 14 Massimo None None 15 Claudia None None 16 Marco Massimo Claudia Notice that we have chosen to make a distinction between: • "father id": the field name used in the table "person"; • "father": the alias we want to use for the table referenced by the above field; this is communicated to the database; • "Father": the variable used by web2py to refer to that alias. The difference is subtle, and there is nothing wrong in using the same name for the three of them: 1 db.define_table('person', 2 Field('name'), 3 Field('father', 'reference person'), 4 Field('mother', 'reference person')) 5 >>> father = db.person.with_alias('father') 6 >>> mother = db.person.with_alias('mother') 7 >>> db.person.insert(name='Massimo') 8 1 9 >>> db.person.insert(name='Claudia') 10 2 11 >>> db.person.insert(name='Marco', father=1, mother=2) 12 3 13 >>> rows = db().select(db.person.name, father.name, mother.name, 14 left=(father.on(father.id==db.person.father), 15 mother.on(mother.id==db.person.mother))) 16 >>> for row in rows: TABLE INHERITANCE 179 17 print row.person.name, row.father.name, row.mother.name 18 Massimo None None 19 Claudia None None 20 Marco Massimo Claudia But it is important to have the distinction clear in order to build correct queries. 6.14 Table Inheritance It is possible to create a table that contains all the fields from another table. It is sufficient to pass the other table in place of a field to define_table. For example 1 db.define_table('person', Field('name')) 2 3 db.define_table('doctor', db.person, Field('specialization')) It is also possible to define a dummy table that is not stored in a database in order to reuse it in multiple other places. For example: 1 current_user_id = (auth.user and auth.user.id) or 0 2 3 timestamp = db.Table(db, 'timestamp_table', 4 Field('created_on', 'datetime', default=request.now), 5 Field('created_by', db.auth_user, default=current_user_id), 6 Field('updated_on', 'datetime', default=request.now), 7 Field('updated_by', db.auth_user, update=current_user_id)) 8 9 db.define_table('payment', timestamp, Field('amount', 'double')) This example assumes that standard web2py authentication is enabled. . OTHER OPERATORS 175 6.10 Other Operators web2 py has other operators that provide an API to access equivalent SQL operators. Let’s define another table "log" to store security. db.define_table('person', 2 Field('name'), 3 Field('father', 'reference person'), 4 Field('mother', 'reference person')) 5 >>> father = db.person.with_alias('father') 6. db.define_table('person', 2 Field('name'), 3 Field('father_id', 'reference person'), 4 Field('mother_id', 'reference person')) In fact

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

Tài liệu cùng người dùng

Tài liệu liên quan