Muestra las diferencias entre dos versiones de la página.
| Ambos lados, revisión anterior Revisión previa Próxima revisión | Revisión previa | ||
|
fw:djangorest [2014/06/02 11:03] alfred [Authentication modes] |
fw:djangorest [2020/05/09 09:25] (actual) |
||
|---|---|---|---|
| Línea 230: | Línea 230: | ||
| Or include read only fields with ''read_only_fields'' field, or write only fields with ''write_only_fields'' field. Even you can add more fields to your serializer class than those that have the model class. | Or include read only fields with ''read_only_fields'' field, or write only fields with ''write_only_fields'' field. Even you can add more fields to your serializer class than those that have the model class. | ||
| - | ===== Parsers ===== | ||
| - | Parsers are classes to convert from a datatype to another. We can set default parsers for all our API REST or any of the views. There are some default parsers: | ||
| - | * ''JSONParser'' | ||
| - | * ''YAMLParser'' | ||
| - | * ''XMLParser'' | ||
| - | * ''FormParser'' | ||
| - | * ''MultiPartParser'' | ||
| - | * ''FileUploadParser'' | ||
| - | |||
| - | You can code your own parse inheriting from ''BaseParser''. There also are other third party packages with their own parsers ''MessagePack'', ''CamelCaseJSON''... | ||
| + | ==== Notes ==== | ||
| + | * Here you can find which fields you could use or how to create your own field type: [[http://www.django-rest-framework.org/api-guide/fields]] | ||
| + | * If you work with relational data bases, here you'll find how to serialize relations: [[http://www.django-rest-framework.org/api-guide/relations]] | ||
| ===== Views ===== | ===== Views ===== | ||
| ==== Class Based Views ==== | ==== Class Based Views ==== | ||
| Línea 389: | Línea 382: | ||
| They are in the package ''rest_framework.generics''. | They are in the package ''rest_framework.generics''. | ||
| + | |||
| + | ===== How to... ===== | ||
| + | ==== Request objects are formed? ==== | ||
| + | * ''request.DATA'' returns the parsed content of the request body. | ||
| + | * ''request.FILES'' returns any uploaded files that may be present in the content of the request body. | ||
| + | * ''request.QUERY_PARAMS'' is a more correctly named synonym for request.GET. | ||
| + | * ''request.user'' typically returns an instance of ''django.contrib.auth.models.User''. | ||
| + | * ''request.auth'' returns any additional authentication context. | ||
| + | * ''request.method'' returns the uppercased string representation of the request's HTTP method. | ||
| + | * ''request.content_type'', returns a string object representing the media type of the HTTP request's body, or an empty string if no media type was provided. | ||
| + | * ''request.stream'' returns a stream representing the content of the request body. | ||
| + | |||
| + | ==== Response objects are created? ==== | ||
| + | The renderers used by the Response class cannot natively handle complex datatypes such as Django model instances, so you need to serialize the data into primitive datatypes before creating the Response object. | ||
| + | * ''data'': The serialized data for the response. | ||
| + | * ''status'': A status code for the response. Defaults to 200. See also status codes. | ||
| + | * ''template_name'': A template name to use if HTMLRenderer is selected. | ||
| + | * ''headers'': A dictionary of HTTP headers to use in the response. | ||
| + | * ''content_type'': The content type of the response. Typically, this will be set automatically by the renderer as determined by content negotiation, but there may be some cases where you need to specify the content type explicitly. | ||
| + | ==== Parsers work? ==== | ||
| + | Parsers are classes to convert from a datatype to another. We can set default parsers for all our API REST or any of the views. There are some default parsers: | ||
| + | * ''JSONParser'' | ||
| + | * ''YAMLParser'' | ||
| + | * ''XMLParser'' | ||
| + | * ''FormParser'' | ||
| + | * ''MultiPartParser'' | ||
| + | * ''FileUploadParser'' | ||
| + | |||
| + | You can code your own parse inheriting from ''BaseParser''. There also are other third party packages with their own parsers ''MessagePack'', ''CamelCaseJSON''... | ||
| + | |||
| + | ==== Filtering works? ==== | ||
| + | To restrict the returned queryset you can filter... | ||
| + | === Against the current user === | ||
| + | <code python> | ||
| + | class PurchaseList(generics.ListAPIView) | ||
| + | serializer_class = PurchaseSerializer | ||
| + | def get_queryset(self): | ||
| + | user = self.request.user | ||
| + | return Purchase.objects.filter(purchaser=user) | ||
| + | </code> | ||
| + | |||
| + | === Against the url === | ||
| + | <code python> | ||
| + | url('^purchases/(?P<username>.+)/$', PurchaseList.as_view()), | ||
| + | ... | ||
| + | class PurchaseList(generics.ListAPIView) | ||
| + | serializer_class = PurchaseSerializer | ||
| + | def get_queryset(self): | ||
| + | username = self.kwargs['username'] | ||
| + | return Purchase.objects.filter(purchaser__username=username) | ||
| + | </code> | ||
| + | |||
| + | === Against query parameters === | ||
| + | <code python> | ||
| + | class PurchaseList(generics.ListAPIView) | ||
| + | serializer_class = PurchaseSerializer | ||
| + | def get_queryset(self): | ||
| + | queryset = Purchase.objects.all() | ||
| + | username = self.request.QUERY_PARAMS.get('username', None) | ||
| + | if username is not None: | ||
| + | queryset = queryset.filter(purchaser__username=username) | ||
| + | return queryset | ||
| + | </code> | ||
| + | |||
| + | === Others === | ||
| + | * [[http://www.django-rest-framework.org/api-guide/filtering]] | ||
| + | Django REST Framework provides several ways to return a queryset only defining order or fields. Also you can define your own filter classes. | ||
| + | |||
| + | ==== Pagination works? ==== | ||
| + | |||
| + | ==== Others ==== | ||
| + | === Format suffixes === | ||
| + | It's how to return the Response with a concrete format indicated by the url: [[http://www.django-rest-framework.org/api-guide/format-suffixes]]. | ||
| + | === Return URLs === | ||
| + | * [[http://www.django-rest-framework.org/api-guide/reverse]] | ||
| + | When returning URLs to other resources it's better to return the absolute url rather than the relative. Even if it was an identifier; if the string represents a resource, in REST it must be the resource absolute path. To do so in Django REST Framework you could use ''reverse'' and ''reverse_lazy'' functions. | ||
| + | |||
| + | === Configure === | ||
| + | * [[http://www.django-rest-framework.org/api-guide/settings]] | ||
| + | You can configure features like default classes (renderers, parsers, authentications...), generic view settings (pagination, ordering...), el formato de las fechas... | ||
| ===== Authentication and permissions ===== | ===== Authentication and permissions ===== | ||
| ==== Authentication ==== | ==== Authentication ==== | ||
| Línea 451: | Línea 524: | ||
| Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b | Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b | ||
| </code> | </code> | ||
| - | The curl command line tool may be useful for testing token authenticated APIs. For example: | + | The curl command for obtain the token: |
| + | <code> | ||
| + | curl -X POST http://127.0.0.1:8000/api-token-auth/ -H "Content-type: application/json" -d '{"username": "alfred", "password": "test"}' | ||
| + | </code> | ||
| + | |||
| + | The curl command for testing token authenticated APIs. For example: | ||
| <code> | <code> | ||
| curl -X GET http://127.0.0.1:8000/api/example/ -H 'Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b' | curl -X GET http://127.0.0.1:8000/api/example/ -H 'Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b' | ||
| Línea 498: | Línea 576: | ||
| return (user, None) | return (user, None) | ||
| </code> | </code> | ||
| - | |||
| ==== Permissions ==== | ==== Permissions ==== | ||
| Permissions are defined as a list of permission classes. When a view is called a permission list classes is checked, if any of them fails an ''exceptions.PermissionDenied'' exception will be raised. \\ | Permissions are defined as a list of permission classes. When a view is called a permission list classes is checked, if any of them fails an ''exceptions.PermissionDenied'' exception will be raised. \\ | ||
| Línea 545: | Línea 622: | ||
| } | } | ||
| return Response(content) | return Response(content) | ||
| + | </code> | ||
| + | |||
| + | === Permission classes === | ||
| + | * ''AllowAny'', will allow unrestricted access, regardless of if the request was authenticated or unauthenticated. | ||
| + | * ''IsAuthenticated'', will deny permission to any unauthenticated user, and allow permission otherwise. | ||
| + | * ''IsAdminUser'', will deny permission to any user, unless ''user.is_staff'' is True. | ||
| + | * There are more in: [[http://www.django-rest-framework.org/api-guide/permissions#api-reference]] | ||
| + | |||
| + | To implement a custom permission class, override ''BasePermission'' and implement either, or both, of the methods: ''.has_permission(self, request, view)'', ''.has_object_permission(self, request, view, obj)''. The methods should return True if the request should be granted access, and False otherwise. | ||
| + | |||
| + | ==== Throttling ==== | ||
| + | They also authorises requests. However they indicate a temporary state, and are used to control the rate of requests that clients can make. Before running the main body of the view each throttle in the list is checked. If any throttle check fails an exceptions.Throttled exception will be raised. \\ | ||
| + | The default throttling policy may be set globally, using the ''DEFAULT_THROTTLE_CLASSES'' and ''DEFAULT_THROTTLE_RATES'' settings: | ||
| + | <code python> | ||
| + | REST_FRAMEWORK = { | ||
| + | 'DEFAULT_THROTTLE_CLASSES': ( | ||
| + | 'rest_framework.throttling.AnonRateThrottle', | ||
| + | 'rest_framework.throttling.UserRateThrottle' | ||
| + | ), | ||
| + | 'DEFAULT_THROTTLE_RATES': { | ||
| + | 'anon': '100/day', | ||
| + | 'user': '1000/day' | ||
| + | } | ||
| + | } | ||
| + | </code> | ||
| + | The rate descriptions used in ''DEFAULT_THROTTLE_RATES'' may include second, minute, hour or day as the throttle period. \\ | ||
| + | |||
| + | You can also set the throttling policy on a per-view or per-viewset basis, using the APIView class based views. | ||
| + | <code python> | ||
| + | class ExampleView(APIView): | ||
| + | throttle_classes = (UserRateThrottle,) | ||
| + | def get(self, request, format=None): | ||
| + | content = { | ||
| + | 'status': 'request was permitted' | ||
| + | } | ||
| + | return Response(content) | ||
| + | | ||
| + | @api_view('GET') | ||
| + | @throttle_classes([UserRateThrottle]) | ||
| + | def example_view(request, format=None): | ||
| + | content = { | ||
| + | 'status': 'request was permitted' | ||
| + | } | ||
| + | return Response(content) | ||
| + | </code> | ||
| + | === Some throttles === | ||
| + | * ''AnonRateThrottle'' | ||
| + | * ''UserRateThrottle'' | ||
| + | * ''ScopedRateThrottle'' | ||
| + | |||
| + | === Custom throttles === | ||
| + | To create a custom throttle, override BaseThrottle and implement ''.allow_request(self, request, view)''. The method should return ''True'' if the request should be allowed, and ''False'' otherwise. \\ | ||
| + | |||
| + | Optionally you may also override the .wait() method. If implemented, ''.wait()'' should return a recommended number of seconds to wait before attempting the next request, or ''None''. The ''.wait()'' method will only be called if ''.allow_request()'' has previously returned ''False''. \\ | ||
| + | |||
| + | The following is an example of a rate throttle, that will randomly throttle 1 in every 10 requests. | ||
| + | <code python> | ||
| + | class RandomRateThrottle(throttles.BaseThrottle): | ||
| + | def allow_request(self, request, view): | ||
| + | return random.randint(1, 10) == 1 | ||
| </code> | </code> | ||
| ===== Testing ===== | ===== Testing ===== | ||