@@ -10,40 +10,212 @@ This tutorial will walk you through our ORM syntax and how to use it to make pro
1010Creating a Connection
1111---------------------
1212
13- In each example I'll be assuming that you have configured and open connection to `syncano `::
13+ In each example I'll be assuming that you have configured connection to `syncano `::
1414
1515 >>> import syncano
1616 >>> connection = syncano.connect(email='YOUR_EMAIL', password='YOUR_PASSWORD')
1717
1818
19- Getting Existing Objects
20- ------------------------
19+ Accessing models
20+ ----------------
2121
22+ All models are defined in :mod: `syncano.models.base ` but ``syncano `` simplifies access to them
23+ by attaching all of them directly to ``connection ``. Thus::
2224
23- Creating New Objects
24- --------------------
25+ from syncano.models.base import Instance
2526
27+ and::
2628
27- Updating Existing Object
28- ------------------------
29+ Instance = connection.Instance
2930
31+ are equivalent.
3032
31- Deleting Existing Object
32- ------------------------
33+ Creating objects
34+ ----------------
35+
36+ A model class represents a single ``Syncano API `` endpoint,
37+ and an instance of that class represents a particular record in this endpoint.
38+
39+ To create an object, instantiate it using **keyword arguments ** to the model class,
40+ then call :meth: `~syncano.models.base.Model.save ` to save it to the ``Syncano API ``.
41+
42+ Here’s an example::
43+
44+ >>> instance = Instance(name='test-one', description='')
45+ >>> instance.save()
46+
47+ This performs a **POST ** request to ``Syncano API `` behind the scenes.
48+ Syncano doesn’t hit the API until you explicitly call :meth: `~syncano.models.base.Model.save `.
3349
50+ .. note ::
51+ To create and save **an object ** in a single step, use the :meth: `~syncano.models.manager.Manager.create ` method.
52+ To create and save **multiple objects ** in a single step, use the :meth: `~syncano.models.manager.Manager.bulk_create ` method.
3453
35- Relations
36- ---------
3754
55+ Saving changes to objects
56+ -------------------------
3857
39- Getting a raw JSON
58+ To save changes to an object that’s already in the ``Syncano API ``, use :meth: `~syncano.models.base.Model.save `.
59+ Regarding our **instance ** from previous example,
60+ this example changes its description and updates its record in the ``Syncano API ``::
61+
62+ >>> instance.description = ' new description'
63+ >>> instance.save()
64+
65+ This performs a **PUT ** request to ``Syncano API `` behind the scenes.
66+ Syncano doesn’t hit the API until you explicitly call :meth: `~syncano.models.base.Model.save `.
67+
68+ .. note ::
69+ To change and save **an object ** in a single step, use the :meth: `~syncano.models.manager.Manager.update ` method.
70+
71+
72+ Retrieving objects
4073------------------
4174
75+ To retrieve objects from ``Syncano API ``, construct a query via a :class: `~syncano.models.manager.Manager ` on your model class.
76+
77+ Each model has only one :class: `~syncano.models.manager.Manager `, and it’s called **please ** by default.
78+ Access it directly via the model class, like so::
79+
80+ >>> Instance.please
81+ [<Instance: test>, <Instance: test-two>, '...(remaining elements truncated)...']
82+ >>> i = Instance(name='Foo', description='Bar')
83+ >>> i.please
84+ Traceback:
85+ ...
86+ AttributeError: Manager isn't accessible via Instance instances.
87+
88+ .. note ::
89+ **Managers ** are accessible only via model classes, rather than from model instances,
90+ to enforce a separation between “table-level” operations and “record-level” operations.
91+
92+
93+ Retrieving all objects
94+ ----------------------
95+
96+ The simplest way to retrieve objects from a ``Syncano API `` is to get all of them.
97+ To do this, use the :meth: `~syncano.models.manager.Manager.all ` or :meth: `~syncano.models.manager.Manager.list `
98+ method on a :class: `~syncano.models.manager.Manager `::
99+
100+ >>> Instance.please
101+ >>> Instance.please.all()
102+ >>> Instance.please.list()
103+
104+ This performs a **GET ** request to ``Syncano API `` list endpoint behind the scenes.
105+
106+ Manager is lazy
107+ ---------------
108+
109+ :class: `~syncano.models.manager.Manager ` is lazy – the act of creating a **Manager ** doesn’t involve any API activity.
110+ You can stack filters Manager methods all day long, and Syncano won’t actually run the API call until the **Manager ** is evaluated.
111+ Take a look at this example::
112+
113+ >>> query = Class.please.list(' test-instance' )
114+ >>> query = query.limit(10 )
115+ >>> print (query)
116+
117+ Though this looks like two API calls, in fact it hits API only once, at the last line (``print(query) ``).
118+ In general, the results of a :class: `~syncano.models.manager.Manager ` aren’t fetched from API until you “ask” for them.
119+
120+
121+ Retrieving a single object
122+ --------------------------
123+
124+ If you know there is only one object that matches your API call,
125+ you can use the :meth: `~syncano.models.manager.Manager.get ` method on a :class: `~syncano.models.manager.Manager `
126+ which returns the object directly::
127+
128+ >>> instance = Instance.please.get(' instance-name' )
129+
130+ This performs a **GET ** request to ``Syncano API `` details endpoint behind the scenes.
131+
132+ If there are no results that match the API call, :meth: `~syncano.models.manager.Manager.get `
133+ will raise a :class: `~syncano.exceptions.SyncanoDoesNotExist ` exception.
134+ This exception is an attribute of the model class that the API call is being performed on - so in the code above,
135+ if there is no **Instance ** object with a name equal "instance-name", Syncano will raise **Instance.DoesNotExist **.
136+
137+ .. note ::
138+ To have more RESTful like method names there is :meth: `~syncano.models.manager.Manager.detail `
139+ alias for :meth: `~syncano.models.manager.Manager.get ` method.
140+
141+
142+ Removing a single object
143+ ------------------------
144+
145+ The delete method, conveniently, is named :meth: `~syncano.models.base.Model.delete `.
146+ This method immediately deletes the object and has no return value.
147+ Example::
148+
149+ >>> instance = Instance.please.get(' test-one' )
150+ >>> instance.delete()
151+
152+ This performs a **DELETE ** request to ``Syncano API `` details endpoint behind the scenes.
153+
154+
155+ Limiting returned objects
156+ -------------------------
157+
158+ Use a subset of Python’s array-slicing syntax to limit your
159+ :class: `~syncano.models.manager.Manager ` to a certain number of results.
160+
161+ For example, this returns the first 5 objects::
162+
163+ >>> Instance.please[:5 ]
164+
165+ This returns the sixth through tenth objects::
166+
167+ >>> Instance.please[5 :10 ]
168+
169+ Negative indexing (i.e. **Instance.please.all()[-1] **) is not supported.
170+
171+ .. note ::
172+ If you don't want to use array-slicing syntax there
173+ is a special manager method called :meth: `~syncano.models.manager.Manager.limit `.
174+
175+
176+ .. warning ::
177+ Python’s array-slicing syntax is a expensive operation in context of API calls so using
178+ :meth: `~syncano.models.manager.Manager.limit ` is a recommended way.
179+
180+
181+ Lookups that span relationships
182+ -------------------------------
183+
184+
185+ Related objects
186+ ---------------
187+
188+
189+ Falling back to raw JSON
190+ ------------------------
191+
192+ If you find yourself needing to work on raw JSON data instead of Python objects just use
193+ :meth: `~syncano.models.manager.Manager.raw ` method::
194+
195+ >>> Instance.please.list()
196+ [<Instance: test>, <Instance: test-two>, '...(remaining elements truncated)...']
197+
198+ >>> Instance.please.list().raw()
199+ [{u'name': u'test-one'...} ...]
200+
201+ >>> Instance.please.raw().get('test-one')
202+ {u'name': u'test-one'...}
42203
43- Connection juggling
44- -------------------
45204
46205
47206Environmental variables
48207-----------------------
49208
209+ Some settings can be overwritten via environmental variables e.g:
210+
211+ .. code-block :: bash
212+
213+ $ export SYNCANO_LOGLEVEL=DEBUG
214+ $ export SYNCANO_APIROOT=' https://127.0.0.1/'
215+ $ export SYNCANO_EMAIL=admin@syncano.com
216+ $ export SYNCANO_PASSWORD=dummy
217+ $ export SYNCANO_APIKEY=dummy123
218+ $ export SYNCANO_INSTANCE=test
219+
220+ .. warning ::
221+ **DEBUG ** loglevel will **disbale ** SSL cert check.
0 commit comments