Skip to main content

为 Django 应用程序创建 REST API 的库

项目描述

Django 休息

不要在生产中使用!!! 这个包是非常早期的 alpha 版本,没有测试!它目前更多的是概念证明。

哲学

Django RestUp 从其他 Django REST API 包(如 Django REST Framework、Django Tastypie 和 Restless)中汲取了久经考验的想法。

它通过应用更多的灵活性/可扩展性和明确性来扩展这些想法。有一个权衡。RestUp 需要比其他包/库更多的配置。

RestUp 与其他包的主要区别在于 RestUp 如何确定 API 数据结构。RestUp 要求开发人员在每个资源的基础上明确声明其数据的结构。

这种明确性带来了一些主要好处:

  • 对您的数据进行额外的安全性和完整性检查。

  • 可以轻松查看数据结构并更改该结构而不会产生副作用。

  • 仅公开您想要公开的数据,并以您想要公开的方式公开。

  • 允许在每个资源、每个对象甚至每个字段的基础上进行深度身份验证和授权。

入门

模式定义

RestUp ModelResource的核心是它的模式定义。您将架构定义为本机 Python 字典对象。此模式用于填充GET请求的 JSON 响应。它还用于帮助将POST ed 数据反序列化为原生 python 数据类型,以便它可以用于创建新对象或修改现有对象。

示例: 假设我们有一个具有以下结构的 Django 模型:

# In ~/yourapp/models.py
from django.db import models


class Book(models.Model):

    title = models.CharField(
        max_lenfth=200,
        blank=False
    )

    isbn = models.CharField(
        max_length=100,
        blank=False
    )

    favorites = models.PositiveIntegerField(
        blank=True,
        default=0
    )

    secret_field = models.CharField(
        max_length=20,
        blank=False
    )

让我们定义一个 RestUp ModelResource类来公开这个资源:

# In ~/yourapp/api.py
from restup import ModelResource
from .models import Book


class BookResource(ModelResource):

    model = Book

    schema = {
        'title': {
            'attribute': 'title'
        },
        'isbn': {
            'attribute': 'isbn'
        },
        'favorites': {
            'attribute': 'favorites'
        },
        'secret_field': {
            'attribute': 'secret_field'
        }
    }

您还需要告诉 Django 在哪里可以找到该资源的 url:

# In ~/yourproject/urls.py

# ~~? (other imports)
from django.conf.urls import include
from yourapp.api import BookResource

urlpatterns = [
    # ...?
    url(
        r'^api/books/', include(BookResource.urls())
    )
]

这就是您需要定义的所有内容,以便向端点发出任何GET、POST、PUT、DELETE 请求。

权限

然而,现在,我们只允许任何人弄乱我们的数据!根本没有安全感!我们只希望登录用户能够操作数据。我们将允许任何人获取它:

# In ~/yourapp/api.py
from restup import ModelResource
from .models import Book


class BookResource(ModelResource):

    model = Book

    schema = {
        'title': {
            'attribute': 'title'
        },
        'isbn': {
            'attribute': 'isbn'
        },
        'favorites': {
            'attribute': 'favorites'
        },
        'secret_field': {
            'attribute': 'secret_field'
        }
    }

    def is_authenticated(self, request): # 添加这个方法覆盖
        如果 self.SAFE_METHODS 中的 request.method:
            返回真
        返回 request.user.is_authenticated()

你可以在is_authenticated方法中放入任何你想要的东西,只要它对经过身份验证的请求返回 true,对未经授权的请求返回 false。您会注意到您可以访问请求对象。这是一个普通的 Django 请求对象。你可以用它做任何你可以在普通的 Django 视图类中做的事情。is_authenticated方法是在任何请求中调用的第二个权限挂钩。它在允许的方法检查之后和请求被路由到正确的操作处理程序之前立即调用。说到允许的方法检查,我们不希望任何人能够删除我们的模型。让我们阻止他们这样做:

# In ~/yourapp/api.py
from restup import ModelResource
from .models import Book


class BookResource(ModelResource):

    model = Book

    schema = {
        'title': {
            'attribute': 'title'
        },
        'isbn': {
            'attribute': 'isbn'
        },
        'favorites': {
            'attribute': 'favorites'
        },
        'secret_field': {
            'attribute': 'secret_field'
        }
    }

    def is_authenticated(自我,请求):
        如果 self.SAFE_METHODS 中的 request.method:
            返回真
        返回 request.user.is_authenticated()

    def can_delete(self, obj, request): # 覆盖这个方法
        返回假

我们去吧!现在,对任何BookResource端点的所有DELETE请求都将返回403 Forbidden HTTP 响应。secret_field 字段呢?当然,我们不希望每个人都看到这一点?但是,我们需要用来自客户端的数据填充它。这就是 RestUp 变得特别的地方:

# In ~/yourapp/api.py
from restup import ModelResource
from .models import Book


class BookResource(ModelResource):

    model = Book

    schema = {
        'title': {
            'attribute': 'title'
        },
        'isbn': {
            'attribute': 'isbn'
        },
        'favorites': {
            'attribute': 'favorites'
        },
        'secret_field': {
            'attribute': 'secret_field',
            'readable': False  # Add this line
        }
    }

    def is_authenticated(self, request):
        if request.method in self.SAFE_METHODS:
            return True
        return request.user.is_authenticated()

    def can_delete(self, obj, request):
        return False

我们需要做的就是在模式中的字段声明中添加一个“可读”键,并将其值设置为False。这将确保此数据不会发送给任何请求的客户端。但是,我们仍然可以将POST ed 数据应用于该字段。

