Ralph API resources¶
How to create new API resource based on Django model¶
# model
from django.db import models
class Foo(model.Model):
bar = models.CharField(max_length=10)
# API
from ralph.api import RalphAPISerializer, RalphAPIViewSet, router
class FooSerializer(RalphAPISerializer):
class Meta:
model = Foo
class FooViewSet(RalphAPIViewSet):
queryset = Foo.objects.all()
serializer_class = FooSerializer
# use Ralph router instance to register new viewset
router.register(r'foos', FooViewSet)
What are built-in features of Ralph API classes?¶
RalphAPISerializer
¶
- include both object PK and its url (see
ralph.api.serializers.RalphAPISerializer.get_default_field_names
for details). - every sub-serializer (even instantiated directly as a field in other serializer) have current context set.
- use
ralph.api.serializers.ReversedChoiceField
for all choice fields - this serializer allow to pass value by name instead of key. Additionally it present value in user-friendly format by-name. This field works perfectly withdj.choices.Choices
. - include permissions per field checking using
ralph.lib.permissions.api.PermissionsPerFieldSerializerMixin
- only fields to which user has access will be returned. This field also handle view-only permission as read-only field. - include permission validation on object level for related fields - if related field model use permissions for object, then only objects to which user has access could be selected/displayed in related field.
- validate data using model's clean validation (set
_validate_using_model_clean
toFalse
in your save seriazlier to turn this off)
RalphAPIViewSet
¶
- default serializer for save actions (POST, PUT, PATCH) in which every relation will be serialized using
rest_framework.serializers.PrimaryKeyRelatedField
(so user should specify object PK in relation field). This serializer could be overwritten usingsave_serializer_class
attribute inRalphAPIViewSet
. - include
ralph.api.utils.QuerysetRelatedMixin
which can easily handle select_related and prefetch_related on queryset. By default select_related is fill with related admin site list_select_related value. - include
ralph.api.viewsets.AdminSearchFieldsMixin
thanks to which search fields will be by default taken from related admin site. - include
ralph.api.permissions.RalphPermission
, which check if user is properly authenticated (throughIsAuthenticated
), user has access to object (throughObjectPermissionsMixin
) and user has proper Django admin permissions (add_*
,change_*
,delete_*
) requested model.
Filter backends¶
By default RalphAPIViewSet
use the following filter backends:
* rest_framework.filters.DjangoFilterBackend
- provides basic filtering for Django model - in RalphAPIViewSet
(through AdminSearchFieldsMixin
) filter fields are associated with model's admin.
* ralph.lib.permissions.api.PermissionsForObjectFilter
- limit result only to object for which user has permission at least to view.
* rest_framework.filters.OrderingFilter
- order queryset using order
url param.
* ralph.api.filters.ExtendedFiltersBackend
- allows to filter for multiple fields using single query param - it's usefull especially for polymorphic models. To use extended filters define extended_filter_fields
in your view, ex. extended_filter_fields = {'name': ['asset__hostname', ip__address', 'cloudhost__hostname']
- this filter will allow you to search using name
query param and it will be resolved to compound search (using OR operator) for fields asset__hostname
, ip__address
or cloudhost__hostname
(ex. <URL>?name=abc
will result in search Q(asset__hostname=abc) | Q(ip__address=abc) | Q(cloudhost__hostname=abc)
).
* ralph.api.filters.LookupFilterBackend
- filter by lookups (using Django's __
convention) in query params, ex. <URL>?barcode__startswit=123
or <URL>?invoice_date__lte=2015-01-01
.
* ralph.api.filters.TagsFilterBackend
- Filter queryset by tags. Multiple tags could be specified in url query: <URL>?tag=abc&tag=def&tag=123
.
Note that polymorphic models (api resources) by default support lookup filters and extended filters, so you could call compound query on your polymorphic-root model, ex.
<URL>/base-objects/?name__startswith=abc
, which will be resolved to query, checking if one of fields defined inextended_filter_fields
(in above exampleasset__hostname
,ip__address
orcloudhost__hostname
) startswithabc
.