1 .. _dbapi: |
|
2 |
|
3 Python/RQL API |
|
4 ~~~~~~~~~~~~~~ |
|
5 |
|
6 The Python API developped to interface with RQL is inspired from the standard db-api, |
|
7 with a Connection object having the methods cursor, rollback and commit essentially. |
|
8 The most important method is the `execute` method of a cursor. |
|
9 |
|
10 .. sourcecode:: python |
|
11 |
|
12 execute(rqlstring, args=None, build_descr=True) |
|
13 |
|
14 :rqlstring: the RQL query to execute (unicode) |
|
15 :args: if the query contains substitutions, a dictionary containing the values to use |
|
16 |
|
17 The `Connection` object owns the methods `commit` and `rollback`. You |
|
18 *should never need to use them* during the development of the web |
|
19 interface based on the *CubicWeb* framework as it determines the end |
|
20 of the transaction depending on the query execution success. They are |
|
21 however useful in other contexts such as tests or custom controllers. |
|
22 |
|
23 .. note:: |
|
24 |
|
25 If a query generates an error related to security (:exc:`Unauthorized`) or to |
|
26 integrity (:exc:`ValidationError`), the transaction can still continue but you |
|
27 won't be able to commit it, a rollback will be necessary to start a new |
|
28 transaction. |
|
29 |
|
30 Also, a rollback is automatically done if an error occurs during commit. |
|
31 |
|
32 .. note:: |
|
33 |
|
34 A :exc:`ValidationError` has a `entity` attribute. In CubicWeb, |
|
35 this atttribute is set to the entity's eid (not a reference to the |
|
36 entity itself). |
|
37 |
|
38 Executing RQL queries from a view or a hook |
|
39 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|
40 |
|
41 When you're within code of the web interface, the db-api like connexion is |
|
42 handled by the request object. You should not have to access it directly, but |
|
43 use the `execute` method directly available on the request, eg: |
|
44 |
|
45 .. sourcecode:: python |
|
46 |
|
47 rset = self._cw.execute(rqlstring, kwargs) |
|
48 |
|
49 Similarly, on the server side (eg in hooks), there is no db-api connexion (since |
|
50 you're directly inside the data-server), so you'll have to use the execute method |
|
51 of the session object. |
|
52 |
|
53 |
|
54 Proper usage of `.execute` |
|
55 ~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|
56 |
|
57 Let's say you want to get T which is in configuration C, this translates to: |
|
58 |
|
59 .. sourcecode:: python |
|
60 |
|
61 self._cw.execute('Any T WHERE T in_conf C, C eid %s' % entity.eid) |
|
62 |
|
63 But it must be written in a syntax that will benefit from the use |
|
64 of a cache on the RQL server side: |
|
65 |
|
66 .. sourcecode:: python |
|
67 |
|
68 self._cw.execute('Any T WHERE T in_conf C, C eid %(x)s', {'x': entity.eid}) |
|
69 |
|
70 The syntax tree is built once for the "generic" RQL and can be re-used |
|
71 with a number of different eids. There rql IN operator is an exception |
|
72 to this rule. |
|
73 |
|
74 .. sourcecode:: python |
|
75 |
|
76 self._cw.execute('Any T WHERE T in_conf C, C name IN (%s)' |
|
77 % ','.join(['foo', 'bar'])) |
|
78 |
|
79 Alternativelly, some of the common data related to an entity can be |
|
80 obtained from the `entity.related()` method (which is used under the |
|
81 hood by the orm when you use attribute access notation on an entity to |
|
82 get a relation. The initial request would then be translated to: |
|
83 |
|
84 .. sourcecode:: python |
|
85 |
|
86 entity.related('in_conf', 'object') |
|
87 |
|
88 Additionnaly this benefits from the fetch_attrs policy (see |
|
89 :ref:`FetchAttrs`) eventually defined on the class element, which says |
|
90 which attributes must be also loaded when the entity is loaded through |
|
91 the orm. |
|
92 |
|
93 |
|
94 .. _resultset: |
|
95 |
|
96 The `ResultSet` API |
|
97 ~~~~~~~~~~~~~~~~~~~ |
|
98 |
|
99 ResultSet instances are a very commonly manipulated object. They have |
|
100 a rich API as seen below, but we would like to highlight a bunch of |
|
101 methods that are quite useful in day-to-day practice: |
|
102 |
|
103 * `__str__()` (applied by `print`) gives a very useful overview of both |
|
104 the underlying RQL expression and the data inside; unavoidable for |
|
105 debugging purposes |
|
106 |
|
107 * `printable_rql()` produces back a well formed RQL expression as a |
|
108 string; it is very useful to build views |
|
109 |
|
110 * `entities()` returns a generator on all entities of the result set |
|
111 |
|
112 * `get_entity(row, col)` gets the entity at row, col coordinates; one |
|
113 of the most used result set method |
|
114 |
|
115 .. autoclass:: cubicweb.rset.ResultSet |
|
116 :members: |
|
117 |
|
118 |
|
119 The `Cursor` and `Connection` API |
|
120 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|
121 |
|
122 The whole cursor API is developped below. |
|
123 |
|
124 .. note:: |
|
125 |
|
126 In practice you'll usually use the `.execute` method on the _cw object of |
|
127 appobjects. Usage of other methods is quite rare. |
|
128 |
|
129 .. autoclass:: cubicweb.dbapi.Cursor |
|
130 :members: |
|
131 |
|
132 .. autoclass:: cubicweb.dbapi.Connection |
|
133 :members: |
|