对象级权限

我们只希望员工用户能够创建和更新任何Book对象。让我们确保没有其他人可以:

# In ~/yourapp/api.py
from restup import ModelResource
from .models import Book


class BookResource(ModelResource):

    model = Book

    schema = {
        'title': {
            'attribute': 'title'
        },
        'isbn': {
            'attribute': 'isbn'
        },
        'favorites': {
            'attribute': 'favorites'
        },
        'secret_field': {
            'attribute': 'secret_field',
            'readable': False
        }
    }

    def is_authenticated(self, request):
        if request.method in self.SAFE_METHODS:
            return True
        return request.user.is_authenticated()

    def can_create(self, request):  # Override this method
        return request.user.is_staff

    def can_delete(self, obj, request):
        return False

    def can_update(self, obj, request):  # Override this method
        return request.user.is_staff

我们去吧!现在只有工作人员可以创建和更新图书资源!

我们现在有一个相当健壮的 RESTful 资源。我们的资源允许我们创建、更新、列出和获取Book对象。我们还确保非员工用户只能从列表或详细信息端点获取资源。

过滤

我们希望用户能够过滤Book对象。我们将允许他们根据收藏夹字段过滤结果:

# In ~/yourapp/api.py
from restup import ModelResource
from .models import Book


class BookResource(ModelResource):

    model = Book

    schema = {
        'title': {
            'attribute': 'title'
        },
        'isbn': {
            'attribute': 'isbn'
        },
        'favorites': {
            'attribute': 'favorites',
            'filters': (  # Add this key
                'gt', 'lt',
            )
        },
        'secret_field': {
            'attribute': 'secret_field',
            'readable': False
        }
    }

    def is_authenticated(self, request):
        if request.method in self.SAFE_METHODS:
            return True
        return request.user.is_authenticated()

    def can_create(self, request):
        return request.user.is_staff

    def can_delete(self, obj, request):
        return False

    def can_update(self, obj, request):
        return request.user.is_staff

伟大的!现在,如果我们的用户想要获得超过 10 个收藏夹的书籍列表,他们只需向http://mysite.com/api/books/?favorites__gt=10发送请求。您可以使用Django 文档中定义的任何标准 Django 查询过滤器

验证

我们希望确保客户端只向我们的收藏夹字段提供一个正整数。我们将创建 2 个验证器函数来确保值正确:

# In ~/yourapp/api.py
from restup import ModelResource
from .models import Book

# We will add two methods for illustrative purposes, but this check could
# easily be done with a single function.

def is_integer(value):  # Add this method
    return type(value) == int

def is_positive(value):  # Add this method
    return value > 0


class BookResource(ModelResource):

    model = Book

    schema = {
        'title': {
            'attribute': 'title'
        },
        'isbn': {
            'attribute': 'isbn'
        },
        'favorites': {
            'attribute': 'favorites',
            'filters': (
                'gt', 'lt',
            ),
            'validators': (  # Add this key
                is_integer,
                is_positive
            )
        },
        'secret_field': {
            'attribute': 'secret_field',
            'readable': False
        }
    }

    def is_authenticated(self, request):
        if request.method in self.SAFE_METHODS:
            return True
        return request.user.is_authenticated()

    def can_create(self, request):
        return request.user.is_staff

    def can_delete(self, obj, request):
        return False

    def can_update(self, obj, request):
        return request.user.is_staff

验证器函数应采用单个参数。这个参数应该是接收到的数据中key的。如果值有效,该函数应返回 True ,否则返回False。像我们示例中的检查并不是绝对必要的,因为如果我们试图保存任何不是正整数的东西,Django 的模型后端会抛出异常。但是,这将返回500 服务器错误响应。这对客户不是很有帮助。最好返回400 Bad Request 响应,让客户知道他们输入了错误的内容。

结论

嗯,这是它如何工作的基本概要。如果您想更深入地了解,请查看源代码。ModelResource类是一个很好的 起点。

文档

随着项目的发展,我计划添加更完整的文档,包括:

  • 深入的教程

  • 完整的 API 参考

  • 深入解读数据流

即将进行的必要开发

  • 测试!

  • 对边缘情况的稳健处理。

即将推出的功能

案卷上的一些功能列表:

  • 支持自定义每个字段的前处理和后处理功能。这些将采用数据库或客户端POST ed 数据返回的值,并执行任何必要的复杂转换。

  • 支持自定义的每字段授权功能,以实现极其精细的权限控制。

  • 类似于 Django REST Framework 的自记录模式端点。

  • 返回 JSON 数据中的资源 URI。

  • 自定义 URL 命名空间。

我不会添加的功能

  • XML/YAML/等支持。我不经常使用它们,它们也不容易序列化。如果其他人想要添加支持,欢迎他们创建拉取请求。

  • Python 2 支持。抱歉,是时候继续前进了。

  • Django < 1.8 支持。看上面。

贡献

该项目处于非常早期的开发阶段。在达到V1.0.0之前,它只能用于非生产项目。

欢迎任何批评或想法。只是打开一个问题。

如果您想为源代码做出贡献,最好在提交拉取请求以讨论您想要进行的更改或增强之前打开一个问题。我不会以任何理由歧视任何人。

下载文件

下载适用于您平台的文件。如果您不确定要选择哪个,请了解有关安装包的更多信息。

源分布

django-restup-0.1.1.tar.gz (14.1 kB 查看哈希)

已上传 source

内置分布

django_restup-0.1.1-py3-none-any.whl (17.5 kB 查看哈希

已上传 py3