# Quick tour of Guillotina

Guillotina is powerful datastore, capable of storing and indexing millions of objects.

It is a high performance web server based on many of the technologies and lessons learned
from [Plone](https://plone.org "Link to Plone"), [Pyramid](https://trypyramid.com/ "Link to Pyramid"),
[Django](https://www.djangoproject.com/ "Link to Django") and others all while utilizing
Python's great [AsyncIO](https://docs.python.org/3/library/asyncio.html "Link to AsyncIO") library.

Using Python's AsyncIO, it works well with micro-service oriented environments.

Features:
 - REST JSON API
 - Built-in authentication/authorization, built-in JWT support
 - Hierarchical data/url structure. Object storage.
 - Permissions/roles/groups
 - Fully customizable permission/roles/groups based on hierarchical data structure
 - Robust customizable component architecture and configuration syntax
 - Content types, dynamic behaviors, based on python interfaces and json schemas.
 - Built-in CORS support
 - Serialization/Validation library integrated.
 - Elastic search integration through guillotina_elasticsearch, or fallback to [PostgreSQL](https://www.postgresql.org/ "Link to PostgreSQL")
   json indexing.
 - Declarative configuration using decorators.
 - Integrated cloud storage file uploads.
 - py.test fixtures for easy service/api/endpoint testing
 - Built-in command system to run jobs.
 - Rich ecosystem of additional packages for adding additional features: Integration with
   [RabbitMQ](https://www.rabbitmq.com/), batching of queries, redis cache layer.
 - Powerful  addon architecture based on [Zope](https://www.zope.org/ "Link to Zope") Component Architecture.


## What is Guillotina like?

### Example configuration:

```eval_rst
.. literalinclude:: examples/quick-tour/config.yaml
```

### Example service:

See [instructions below](#playing-with-those-examples) to play with.

```eval_rst
.. literalinclude:: examples/quick-tour/service.py
```

### Example content type:

See [instructions below](#playing-with-those-examples) to play with.

```eval_rst
.. literalinclude:: examples/quick-tour/ct.py
```

### Example usage:

See [instructions below](#playing-with-those-examples) to play with.

```eval_rst
.. http:post:: /db/container/

    Create MyType

    **Example**

    ..  http:example:: curl wget httpie python-requests

        POST /db/container HTTP/1.1
        Accept: application/json
        Content-Type: application/json
        Host: localhost:8080
        Authorization: Basic cm9vdDpyb290

        {
          "@type": "MyType",
          "id": "foobar",
          "foobar": "foobar"
        }


        HTTP/1.1 201 OK
        Content-Type: application/json

    :reqheader Authorization: Required token to authenticate
    :statuscode 201: no error
    :statuscode 401: Invalid Auth code
    :statuscode 500: Error processing request


.. http:get:: /db/container/foobar/

    Get MyType

    **Example**

    ..  http:example:: curl wget httpie python-requests

        GET /db/container/foobar HTTP/1.1
        Accept: application/json
        Host: localhost:8080
        Authorization: Basic cm9vdDpyb290


        HTTP/1.1 200 OK
        Content-Length: 851
        Content-Type: application/json

        {
            "@id": "http://localhost:8080/db/container/foobar",
            "@name": "foobar",
            "@type": "MyType",
            "@uid": "e3f|81c5406638bd4a68b89275f739fc18b2",
            "UID": "e3f|81c5406638bd4a68b89275f739fc18b2",
            "creation_date": "2018-07-21T13:14:15.245181+00:00",
            "foobar": "foobar",
            "guillotina.behaviors.dublincore.IDublinCore": {
                "contributors": [
                    "root"
                ],
                "creation_date": "2018-07-21T13:14:15.245181+00:00",
                "creators": [
                    "root"
                ],
                "description": null,
                "effective_date": null,
                "expiration_date": null,
                "modification_date": "2018-07-21T13:14:15.245181+00:00",
                "publisher": null,
                "tags": null,
                "title": null
            },
            "is_folderish": false,
            "modification_date": "2018-07-21T13:14:15.245181+00:00",
            "parent": {
                "@id": "http://localhost:8080/db/container",
                "@name": "container",
                "@type": "Container",
                "@uid": "e3f4e401d12843a4a303666da4158458",
                "UID": "e3f4e401d12843a4a303666da4158458"
            }
        }



    :reqheader Authorization: Required token to authenticate
    :statuscode 200: no error
    :statuscode 401: Invalid Auth code
    :statuscode 500: Error processing request


.. http:post:: /db/@foobar

    Use foobar service

    **Example**

    ..  http:example:: curl wget httpie python-requests

        POST /db/@foobar HTTP/1.1
        Accept: application/json
        Host: localhost:8080
        Authorization: Basic cm9vdDpyb290


        HTTP/1.1 201 OK
        Content-Type: application/json

        { "foo": "bar"}

    or

    ..  http:example:: curl wget httpie python-requests

        POST /db/container/@foobar HTTP/1.1
        Accept: application/json
        Host: localhost:8080
        Authorization: Basic cm9vdDpyb290


        HTTP/1.1 201 OK
        Content-Type: application/json

        { "foo": "bar"}

    or

    ..  http:example:: curl wget httpie python-requests

        POST /db/container/foobar/@foobar HTTP/1.1
        Accept: application/json
        Host: localhost:8080
        Authorization: Basic cm9vdDpyb290


        HTTP/1.1 201 OK
        Content-Type: application/json

        { "foo": "bar"}


    :reqheader Authorization: Required token to authenticate
    :statuscode 200: no error
    :statuscode 401: Invalid Auth code
    :statuscode 500: Error processing request

    You can see that `@foobar` service is available on any endpoints.
```

### Playing with those examples

To play with those examples you should install Guillotina and [Cookiecutter](https://cookiecutter.readthedocs.io "Link to cookiecutter"),
let's do that in a python venv:

```shell
python3.7 -m venv .
source ./bin/activate
pip install guillotina cookiecutter
```

Use Guillotina templates to create an application:

```shell
./bin/g create --template=application
full_name []: My App
email []: guillotina@myapp.io
package_name [guillotina_myproject]: myapp
project_short_description [Guillotina server application python project]:
Select open_source_license:
1 - MIT license
2 - BSD license
3 - ISC license
4 - Apache Software License 2.0
5 - GNU General Public License v3
6 - Not open source
Choose from 1, 2, 3, 4, 5, 6 [1]:
```

You should now have a structure like the following one:

```
.
└── myapp
    ├── README.rst
    ├── config.yaml
    ├── myapp
    │   ├── __init__.py
    │   ├── api.py
    │   └── install.py
    └── setup.py
```

Now copy [Example content type](#example-content-type) section content in `myapp/myapp/content.py`.

Add `configure.scan('myapp.content')` to `myapp/myapp/__init__.py` `includeme` function.

`@foobar` service is already defined in `myapp/mayapp/api.py`.

Then install `myapp`:

```shell
pip install -e myapp
```

Edit `myapp/config.yaml` to fit your needs, especially in term of db configuration.

And run guillotina with:

```shell
g serve -c myapp/config.yaml
```

Now create a container:


```eval_rst
..  http:example:: curl wget httpie python-requests

    POST /db/ HTTP/1.1
    Accept: application/json
    Content-Type: application/json
    Host: localhost:8080
    Authorization: Basic cm9vdDpyb290

    {
        "@type": "Container",
        "title": "Container 1",
        "id": "container",
        "description": "Description"
    }


    HTTP/1.1 201 OK
    Content-Type: application/json

```

You can now use all above examples.
