Skip to main content

django Fake ORM model that query an RestAPI instead of a database —

Project description

allow to query an RestAPI (django-rest-framework + dynamic-rest) with same same interface as the django ORM. if fact, it work like any other database engin. you add the rest_models engin in an alternate database, the router, and add a APIMeta class to your models, and let’s go.

stable branche

https://img.shields.io/travis/Yupeek/django-rest-models/master.svg https://readthedocs.org/projects/django-rest-models/badge/?version=latest https://coveralls.io/repos/github/Yupeek/django-rest-models/badge.svg?branch=master Latest PyPI version Number of PyPI downloads per month Requirements Status

development status

https://img.shields.io/travis/Yupeek/django-rest-models/develop.svg https://coveralls.io/repos/github/Yupeek/django-rest-models/badge.svg?branch=develop Requirements Status

Installation

  1. Install using pip:

    pip install django-rest-models

  2. Alternatively, you can install download or clone this repo and call

    pip install -e ..

requirements

this database wrapper work with

  • python 2.7, 3.4, 3.5

  • django 1.8 , 1.9, 1.10

on the api, this is tested against

  • django-rest-framework 3.4, 3.5

  • dynamic-rest 1.5, 1.6

exemples

settings.py:

DATABASES = {
    'default': {
        ...
    },
    'api': {
        'ENGINE': 'rest_models.backend',
        'NAME': 'https://requestb.in/',
        'USER': 'userapi',
        'PASSWORD': 'passwordapi',
        'AUTH': 'rest_models.backend.auth.BasicAuth',
    },
}

DATABASE_ROUTERS = [
    'rest_models.router.RestModelRouter',
]

models.py:

class MyModel(models.Model):
    field = models.IntegerField()
    ...

    class Meta:
        # basic django meta Stuff
        verbose_name = 'my model'

    # the only customisation that make this model special
    class APIMeta:
        pass

constraints

to allow this database adaptater to work like a relational one, the API targeted must respect some requirments

  • dynamic-rest installed and all the serializers must provide it’s functionnality (hinerit from DynamicModelSerializer)

each serializers must :

  • provide the id fields

  • provide the related field (ManyToMany and ForeignKey on Models) as DynamicRelationField

  • provide the reverse related field (each ForeignKey and manyToMany add a relation on the other models. the serializer from the other model must provide the DynamicRelationField for these relation

class MenuSerializer(DynamicModelSerializer):
    pizzas = DynamicRelationField('PizzaSerializer', many=True)

    class Meta:
        model = Menu
        name = 'menu'
        fields = ('id', 'code', 'name', 'pizzas')
        deferred_fields = ('pizza_set', )


class PizzaSerializer(DynamicModelSerializer):

    toppings = DynamicRelationField(ToppingSerializer, many=True)
    menu = DynamicRelationField(MenuSerializer)

    class Meta:
        model = Pizza
        name = 'pizza'
        fields = ('id', 'name', 'price', 'from_date', 'to_date', 'toppings', 'menu')

Django rest models provide a way to check the consistency of the api with the local models via the django check framework. at each startup, it will query the api with OPTIONS to check if the local models match the remote serializers.

limitations

since this is not a real relational database, all feathure cannot be implemented. some limitations are inherited by dynamic-rest filtering system too.

  • aggregations : is not implemented on the api endpoint. maybe in future release

  • complexe filtering using OR : all filter passed to dynamic-rest is ANDed together, so no OR is possible

  • negated AND in filtering: a negated AND give a OR, so previous limitation apply

  • negated OR in filtering: since the compitation of nested filter is complexe and error prone, we disable all OR. in fact, only some nested of AND is accepted. only the final value of the Q() object can be negated

    for short, you can’t :

    Pizza.objects.aggregate()
    Pizza.objects.annotate()
    Pizza.objects.filter(Q(..) | Q(..))
    Pizza.objects.exclude(Q(..) & Q(..))
    Pizza.objects.exclude(Q(..) | Q(..))

but you can :
Pizza.objects.create
Pizza.objects.bulk_create
Pizza.objects.update
Pizza.objects.bulk_update
Pizza.objects.select_related
Pizza.objects.prefetch_related
Pizza.objects.values
Pizza.objects.values_list
Pizza.objects.delete
Pizza.objects.count()
Pizza.objects.filter(..., ..., ...)
Pizza.objects.filter(...).filter(...).exclude(...)
Pizza.objects.exclude(..., ...).exclude(...)
Pizza.objects.filter(Q(..) & Q(..))

specific comportments

some specific behaviour has been implemented to use the extra functionnality of a Rest API :

  • whene inserting, the resulting model is returned by the API. the inserted model is updated with the resulting values. this imply 2 behavior:

    • if you provided a default data in the api, this data will be populated into your created instance if it was missed

    • if the serializer have some cumputed data, its data will always be used as a replacment of the one you gave to your models. (see exemple Pizza.cost which is the sum of the cost of the toppling. after each save, its value will be updated)

support

this database api support :

  • select_related

  • order_by

  • only

  • defer

  • filter

  • exclude

  • delete

  • update

  • create

  • bulk create (with retrive of pk)

  • ManyToManyField

  • ForeignKey

Documentation

The full documentation is at http://django-rest-models.readthedocs.org/en/latest/.

Requirements

  • Python 2.7, 3.4, 3.5

  • Django >= 1.8

Contributions and pull requests for other Django and Python versions are welcome.

Bugs and requests

If you have found a bug or if you have a request for additional functionality, please use the issue tracker on GitHub.

https://github.com/Yupeek/django-rest-models/issues

License

You can use this under GPLv3.

Author

Original author: Darius BERNARD.

Thanks

Thanks to django for this amazing framework.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

django-rest-models-1.4.0.tar.gz (50.9 kB view details)

Uploaded Source

Built Distribution

django_rest_models-1.4.0-py2.py3-none-any.whl (42.7 kB view details)

Uploaded Python 2 Python 3

File details

Details for the file django-rest-models-1.4.0.tar.gz.

File metadata

File hashes

Hashes for django-rest-models-1.4.0.tar.gz
Algorithm Hash digest
SHA256 2333e7a089baea215588d4f527bad4760479cb9c65352edb64d4fd3a6e1acc1f
MD5 819c24c5ef6ed8f5da93a2644051d562
BLAKE2b-256 a670a1bb283ca15b6475ec51b38d476795d1ee75c1a764cc373cb799852a9e01

See more details on using hashes here.

File details

Details for the file django_rest_models-1.4.0-py2.py3-none-any.whl.

File metadata

File hashes

Hashes for django_rest_models-1.4.0-py2.py3-none-any.whl
Algorithm Hash digest
SHA256 2e4cc619772d9aa02654acdaba2261df2463610613025bef8f4eca67ef5a8498
MD5 5c9c16fe30855024328c1b9aa8ed3514
BLAKE2b-256 333d24d8eeed381edf739b43a24b23096e768e0e64ade21751d1284402c9b48a

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page