mirror of
				https://github.com/encode/django-rest-framework.git
				synced 2025-11-04 09:57:55 +03:00 
			
		
		
		
	Merge pull request #2373 from jakul/document-translations-3.1
Document how to translate DRF error messages (version 3.1)
This commit is contained in:
		
						commit
						11efde8905
					
				
							
								
								
									
										9
									
								
								.tx/config
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								.tx/config
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,9 @@
 | 
				
			||||||
 | 
					[main]
 | 
				
			||||||
 | 
					host = https://www.transifex.com
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[django-rest-framework.djangopo]
 | 
				
			||||||
 | 
					file_filter = rest_framework/locale/<lang>/LC_MESSAGES/django.po
 | 
				
			||||||
 | 
					source_file = rest_framework/locale/en_US/LC_MESSAGES/django.po
 | 
				
			||||||
 | 
					source_lang = en_US
 | 
				
			||||||
 | 
					type = PO
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -177,6 +177,57 @@ We recommend the [`django-reusable-app`][django-reusable-app] template as a good
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Once your package is decently documented and available on PyPI open a pull request or issue, and we'll add a link to it from the main REST framework documentation.
 | 
					Once your package is decently documented and available on PyPI open a pull request or issue, and we'll add a link to it from the main REST framework documentation.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Translations
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If REST framework isn't translated into your language you can request that it is at the [Transifex project][transifex].
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Managing Transfiex
 | 
				
			||||||
 | 
					The [official Transifex client][transifex-client] is used to upload and download translations to Transifex. The client is installed using pip:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					pip install transifex-client
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					To use it you'll need a login to Transifex which has a password, and you'll need to have administrative access to the Transifex project. You'll need to create a `~/.transifexrc` file which contains your authentication information:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					[https://www.transifex.com]
 | 
				
			||||||
 | 
					username = user
 | 
				
			||||||
 | 
					token =
 | 
				
			||||||
 | 
					password = p@ssw0rd
 | 
				
			||||||
 | 
					hostname = https://www.transifex.com
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Upload new source translations
 | 
				
			||||||
 | 
					When any user-visible strings are changed, they should be uploaded to Transifex so that the translators can start to translate them. To do this, just run:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					cd rest_framework
 | 
				
			||||||
 | 
					django-admin.py makemessages -l en_US
 | 
				
			||||||
 | 
					cd ..
 | 
				
			||||||
 | 
					tx push -s
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					When pushing source files, Transifex will update the source strings of a resource to match those from the new source file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Here's how differences between the old and new source files will be handled:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* New strings will be added.
 | 
				
			||||||
 | 
					* Modified strings will be added as well.
 | 
				
			||||||
 | 
					* Strings which do not exist in the new source file will be removed from the database, along with their translations. If that source strings gets re-added later then [Transifex Translation Memory][translation-memory] will automatically restore the translated string too. 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Get translations
 | 
				
			||||||
 | 
					When a translator has finished translating their work needs to be downloaded from Transifex into the source repo. To do this, run:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					tx pull -a
 | 
				
			||||||
 | 
					cd rest_framework
 | 
				
			||||||
 | 
					django-admin.py compilemessages
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					You can then commit as normal.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[cite]: http://www.w3.org/People/Berners-Lee/FAQ.html
 | 
					[cite]: http://www.w3.org/People/Berners-Lee/FAQ.html
 | 
				
			||||||
[code-of-conduct]: https://www.djangoproject.com/conduct/
 | 
					[code-of-conduct]: https://www.djangoproject.com/conduct/
 | 
				
			||||||
[google-group]: https://groups.google.com/forum/?fromgroups#!forum/django-rest-framework
 | 
					[google-group]: https://groups.google.com/forum/?fromgroups#!forum/django-rest-framework
 | 
				
			||||||
| 
						 | 
					@ -190,3 +241,6 @@ Once your package is decently documented and available on PyPI open a pull reque
 | 
				
			||||||
[docs]: https://github.com/tomchristie/django-rest-framework/tree/master/docs
 | 
					[docs]: https://github.com/tomchristie/django-rest-framework/tree/master/docs
 | 
				
			||||||
[mou]: http://mouapp.com/
 | 
					[mou]: http://mouapp.com/
 | 
				
			||||||
[django-reusable-app]: https://github.com/dabapps/django-reusable-app
 | 
					[django-reusable-app]: https://github.com/dabapps/django-reusable-app
 | 
				
			||||||
 | 
					[transifex]: https://www.transifex.com/projects/p/django-rest-framework/
 | 
				
			||||||
 | 
					[transifex-client]: https://pypi.python.org/pypi/transifex-client
 | 
				
			||||||
 | 
					[translation-memory]: http://docs.transifex.com/guides/tm#let-tm-automatically-populate-translations
 | 
				
			||||||
							
								
								
									
										95
									
								
								docs/topics/internationalisation.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										95
									
								
								docs/topics/internationalisation.md
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,95 @@
 | 
				
			||||||
 | 
					# Internationalisation
 | 
				
			||||||
 | 
					REST framework ships with translatable error messages.  You can make these appear in your language enabling [Django's standard translation mechanisms][django-translation] and by translating the messages into your language.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## How to translate REST Framework errors
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					REST framework translations are managed online using [Transifex.com][transifex]. To get started, checkout the guide in the [CONTRIBUTING.md guide][contributing].
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Sometimes you may want to use REST Framework in a language which has not been translated yet on Transifex. If that is the case then you should translate the error messages locally.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### How to translate REST Framework error messages locally:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This guide assumes you are already familiar with how to translate a Django app.  If you're not, start by reading [Django's translation docs][django-translation].
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					1. Make a new folder where you want to store the translated errors. Add this 
 | 
				
			||||||
 | 
					path to your [`LOCALE_PATHS`][django-locale-paths] setting. 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  **Note:** For the rest of 
 | 
				
			||||||
 | 
					this document we will assume the path you created was 
 | 
				
			||||||
 | 
					`/home/www/project/conf/locale/`, and that you have updated your `settings.py` to include the setting:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ```
 | 
				
			||||||
 | 
					  LOCALE_PATHS = (
 | 
				
			||||||
 | 
					      '/home/www/project/conf/locale/',
 | 
				
			||||||
 | 
					  )
 | 
				
			||||||
 | 
					  ```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					2. Now create a subfolder for the language you want to translate. The folder should be named using [locale 
 | 
				
			||||||
 | 
					name][django-locale-name] notation.  E.g. `de`, `pt_BR`, `es_AR`, etc.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ```
 | 
				
			||||||
 | 
					  mkdir /home/www/project/conf/locale/pt_BR/LC_MESSAGES
 | 
				
			||||||
 | 
					  ```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					3. Now copy the base translations file from the REST framework source code 
 | 
				
			||||||
 | 
					into your translations folder
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ```
 | 
				
			||||||
 | 
					  cp /home/user/.virtualenvs/myproject/lib/python2.7/site-packages/rest_framework/locale/en_US/LC_MESSAGES/django.po
 | 
				
			||||||
 | 
					  /home/www/project/conf/locale/pt_BR/LC_MESSAGES
 | 
				
			||||||
 | 
					  ```
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  This should create the file 
 | 
				
			||||||
 | 
					  `/home/www/project/conf/locale/pt_BR/LC_MESSAGES/django.po`
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  ---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  **Note:** To find out where `rest_framework` is installed, run 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ```
 | 
				
			||||||
 | 
					  python -c "from distutils.sysconfig import get_python_lib; print(get_python_lib())"
 | 
				
			||||||
 | 
					  ```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ---
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					4. Edit `/home/www/project/conf/locale/pt_BR/LC_MESSAGES/django.po` and 
 | 
				
			||||||
 | 
					translate all the error messages.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					5. Run `manage.py compilemessages -l pt_BR` to make the translations 
 | 
				
			||||||
 | 
					available for Django to use. You should see a message
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ```
 | 
				
			||||||
 | 
					    processing file django.po in /home/www/project/conf/locale/pt_BR/LC_MESSAGES
 | 
				
			||||||
 | 
					    ```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					6. Restart your server.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## How Django chooses which language to use
 | 
				
			||||||
 | 
					REST framework will use the same preferences to select which language to 
 | 
				
			||||||
 | 
					display as Django does.  You can find more info in the [Django docs on discovering language preferences][django-language-preference].  For reference, these are
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					1. First, it looks for the language prefix in the requested URL
 | 
				
			||||||
 | 
					2. Failing that, it looks for the `LANGUAGE_SESSION_KEY` key in the current user’s session.
 | 
				
			||||||
 | 
					3. Failing that, it looks for a cookie
 | 
				
			||||||
 | 
					4. Failing that, it looks at the `Accept-Language` HTTP header.
 | 
				
			||||||
 | 
					5. Failing that, it uses the global `LANGUAGE_CODE` setting.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					**Note:** You'll need to include the `django.middleware.locale.LocaleMiddleware` to enable any of the per-request language preferences.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[django-translation]: https://docs.djangoproject.com/en/1.7/topics/i18n/translation
 | 
				
			||||||
 | 
					[django-language-preference]: https://docs.djangoproject.com/en/1.7/topics/i18n/translation/#how-django-discovers-language-preference
 | 
				
			||||||
 | 
					[django-locale-paths]: https://docs.djangoproject.com/en/1.7/ref/settings/#std:setting-LOCALE_PATHS
 | 
				
			||||||
 | 
					[django-locale-name]: https://docs.djangoproject.com/en/1.7/topics/i18n/#term-locale-name
 | 
				
			||||||
 | 
					[contributing]: ../../CONTRIBUTING.md
 | 
				
			||||||
| 
						 | 
					@ -5,6 +5,7 @@ from __future__ import unicode_literals
 | 
				
			||||||
import base64
 | 
					import base64
 | 
				
			||||||
from django.contrib.auth import authenticate
 | 
					from django.contrib.auth import authenticate
 | 
				
			||||||
from django.middleware.csrf import CsrfViewMiddleware
 | 
					from django.middleware.csrf import CsrfViewMiddleware
 | 
				
			||||||
 | 
					from django.utils.translation import ugettext_lazy as _
 | 
				
			||||||
from rest_framework import exceptions, HTTP_HEADER_ENCODING
 | 
					from rest_framework import exceptions, HTTP_HEADER_ENCODING
 | 
				
			||||||
from rest_framework.authtoken.models import Token
 | 
					from rest_framework.authtoken.models import Token
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -65,16 +66,16 @@ class BasicAuthentication(BaseAuthentication):
 | 
				
			||||||
            return None
 | 
					            return None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if len(auth) == 1:
 | 
					        if len(auth) == 1:
 | 
				
			||||||
            msg = 'Invalid basic header. No credentials provided.'
 | 
					            msg = _('Invalid basic header. No credentials provided.')
 | 
				
			||||||
            raise exceptions.AuthenticationFailed(msg)
 | 
					            raise exceptions.AuthenticationFailed(msg)
 | 
				
			||||||
        elif len(auth) > 2:
 | 
					        elif len(auth) > 2:
 | 
				
			||||||
            msg = 'Invalid basic header. Credentials string should not contain spaces.'
 | 
					            msg = _('Invalid basic header. Credentials string should not contain spaces.')
 | 
				
			||||||
            raise exceptions.AuthenticationFailed(msg)
 | 
					            raise exceptions.AuthenticationFailed(msg)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            auth_parts = base64.b64decode(auth[1]).decode(HTTP_HEADER_ENCODING).partition(':')
 | 
					            auth_parts = base64.b64decode(auth[1]).decode(HTTP_HEADER_ENCODING).partition(':')
 | 
				
			||||||
        except (TypeError, UnicodeDecodeError):
 | 
					        except (TypeError, UnicodeDecodeError):
 | 
				
			||||||
            msg = 'Invalid basic header. Credentials not correctly base64 encoded'
 | 
					            msg = _('Invalid basic header. Credentials not correctly base64 encoded.')
 | 
				
			||||||
            raise exceptions.AuthenticationFailed(msg)
 | 
					            raise exceptions.AuthenticationFailed(msg)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        userid, password = auth_parts[0], auth_parts[2]
 | 
					        userid, password = auth_parts[0], auth_parts[2]
 | 
				
			||||||
| 
						 | 
					@ -86,7 +87,7 @@ class BasicAuthentication(BaseAuthentication):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        user = authenticate(username=userid, password=password)
 | 
					        user = authenticate(username=userid, password=password)
 | 
				
			||||||
        if user is None or not user.is_active:
 | 
					        if user is None or not user.is_active:
 | 
				
			||||||
            raise exceptions.AuthenticationFailed('Invalid username/password')
 | 
					            raise exceptions.AuthenticationFailed(_('Invalid username/password.'))
 | 
				
			||||||
        return (user, None)
 | 
					        return (user, None)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def authenticate_header(self, request):
 | 
					    def authenticate_header(self, request):
 | 
				
			||||||
| 
						 | 
					@ -152,10 +153,10 @@ class TokenAuthentication(BaseAuthentication):
 | 
				
			||||||
            return None
 | 
					            return None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if len(auth) == 1:
 | 
					        if len(auth) == 1:
 | 
				
			||||||
            msg = 'Invalid token header. No credentials provided.'
 | 
					            msg = _('Invalid token header. No credentials provided.')
 | 
				
			||||||
            raise exceptions.AuthenticationFailed(msg)
 | 
					            raise exceptions.AuthenticationFailed(msg)
 | 
				
			||||||
        elif len(auth) > 2:
 | 
					        elif len(auth) > 2:
 | 
				
			||||||
            msg = 'Invalid token header. Token string should not contain spaces.'
 | 
					            msg = _('Invalid token header. Token string should not contain spaces.')
 | 
				
			||||||
            raise exceptions.AuthenticationFailed(msg)
 | 
					            raise exceptions.AuthenticationFailed(msg)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return self.authenticate_credentials(auth[1])
 | 
					        return self.authenticate_credentials(auth[1])
 | 
				
			||||||
| 
						 | 
					@ -164,10 +165,10 @@ class TokenAuthentication(BaseAuthentication):
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            token = self.model.objects.get(key=key)
 | 
					            token = self.model.objects.get(key=key)
 | 
				
			||||||
        except self.model.DoesNotExist:
 | 
					        except self.model.DoesNotExist:
 | 
				
			||||||
            raise exceptions.AuthenticationFailed('Invalid token')
 | 
					            raise exceptions.AuthenticationFailed(_('Invalid token.'))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if not token.user.is_active:
 | 
					        if not token.user.is_active:
 | 
				
			||||||
            raise exceptions.AuthenticationFailed('User inactive or deleted')
 | 
					            raise exceptions.AuthenticationFailed(_('User inactive or deleted.'))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return (token.user, token)
 | 
					        return (token.user, token)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -23,7 +23,7 @@ class AuthTokenSerializer(serializers.Serializer):
 | 
				
			||||||
                msg = _('Unable to log in with provided credentials.')
 | 
					                msg = _('Unable to log in with provided credentials.')
 | 
				
			||||||
                raise exceptions.ValidationError(msg)
 | 
					                raise exceptions.ValidationError(msg)
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            msg = _('Must include "username" and "password"')
 | 
					            msg = _('Must include "username" and "password".')
 | 
				
			||||||
            raise exceptions.ValidationError(msg)
 | 
					            raise exceptions.ValidationError(msg)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        attrs['user'] = user
 | 
					        attrs['user'] = user
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,8 +7,7 @@ In addition Django's built in 403 and 404 exceptions are handled.
 | 
				
			||||||
from __future__ import unicode_literals
 | 
					from __future__ import unicode_literals
 | 
				
			||||||
from django.utils import six
 | 
					from django.utils import six
 | 
				
			||||||
from django.utils.encoding import force_text
 | 
					from django.utils.encoding import force_text
 | 
				
			||||||
from django.utils.translation import ugettext_lazy as _
 | 
					from django.utils.translation import ugettext_lazy as _, ungettext
 | 
				
			||||||
from django.utils.translation import ungettext_lazy
 | 
					 | 
				
			||||||
from rest_framework import status
 | 
					from rest_framework import status
 | 
				
			||||||
import math
 | 
					import math
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -36,7 +35,7 @@ class APIException(Exception):
 | 
				
			||||||
    Subclasses should provide `.status_code` and `.default_detail` properties.
 | 
					    Subclasses should provide `.status_code` and `.default_detail` properties.
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    status_code = status.HTTP_500_INTERNAL_SERVER_ERROR
 | 
					    status_code = status.HTTP_500_INTERNAL_SERVER_ERROR
 | 
				
			||||||
    default_detail = _('A server error occured')
 | 
					    default_detail = _('A server error occurred.')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self, detail=None):
 | 
					    def __init__(self, detail=None):
 | 
				
			||||||
        if detail is not None:
 | 
					        if detail is not None:
 | 
				
			||||||
| 
						 | 
					@ -91,23 +90,23 @@ class PermissionDenied(APIException):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class NotFound(APIException):
 | 
					class NotFound(APIException):
 | 
				
			||||||
    status_code = status.HTTP_404_NOT_FOUND
 | 
					    status_code = status.HTTP_404_NOT_FOUND
 | 
				
			||||||
    default_detail = _('Not found')
 | 
					    default_detail = _('Not found.')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class MethodNotAllowed(APIException):
 | 
					class MethodNotAllowed(APIException):
 | 
				
			||||||
    status_code = status.HTTP_405_METHOD_NOT_ALLOWED
 | 
					    status_code = status.HTTP_405_METHOD_NOT_ALLOWED
 | 
				
			||||||
    default_detail = _("Method '%s' not allowed.")
 | 
					    default_detail = _('Method "{method}" not allowed.')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self, method, detail=None):
 | 
					    def __init__(self, method, detail=None):
 | 
				
			||||||
        if detail is not None:
 | 
					        if detail is not None:
 | 
				
			||||||
            self.detail = force_text(detail)
 | 
					            self.detail = force_text(detail)
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            self.detail = force_text(self.default_detail) % method
 | 
					            self.detail = force_text(self.default_detail).format(method=method)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class NotAcceptable(APIException):
 | 
					class NotAcceptable(APIException):
 | 
				
			||||||
    status_code = status.HTTP_406_NOT_ACCEPTABLE
 | 
					    status_code = status.HTTP_406_NOT_ACCEPTABLE
 | 
				
			||||||
    default_detail = _('Could not satisfy the request Accept header')
 | 
					    default_detail = _('Could not satisfy the request Accept header.')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self, detail=None, available_renderers=None):
 | 
					    def __init__(self, detail=None, available_renderers=None):
 | 
				
			||||||
        if detail is not None:
 | 
					        if detail is not None:
 | 
				
			||||||
| 
						 | 
					@ -119,23 +118,22 @@ class NotAcceptable(APIException):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class UnsupportedMediaType(APIException):
 | 
					class UnsupportedMediaType(APIException):
 | 
				
			||||||
    status_code = status.HTTP_415_UNSUPPORTED_MEDIA_TYPE
 | 
					    status_code = status.HTTP_415_UNSUPPORTED_MEDIA_TYPE
 | 
				
			||||||
    default_detail = _("Unsupported media type '%s' in request.")
 | 
					    default_detail = _('Unsupported media type "{media_type}" in request.')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self, media_type, detail=None):
 | 
					    def __init__(self, media_type, detail=None):
 | 
				
			||||||
        if detail is not None:
 | 
					        if detail is not None:
 | 
				
			||||||
            self.detail = force_text(detail)
 | 
					            self.detail = force_text(detail)
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            self.detail = force_text(self.default_detail) % media_type
 | 
					            self.detail = force_text(self.default_detail).format(
 | 
				
			||||||
 | 
					                media_type=media_type
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Throttled(APIException):
 | 
					class Throttled(APIException):
 | 
				
			||||||
    status_code = status.HTTP_429_TOO_MANY_REQUESTS
 | 
					    status_code = status.HTTP_429_TOO_MANY_REQUESTS
 | 
				
			||||||
    default_detail = _('Request was throttled.')
 | 
					    default_detail = _('Request was throttled.')
 | 
				
			||||||
    extra_detail = ungettext_lazy(
 | 
					    extra_detail_singular = 'Expected available in {wait} second.'
 | 
				
			||||||
        'Expected available in %(wait)d second.',
 | 
					    extra_detail_plural = 'Expected available in {wait} seconds.'
 | 
				
			||||||
        'Expected available in %(wait)d seconds.',
 | 
					 | 
				
			||||||
        'wait'
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self, wait=None, detail=None):
 | 
					    def __init__(self, wait=None, detail=None):
 | 
				
			||||||
        if detail is not None:
 | 
					        if detail is not None:
 | 
				
			||||||
| 
						 | 
					@ -147,6 +145,8 @@ class Throttled(APIException):
 | 
				
			||||||
            self.wait = None
 | 
					            self.wait = None
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            self.wait = math.ceil(wait)
 | 
					            self.wait = math.ceil(wait)
 | 
				
			||||||
            self.detail += ' ' + force_text(
 | 
					            self.detail += ' ' + force_text(ungettext(
 | 
				
			||||||
                self.extra_detail % {'wait': self.wait}
 | 
					                self.extra_detail_singular.format(wait=self.wait),
 | 
				
			||||||
            )
 | 
					                self.extra_detail_plural.format(wait=self.wait),
 | 
				
			||||||
 | 
					                self.wait
 | 
				
			||||||
 | 
					            ))
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -483,7 +483,7 @@ class Field(object):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class BooleanField(Field):
 | 
					class BooleanField(Field):
 | 
				
			||||||
    default_error_messages = {
 | 
					    default_error_messages = {
 | 
				
			||||||
        'invalid': _('`{input}` is not a valid boolean.')
 | 
					        'invalid': _('"{input}" is not a valid boolean.')
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    default_empty_html = False
 | 
					    default_empty_html = False
 | 
				
			||||||
    initial = False
 | 
					    initial = False
 | 
				
			||||||
| 
						 | 
					@ -511,7 +511,7 @@ class BooleanField(Field):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class NullBooleanField(Field):
 | 
					class NullBooleanField(Field):
 | 
				
			||||||
    default_error_messages = {
 | 
					    default_error_messages = {
 | 
				
			||||||
        'invalid': _('`{input}` is not a valid boolean.')
 | 
					        'invalid': _('"{input}" is not a valid boolean.')
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    initial = None
 | 
					    initial = None
 | 
				
			||||||
    TRUE_VALUES = set(('t', 'T', 'true', 'True', 'TRUE', '1', 1, True))
 | 
					    TRUE_VALUES = set(('t', 'T', 'true', 'True', 'TRUE', '1', 1, True))
 | 
				
			||||||
| 
						 | 
					@ -611,7 +611,7 @@ class RegexField(CharField):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class SlugField(CharField):
 | 
					class SlugField(CharField):
 | 
				
			||||||
    default_error_messages = {
 | 
					    default_error_messages = {
 | 
				
			||||||
        'invalid': _("Enter a valid 'slug' consisting of letters, numbers, underscores or hyphens.")
 | 
					        'invalid': _('Enter a valid "slug" consisting of letters, numbers, underscores or hyphens.')
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self, **kwargs):
 | 
					    def __init__(self, **kwargs):
 | 
				
			||||||
| 
						 | 
					@ -623,7 +623,7 @@ class SlugField(CharField):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class URLField(CharField):
 | 
					class URLField(CharField):
 | 
				
			||||||
    default_error_messages = {
 | 
					    default_error_messages = {
 | 
				
			||||||
        'invalid': _("Enter a valid URL.")
 | 
					        'invalid': _('Enter a valid URL.')
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self, **kwargs):
 | 
					    def __init__(self, **kwargs):
 | 
				
			||||||
| 
						 | 
					@ -639,7 +639,7 @@ class IntegerField(Field):
 | 
				
			||||||
        'invalid': _('A valid integer is required.'),
 | 
					        'invalid': _('A valid integer is required.'),
 | 
				
			||||||
        'max_value': _('Ensure this value is less than or equal to {max_value}.'),
 | 
					        'max_value': _('Ensure this value is less than or equal to {max_value}.'),
 | 
				
			||||||
        'min_value': _('Ensure this value is greater than or equal to {min_value}.'),
 | 
					        'min_value': _('Ensure this value is greater than or equal to {min_value}.'),
 | 
				
			||||||
        'max_string_length': _('String value too large')
 | 
					        'max_string_length': _('String value too large.')
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    MAX_STRING_LENGTH = 1000  # Guard against malicious string inputs.
 | 
					    MAX_STRING_LENGTH = 1000  # Guard against malicious string inputs.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -670,10 +670,10 @@ class IntegerField(Field):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class FloatField(Field):
 | 
					class FloatField(Field):
 | 
				
			||||||
    default_error_messages = {
 | 
					    default_error_messages = {
 | 
				
			||||||
        'invalid': _("A valid number is required."),
 | 
					        'invalid': _('A valid number is required.'),
 | 
				
			||||||
        'max_value': _('Ensure this value is less than or equal to {max_value}.'),
 | 
					        'max_value': _('Ensure this value is less than or equal to {max_value}.'),
 | 
				
			||||||
        'min_value': _('Ensure this value is greater than or equal to {min_value}.'),
 | 
					        'min_value': _('Ensure this value is greater than or equal to {min_value}.'),
 | 
				
			||||||
        'max_string_length': _('String value too large')
 | 
					        'max_string_length': _('String value too large.')
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    MAX_STRING_LENGTH = 1000  # Guard against malicious string inputs.
 | 
					    MAX_STRING_LENGTH = 1000  # Guard against malicious string inputs.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -709,7 +709,7 @@ class DecimalField(Field):
 | 
				
			||||||
        'max_digits': _('Ensure that there are no more than {max_digits} digits in total.'),
 | 
					        'max_digits': _('Ensure that there are no more than {max_digits} digits in total.'),
 | 
				
			||||||
        'max_decimal_places': _('Ensure that there are no more than {max_decimal_places} decimal places.'),
 | 
					        'max_decimal_places': _('Ensure that there are no more than {max_decimal_places} decimal places.'),
 | 
				
			||||||
        'max_whole_digits': _('Ensure that there are no more than {max_whole_digits} digits before the decimal point.'),
 | 
					        'max_whole_digits': _('Ensure that there are no more than {max_whole_digits} digits before the decimal point.'),
 | 
				
			||||||
        'max_string_length': _('String value too large')
 | 
					        'max_string_length': _('String value too large.')
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    MAX_STRING_LENGTH = 1000  # Guard against malicious string inputs.
 | 
					    MAX_STRING_LENGTH = 1000  # Guard against malicious string inputs.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -792,7 +792,7 @@ class DecimalField(Field):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class DateTimeField(Field):
 | 
					class DateTimeField(Field):
 | 
				
			||||||
    default_error_messages = {
 | 
					    default_error_messages = {
 | 
				
			||||||
        'invalid': _('Datetime has wrong format. Use one of these formats instead: {format}'),
 | 
					        'invalid': _('Datetime has wrong format. Use one of these formats instead: {format}.'),
 | 
				
			||||||
        'date': _('Expected a datetime but got a date.'),
 | 
					        'date': _('Expected a datetime but got a date.'),
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    format = api_settings.DATETIME_FORMAT
 | 
					    format = api_settings.DATETIME_FORMAT
 | 
				
			||||||
| 
						 | 
					@ -857,7 +857,7 @@ class DateTimeField(Field):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class DateField(Field):
 | 
					class DateField(Field):
 | 
				
			||||||
    default_error_messages = {
 | 
					    default_error_messages = {
 | 
				
			||||||
        'invalid': _('Date has wrong format. Use one of these formats instead: {format}'),
 | 
					        'invalid': _('Date has wrong format. Use one of these formats instead: {format}.'),
 | 
				
			||||||
        'datetime': _('Expected a date but got a datetime.'),
 | 
					        'datetime': _('Expected a date but got a datetime.'),
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    format = api_settings.DATE_FORMAT
 | 
					    format = api_settings.DATE_FORMAT
 | 
				
			||||||
| 
						 | 
					@ -915,7 +915,7 @@ class DateField(Field):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class TimeField(Field):
 | 
					class TimeField(Field):
 | 
				
			||||||
    default_error_messages = {
 | 
					    default_error_messages = {
 | 
				
			||||||
        'invalid': _('Time has wrong format. Use one of these formats instead: {format}'),
 | 
					        'invalid': _('Time has wrong format. Use one of these formats instead: {format}.'),
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    format = api_settings.TIME_FORMAT
 | 
					    format = api_settings.TIME_FORMAT
 | 
				
			||||||
    input_formats = api_settings.TIME_INPUT_FORMATS
 | 
					    input_formats = api_settings.TIME_INPUT_FORMATS
 | 
				
			||||||
| 
						 | 
					@ -971,7 +971,7 @@ class TimeField(Field):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ChoiceField(Field):
 | 
					class ChoiceField(Field):
 | 
				
			||||||
    default_error_messages = {
 | 
					    default_error_messages = {
 | 
				
			||||||
        'invalid_choice': _('`{input}` is not a valid choice.')
 | 
					        'invalid_choice': _('"{input}" is not a valid choice.')
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self, choices, **kwargs):
 | 
					    def __init__(self, choices, **kwargs):
 | 
				
			||||||
| 
						 | 
					@ -1015,8 +1015,8 @@ class ChoiceField(Field):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class MultipleChoiceField(ChoiceField):
 | 
					class MultipleChoiceField(ChoiceField):
 | 
				
			||||||
    default_error_messages = {
 | 
					    default_error_messages = {
 | 
				
			||||||
        'invalid_choice': _('`{input}` is not a valid choice.'),
 | 
					        'invalid_choice': _('"{input}" is not a valid choice.'),
 | 
				
			||||||
        'not_a_list': _('Expected a list of items but got type `{input_type}`.')
 | 
					        'not_a_list': _('Expected a list of items but got type "{input_type}".')
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    default_empty_html = []
 | 
					    default_empty_html = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1046,10 +1046,10 @@ class MultipleChoiceField(ChoiceField):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class FileField(Field):
 | 
					class FileField(Field):
 | 
				
			||||||
    default_error_messages = {
 | 
					    default_error_messages = {
 | 
				
			||||||
        'required': _("No file was submitted."),
 | 
					        'required': _('No file was submitted.'),
 | 
				
			||||||
        'invalid': _("The submitted data was not a file. Check the encoding type on the form."),
 | 
					        'invalid': _('The submitted data was not a file. Check the encoding type on the form.'),
 | 
				
			||||||
        'no_name': _("No filename could be determined."),
 | 
					        'no_name': _('No filename could be determined.'),
 | 
				
			||||||
        'empty': _("The submitted file is empty."),
 | 
					        'empty': _('The submitted file is empty.'),
 | 
				
			||||||
        'max_length': _('Ensure this filename has at most {max_length} characters (it has {length}).'),
 | 
					        'max_length': _('Ensure this filename has at most {max_length} characters (it has {length}).'),
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    use_url = api_settings.UPLOADED_FILES_USE_URL
 | 
					    use_url = api_settings.UPLOADED_FILES_USE_URL
 | 
				
			||||||
| 
						 | 
					@ -1092,8 +1092,7 @@ class FileField(Field):
 | 
				
			||||||
class ImageField(FileField):
 | 
					class ImageField(FileField):
 | 
				
			||||||
    default_error_messages = {
 | 
					    default_error_messages = {
 | 
				
			||||||
        'invalid_image': _(
 | 
					        'invalid_image': _(
 | 
				
			||||||
            'Upload a valid image. The file you uploaded was either not an '
 | 
					            'Upload a valid image. The file you uploaded was either not an image or a corrupted image.'
 | 
				
			||||||
            'image or a corrupted image.'
 | 
					 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1118,7 +1117,7 @@ class ListField(Field):
 | 
				
			||||||
    child = None
 | 
					    child = None
 | 
				
			||||||
    initial = []
 | 
					    initial = []
 | 
				
			||||||
    default_error_messages = {
 | 
					    default_error_messages = {
 | 
				
			||||||
        'not_a_list': _('Expected a list of items but got type `{input_type}`')
 | 
					        'not_a_list': _('Expected a list of items but got type "{input_type}".')
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self, *args, **kwargs):
 | 
					    def __init__(self, *args, **kwargs):
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -119,15 +119,15 @@ class GenericAPIView(views.APIView):
 | 
				
			||||||
            if page == 'last':
 | 
					            if page == 'last':
 | 
				
			||||||
                page_number = paginator.num_pages
 | 
					                page_number = paginator.num_pages
 | 
				
			||||||
            else:
 | 
					            else:
 | 
				
			||||||
                raise Http404(_("Page is not 'last', nor can it be converted to an int."))
 | 
					                raise Http404(_('Choose a valid page number. Page numbers must be a whole number, or must be the string "last".'))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            page = paginator.page(page_number)
 | 
					            page = paginator.page(page_number)
 | 
				
			||||||
        except InvalidPage as exc:
 | 
					        except InvalidPage as exc:
 | 
				
			||||||
            error_format = _('Invalid page (%(page_number)s): %(message)s')
 | 
					            error_format = _('Invalid page "{page_number}": {message}.')
 | 
				
			||||||
            raise Http404(error_format % {
 | 
					            raise Http404(error_format.format(
 | 
				
			||||||
                'page_number': page_number,
 | 
					                page_number=page_number, message=six.text_type(exc)
 | 
				
			||||||
                'message': six.text_type(exc)
 | 
					            ))
 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return page
 | 
					        return page
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										316
									
								
								rest_framework/locale/en_US/LC_MESSAGES/django.po
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										316
									
								
								rest_framework/locale/en_US/LC_MESSAGES/django.po
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,316 @@
 | 
				
			||||||
 | 
					# SOME DESCRIPTIVE TITLE.
 | 
				
			||||||
 | 
					# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
 | 
				
			||||||
 | 
					# This file is distributed under the same license as the PACKAGE package.
 | 
				
			||||||
 | 
					# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					#, fuzzy
 | 
				
			||||||
 | 
					msgid ""
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					"Project-Id-Version: PACKAGE VERSION\n"
 | 
				
			||||||
 | 
					"Report-Msgid-Bugs-To: \n"
 | 
				
			||||||
 | 
					"POT-Creation-Date: 2015-01-07 18:21+0000\n"
 | 
				
			||||||
 | 
					"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 | 
				
			||||||
 | 
					"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 | 
				
			||||||
 | 
					"Language-Team: LANGUAGE <LL@li.org>\n"
 | 
				
			||||||
 | 
					"Language: \n"
 | 
				
			||||||
 | 
					"MIME-Version: 1.0\n"
 | 
				
			||||||
 | 
					"Content-Type: text/plain; charset=UTF-8\n"
 | 
				
			||||||
 | 
					"Content-Transfer-Encoding: 8bit\n"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: authentication.py:69
 | 
				
			||||||
 | 
					msgid "Invalid basic header. No credentials provided."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: authentication.py:72
 | 
				
			||||||
 | 
					msgid "Invalid basic header. Credentials string should not contain spaces."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: authentication.py:78
 | 
				
			||||||
 | 
					msgid "Invalid basic header. Credentials not correctly base64 encoded."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: authentication.py:90
 | 
				
			||||||
 | 
					msgid "Invalid username/password."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: authentication.py:156
 | 
				
			||||||
 | 
					msgid "Invalid token header. No credentials provided."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: authentication.py:159
 | 
				
			||||||
 | 
					msgid "Invalid token header. Token string should not contain spaces."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: authentication.py:168
 | 
				
			||||||
 | 
					msgid "Invalid token."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: authentication.py:171
 | 
				
			||||||
 | 
					msgid "User inactive or deleted."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: authtoken/serializers.py:20
 | 
				
			||||||
 | 
					msgid "User account is disabled."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: authtoken/serializers.py:23
 | 
				
			||||||
 | 
					msgid "Unable to log in with provided credentials."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: authtoken/serializers.py:26
 | 
				
			||||||
 | 
					msgid "Must include \"username\" and \"password\"."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: exceptions.py:38
 | 
				
			||||||
 | 
					msgid "A server error occurred."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: exceptions.py:73
 | 
				
			||||||
 | 
					msgid "Malformed request."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: exceptions.py:78
 | 
				
			||||||
 | 
					msgid "Incorrect authentication credentials."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: exceptions.py:83
 | 
				
			||||||
 | 
					msgid "Authentication credentials were not provided."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: exceptions.py:88
 | 
				
			||||||
 | 
					msgid "You do not have permission to perform this action."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: exceptions.py:93
 | 
				
			||||||
 | 
					msgid "Not found."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: exceptions.py:98
 | 
				
			||||||
 | 
					msgid "Method \"{method}\" not allowed."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: exceptions.py:109
 | 
				
			||||||
 | 
					msgid "Could not satisfy the request Accept header."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: exceptions.py:121
 | 
				
			||||||
 | 
					msgid "Unsupported media type \"{media_type}\" in request."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: exceptions.py:134
 | 
				
			||||||
 | 
					msgid "Request was throttled."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: fields.py:152 relations.py:131 relations.py:155 validators.py:77
 | 
				
			||||||
 | 
					#: validators.py:155
 | 
				
			||||||
 | 
					msgid "This field is required."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: fields.py:153
 | 
				
			||||||
 | 
					msgid "This field may not be null."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: fields.py:480 fields.py:508
 | 
				
			||||||
 | 
					msgid "\"{input}\" is not a valid boolean."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: fields.py:543
 | 
				
			||||||
 | 
					msgid "This field may not be blank."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: fields.py:544 fields.py:1252
 | 
				
			||||||
 | 
					msgid "Ensure this field has no more than {max_length} characters."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: fields.py:545
 | 
				
			||||||
 | 
					msgid "Ensure this field has at least {min_length} characters."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: fields.py:587
 | 
				
			||||||
 | 
					msgid "Enter a valid email address."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: fields.py:604
 | 
				
			||||||
 | 
					msgid "This value does not match the required pattern."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: fields.py:615
 | 
				
			||||||
 | 
					msgid ""
 | 
				
			||||||
 | 
					"Enter a valid \"slug\" consisting of letters, numbers, underscores or "
 | 
				
			||||||
 | 
					"hyphens."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: fields.py:627
 | 
				
			||||||
 | 
					msgid "Enter a valid URL."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: fields.py:640
 | 
				
			||||||
 | 
					msgid "A valid integer is required."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: fields.py:641 fields.py:675 fields.py:708
 | 
				
			||||||
 | 
					msgid "Ensure this value is less than or equal to {max_value}."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: fields.py:642 fields.py:676 fields.py:709
 | 
				
			||||||
 | 
					msgid "Ensure this value is greater than or equal to {min_value}."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: fields.py:643 fields.py:677 fields.py:713
 | 
				
			||||||
 | 
					msgid "String value too large."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: fields.py:674 fields.py:707
 | 
				
			||||||
 | 
					msgid "A valid number is required."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: fields.py:710
 | 
				
			||||||
 | 
					msgid "Ensure that there are no more than {max_digits} digits in total."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: fields.py:711
 | 
				
			||||||
 | 
					msgid "Ensure that there are no more than {max_decimal_places} decimal places."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: fields.py:712
 | 
				
			||||||
 | 
					msgid ""
 | 
				
			||||||
 | 
					"Ensure that there are no more than {max_whole_digits} digits before the "
 | 
				
			||||||
 | 
					"decimal point."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: fields.py:796
 | 
				
			||||||
 | 
					msgid "Datetime has wrong format. Use one of these formats instead: {format}."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: fields.py:797
 | 
				
			||||||
 | 
					msgid "Expected a datetime but got a date."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: fields.py:861
 | 
				
			||||||
 | 
					msgid "Date has wrong format. Use one of these formats instead: {format}."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: fields.py:862
 | 
				
			||||||
 | 
					msgid "Expected a date but got a datetime."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: fields.py:919
 | 
				
			||||||
 | 
					msgid "Time has wrong format. Use one of these formats instead: {format}."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: fields.py:975 fields.py:1019
 | 
				
			||||||
 | 
					msgid "\"{input}\" is not a valid choice."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: fields.py:1020 fields.py:1121 serializers.py:476
 | 
				
			||||||
 | 
					msgid "Expected a list of items but got type \"{input_type}\"."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: fields.py:1050
 | 
				
			||||||
 | 
					msgid "No file was submitted."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: fields.py:1051
 | 
				
			||||||
 | 
					msgid "The submitted data was not a file. Check the encoding type on the form."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: fields.py:1052
 | 
				
			||||||
 | 
					msgid "No filename could be determined."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: fields.py:1053
 | 
				
			||||||
 | 
					msgid "The submitted file is empty."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: fields.py:1054
 | 
				
			||||||
 | 
					msgid ""
 | 
				
			||||||
 | 
					"Ensure this filename has at most {max_length} characters (it has {length})."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: fields.py:1096
 | 
				
			||||||
 | 
					msgid ""
 | 
				
			||||||
 | 
					"Upload a valid image. The file you uploaded was either not an image or a "
 | 
				
			||||||
 | 
					"corrupted image."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: generics.py:123
 | 
				
			||||||
 | 
					msgid ""
 | 
				
			||||||
 | 
					"Choose a valid page number. Page numbers must be a whole number, or must be "
 | 
				
			||||||
 | 
					"the string \"last\"."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: generics.py:128
 | 
				
			||||||
 | 
					msgid "Invalid page \"{page_number}\": {message}."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: relations.py:132
 | 
				
			||||||
 | 
					msgid "Invalid pk \"{pk_value}\" - object does not exist."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: relations.py:133
 | 
				
			||||||
 | 
					msgid "Incorrect type. Expected pk value, received {data_type}."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: relations.py:156
 | 
				
			||||||
 | 
					msgid "Invalid hyperlink - No URL match."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: relations.py:157
 | 
				
			||||||
 | 
					msgid "Invalid hyperlink - Incorrect URL match."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: relations.py:158
 | 
				
			||||||
 | 
					msgid "Invalid hyperlink - Object does not exist."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: relations.py:159
 | 
				
			||||||
 | 
					msgid "Incorrect type. Expected URL string, received {data_type}."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: relations.py:294
 | 
				
			||||||
 | 
					msgid "Object with {slug_name}={value} does not exist."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: relations.py:295
 | 
				
			||||||
 | 
					msgid "Invalid value."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: serializers.py:299
 | 
				
			||||||
 | 
					msgid "Invalid data. Expected a dictionary, but got {datatype}."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: validators.py:22
 | 
				
			||||||
 | 
					msgid "This field must be unique."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: validators.py:76
 | 
				
			||||||
 | 
					msgid "The fields {field_names} must make a unique set."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: validators.py:219
 | 
				
			||||||
 | 
					msgid "This field must be unique for the \"{date_field}\" date."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: validators.py:234
 | 
				
			||||||
 | 
					msgid "This field must be unique for the \"{date_field}\" month."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: validators.py:247
 | 
				
			||||||
 | 
					msgid "This field must be unique for the \"{date_field}\" year."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: versioning.py:39
 | 
				
			||||||
 | 
					msgid "Invalid version in \"Accept\" header."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: versioning.py:70 versioning.py:112
 | 
				
			||||||
 | 
					msgid "Invalid version in URL path."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: versioning.py:138
 | 
				
			||||||
 | 
					msgid "Invalid version in hostname."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#: versioning.py:160
 | 
				
			||||||
 | 
					msgid "Invalid version in query parameter."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
| 
						 | 
					@ -129,7 +129,7 @@ class StringRelatedField(RelatedField):
 | 
				
			||||||
class PrimaryKeyRelatedField(RelatedField):
 | 
					class PrimaryKeyRelatedField(RelatedField):
 | 
				
			||||||
    default_error_messages = {
 | 
					    default_error_messages = {
 | 
				
			||||||
        'required': _('This field is required.'),
 | 
					        'required': _('This field is required.'),
 | 
				
			||||||
        'does_not_exist': _("Invalid pk '{pk_value}' - object does not exist."),
 | 
					        'does_not_exist': _('Invalid pk "{pk_value}" - object does not exist.'),
 | 
				
			||||||
        'incorrect_type': _('Incorrect type. Expected pk value, received {data_type}.'),
 | 
					        'incorrect_type': _('Incorrect type. Expected pk value, received {data_type}.'),
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -153,7 +153,7 @@ class HyperlinkedRelatedField(RelatedField):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    default_error_messages = {
 | 
					    default_error_messages = {
 | 
				
			||||||
        'required': _('This field is required.'),
 | 
					        'required': _('This field is required.'),
 | 
				
			||||||
        'no_match': _('Invalid hyperlink - No URL match'),
 | 
					        'no_match': _('Invalid hyperlink - No URL match.'),
 | 
				
			||||||
        'incorrect_match': _('Invalid hyperlink - Incorrect URL match.'),
 | 
					        'incorrect_match': _('Invalid hyperlink - Incorrect URL match.'),
 | 
				
			||||||
        'does_not_exist': _('Invalid hyperlink - Object does not exist.'),
 | 
					        'does_not_exist': _('Invalid hyperlink - Object does not exist.'),
 | 
				
			||||||
        'incorrect_type': _('Incorrect type. Expected URL string, received {data_type}.'),
 | 
					        'incorrect_type': _('Incorrect type. Expected URL string, received {data_type}.'),
 | 
				
			||||||
| 
						 | 
					@ -291,7 +291,7 @@ class SlugRelatedField(RelatedField):
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    default_error_messages = {
 | 
					    default_error_messages = {
 | 
				
			||||||
        'does_not_exist': _("Object with {slug_name}={value} does not exist."),
 | 
					        'does_not_exist': _('Object with {slug_name}={value} does not exist.'),
 | 
				
			||||||
        'invalid': _('Invalid value.'),
 | 
					        'invalid': _('Invalid value.'),
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -479,7 +479,7 @@ class ListSerializer(BaseSerializer):
 | 
				
			||||||
    many = True
 | 
					    many = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    default_error_messages = {
 | 
					    default_error_messages = {
 | 
				
			||||||
        'not_a_list': _('Expected a list of items but got type `{input_type}`.')
 | 
					        'not_a_list': _('Expected a list of items but got type "{input_type}".')
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self, *args, **kwargs):
 | 
					    def __init__(self, *args, **kwargs):
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -36,7 +36,7 @@ class AcceptHeaderVersioning(BaseVersioning):
 | 
				
			||||||
    Host: example.com
 | 
					    Host: example.com
 | 
				
			||||||
    Accept: application/json; version=1.0
 | 
					    Accept: application/json; version=1.0
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    invalid_version_message = _("Invalid version in 'Accept' header.")
 | 
					    invalid_version_message = _('Invalid version in "Accept" header.')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def determine_version(self, request, *args, **kwargs):
 | 
					    def determine_version(self, request, *args, **kwargs):
 | 
				
			||||||
        media_type = _MediaType(request.accepted_media_type)
 | 
					        media_type = _MediaType(request.accepted_media_type)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -346,7 +346,7 @@ class TestBooleanField(FieldValues):
 | 
				
			||||||
        False: False,
 | 
					        False: False,
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    invalid_inputs = {
 | 
					    invalid_inputs = {
 | 
				
			||||||
        'foo': ['`foo` is not a valid boolean.'],
 | 
					        'foo': ['"foo" is not a valid boolean.'],
 | 
				
			||||||
        None: ['This field may not be null.']
 | 
					        None: ['This field may not be null.']
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    outputs = {
 | 
					    outputs = {
 | 
				
			||||||
| 
						 | 
					@ -376,7 +376,7 @@ class TestNullBooleanField(FieldValues):
 | 
				
			||||||
        None: None
 | 
					        None: None
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    invalid_inputs = {
 | 
					    invalid_inputs = {
 | 
				
			||||||
        'foo': ['`foo` is not a valid boolean.'],
 | 
					        'foo': ['"foo" is not a valid boolean.'],
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    outputs = {
 | 
					    outputs = {
 | 
				
			||||||
        'true': True,
 | 
					        'true': True,
 | 
				
			||||||
| 
						 | 
					@ -447,7 +447,7 @@ class TestSlugField(FieldValues):
 | 
				
			||||||
        'slug-99': 'slug-99',
 | 
					        'slug-99': 'slug-99',
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    invalid_inputs = {
 | 
					    invalid_inputs = {
 | 
				
			||||||
        'slug 99': ["Enter a valid 'slug' consisting of letters, numbers, underscores or hyphens."]
 | 
					        'slug 99': ['Enter a valid "slug" consisting of letters, numbers, underscores or hyphens.']
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    outputs = {}
 | 
					    outputs = {}
 | 
				
			||||||
    field = serializers.SlugField()
 | 
					    field = serializers.SlugField()
 | 
				
			||||||
| 
						 | 
					@ -648,8 +648,8 @@ class TestDateField(FieldValues):
 | 
				
			||||||
        datetime.date(2001, 1, 1): datetime.date(2001, 1, 1),
 | 
					        datetime.date(2001, 1, 1): datetime.date(2001, 1, 1),
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    invalid_inputs = {
 | 
					    invalid_inputs = {
 | 
				
			||||||
        'abc': ['Date has wrong format. Use one of these formats instead: YYYY[-MM[-DD]]'],
 | 
					        'abc': ['Date has wrong format. Use one of these formats instead: YYYY[-MM[-DD]].'],
 | 
				
			||||||
        '2001-99-99': ['Date has wrong format. Use one of these formats instead: YYYY[-MM[-DD]]'],
 | 
					        '2001-99-99': ['Date has wrong format. Use one of these formats instead: YYYY[-MM[-DD]].'],
 | 
				
			||||||
        datetime.datetime(2001, 1, 1, 12, 00): ['Expected a date but got a datetime.'],
 | 
					        datetime.datetime(2001, 1, 1, 12, 00): ['Expected a date but got a datetime.'],
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    outputs = {
 | 
					    outputs = {
 | 
				
			||||||
| 
						 | 
					@ -666,7 +666,7 @@ class TestCustomInputFormatDateField(FieldValues):
 | 
				
			||||||
        '1 Jan 2001': datetime.date(2001, 1, 1),
 | 
					        '1 Jan 2001': datetime.date(2001, 1, 1),
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    invalid_inputs = {
 | 
					    invalid_inputs = {
 | 
				
			||||||
        '2001-01-01': ['Date has wrong format. Use one of these formats instead: DD [Jan-Dec] YYYY']
 | 
					        '2001-01-01': ['Date has wrong format. Use one of these formats instead: DD [Jan-Dec] YYYY.']
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    outputs = {}
 | 
					    outputs = {}
 | 
				
			||||||
    field = serializers.DateField(input_formats=['%d %b %Y'])
 | 
					    field = serializers.DateField(input_formats=['%d %b %Y'])
 | 
				
			||||||
| 
						 | 
					@ -710,8 +710,8 @@ class TestDateTimeField(FieldValues):
 | 
				
			||||||
        '2001-01-01T14:00+01:00' if (django.VERSION > (1, 4)) else '2001-01-01T13:00Z': datetime.datetime(2001, 1, 1, 13, 00, tzinfo=timezone.UTC())
 | 
					        '2001-01-01T14:00+01:00' if (django.VERSION > (1, 4)) else '2001-01-01T13:00Z': datetime.datetime(2001, 1, 1, 13, 00, tzinfo=timezone.UTC())
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    invalid_inputs = {
 | 
					    invalid_inputs = {
 | 
				
			||||||
        'abc': ['Datetime has wrong format. Use one of these formats instead: YYYY-MM-DDThh:mm[:ss[.uuuuuu]][+HH:MM|-HH:MM|Z]'],
 | 
					        'abc': ['Datetime has wrong format. Use one of these formats instead: YYYY-MM-DDThh:mm[:ss[.uuuuuu]][+HH:MM|-HH:MM|Z].'],
 | 
				
			||||||
        '2001-99-99T99:00': ['Datetime has wrong format. Use one of these formats instead: YYYY-MM-DDThh:mm[:ss[.uuuuuu]][+HH:MM|-HH:MM|Z]'],
 | 
					        '2001-99-99T99:00': ['Datetime has wrong format. Use one of these formats instead: YYYY-MM-DDThh:mm[:ss[.uuuuuu]][+HH:MM|-HH:MM|Z].'],
 | 
				
			||||||
        datetime.date(2001, 1, 1): ['Expected a datetime but got a date.'],
 | 
					        datetime.date(2001, 1, 1): ['Expected a datetime but got a date.'],
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    outputs = {
 | 
					    outputs = {
 | 
				
			||||||
| 
						 | 
					@ -729,7 +729,7 @@ class TestCustomInputFormatDateTimeField(FieldValues):
 | 
				
			||||||
        '1:35pm, 1 Jan 2001': datetime.datetime(2001, 1, 1, 13, 35, tzinfo=timezone.UTC()),
 | 
					        '1:35pm, 1 Jan 2001': datetime.datetime(2001, 1, 1, 13, 35, tzinfo=timezone.UTC()),
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    invalid_inputs = {
 | 
					    invalid_inputs = {
 | 
				
			||||||
        '2001-01-01T20:50': ['Datetime has wrong format. Use one of these formats instead: hh:mm[AM|PM], DD [Jan-Dec] YYYY']
 | 
					        '2001-01-01T20:50': ['Datetime has wrong format. Use one of these formats instead: hh:mm[AM|PM], DD [Jan-Dec] YYYY.']
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    outputs = {}
 | 
					    outputs = {}
 | 
				
			||||||
    field = serializers.DateTimeField(default_timezone=timezone.UTC(), input_formats=['%I:%M%p, %d %b %Y'])
 | 
					    field = serializers.DateTimeField(default_timezone=timezone.UTC(), input_formats=['%I:%M%p, %d %b %Y'])
 | 
				
			||||||
| 
						 | 
					@ -781,8 +781,8 @@ class TestTimeField(FieldValues):
 | 
				
			||||||
        datetime.time(13, 00): datetime.time(13, 00),
 | 
					        datetime.time(13, 00): datetime.time(13, 00),
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    invalid_inputs = {
 | 
					    invalid_inputs = {
 | 
				
			||||||
        'abc': ['Time has wrong format. Use one of these formats instead: hh:mm[:ss[.uuuuuu]]'],
 | 
					        'abc': ['Time has wrong format. Use one of these formats instead: hh:mm[:ss[.uuuuuu]].'],
 | 
				
			||||||
        '99:99': ['Time has wrong format. Use one of these formats instead: hh:mm[:ss[.uuuuuu]]'],
 | 
					        '99:99': ['Time has wrong format. Use one of these formats instead: hh:mm[:ss[.uuuuuu]].'],
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    outputs = {
 | 
					    outputs = {
 | 
				
			||||||
        datetime.time(13, 00): '13:00:00'
 | 
					        datetime.time(13, 00): '13:00:00'
 | 
				
			||||||
| 
						 | 
					@ -798,7 +798,7 @@ class TestCustomInputFormatTimeField(FieldValues):
 | 
				
			||||||
        '1:00pm': datetime.time(13, 00),
 | 
					        '1:00pm': datetime.time(13, 00),
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    invalid_inputs = {
 | 
					    invalid_inputs = {
 | 
				
			||||||
        '13:00': ['Time has wrong format. Use one of these formats instead: hh:mm[AM|PM]'],
 | 
					        '13:00': ['Time has wrong format. Use one of these formats instead: hh:mm[AM|PM].'],
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    outputs = {}
 | 
					    outputs = {}
 | 
				
			||||||
    field = serializers.TimeField(input_formats=['%I:%M%p'])
 | 
					    field = serializers.TimeField(input_formats=['%I:%M%p'])
 | 
				
			||||||
| 
						 | 
					@ -840,7 +840,7 @@ class TestChoiceField(FieldValues):
 | 
				
			||||||
        'good': 'good',
 | 
					        'good': 'good',
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    invalid_inputs = {
 | 
					    invalid_inputs = {
 | 
				
			||||||
        'amazing': ['`amazing` is not a valid choice.']
 | 
					        'amazing': ['"amazing" is not a valid choice.']
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    outputs = {
 | 
					    outputs = {
 | 
				
			||||||
        'good': 'good',
 | 
					        'good': 'good',
 | 
				
			||||||
| 
						 | 
					@ -880,8 +880,8 @@ class TestChoiceFieldWithType(FieldValues):
 | 
				
			||||||
        3: 3,
 | 
					        3: 3,
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    invalid_inputs = {
 | 
					    invalid_inputs = {
 | 
				
			||||||
        5: ['`5` is not a valid choice.'],
 | 
					        5: ['"5" is not a valid choice.'],
 | 
				
			||||||
        'abc': ['`abc` is not a valid choice.']
 | 
					        'abc': ['"abc" is not a valid choice.']
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    outputs = {
 | 
					    outputs = {
 | 
				
			||||||
        '1': 1,
 | 
					        '1': 1,
 | 
				
			||||||
| 
						 | 
					@ -907,7 +907,7 @@ class TestChoiceFieldWithListChoices(FieldValues):
 | 
				
			||||||
        'good': 'good',
 | 
					        'good': 'good',
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    invalid_inputs = {
 | 
					    invalid_inputs = {
 | 
				
			||||||
        'awful': ['`awful` is not a valid choice.']
 | 
					        'awful': ['"awful" is not a valid choice.']
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    outputs = {
 | 
					    outputs = {
 | 
				
			||||||
        'good': 'good'
 | 
					        'good': 'good'
 | 
				
			||||||
| 
						 | 
					@ -925,8 +925,8 @@ class TestMultipleChoiceField(FieldValues):
 | 
				
			||||||
        ('aircon', 'manual'): set(['aircon', 'manual']),
 | 
					        ('aircon', 'manual'): set(['aircon', 'manual']),
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    invalid_inputs = {
 | 
					    invalid_inputs = {
 | 
				
			||||||
        'abc': ['Expected a list of items but got type `str`.'],
 | 
					        'abc': ['Expected a list of items but got type "str".'],
 | 
				
			||||||
        ('aircon', 'incorrect'): ['`incorrect` is not a valid choice.']
 | 
					        ('aircon', 'incorrect'): ['"incorrect" is not a valid choice.']
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    outputs = [
 | 
					    outputs = [
 | 
				
			||||||
        (['aircon', 'manual'], set(['aircon', 'manual']))
 | 
					        (['aircon', 'manual'], set(['aircon', 'manual']))
 | 
				
			||||||
| 
						 | 
					@ -1036,7 +1036,7 @@ class TestListField(FieldValues):
 | 
				
			||||||
        (['1', '2', '3'], [1, 2, 3])
 | 
					        (['1', '2', '3'], [1, 2, 3])
 | 
				
			||||||
    ]
 | 
					    ]
 | 
				
			||||||
    invalid_inputs = [
 | 
					    invalid_inputs = [
 | 
				
			||||||
        ('not a list', ['Expected a list of items but got type `str`']),
 | 
					        ('not a list', ['Expected a list of items but got type "str".']),
 | 
				
			||||||
        ([1, 2, 'error'], ['A valid integer is required.'])
 | 
					        ([1, 2, 'error'], ['A valid integer is required.'])
 | 
				
			||||||
    ]
 | 
					    ]
 | 
				
			||||||
    outputs = [
 | 
					    outputs = [
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -117,7 +117,7 @@ class TestRootView(TestCase):
 | 
				
			||||||
        with self.assertNumQueries(0):
 | 
					        with self.assertNumQueries(0):
 | 
				
			||||||
            response = self.view(request).render()
 | 
					            response = self.view(request).render()
 | 
				
			||||||
        self.assertEqual(response.status_code, status.HTTP_405_METHOD_NOT_ALLOWED)
 | 
					        self.assertEqual(response.status_code, status.HTTP_405_METHOD_NOT_ALLOWED)
 | 
				
			||||||
        self.assertEqual(response.data, {"detail": "Method 'PUT' not allowed."})
 | 
					        self.assertEqual(response.data, {"detail": 'Method "PUT" not allowed.'})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_delete_root_view(self):
 | 
					    def test_delete_root_view(self):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
| 
						 | 
					@ -127,7 +127,7 @@ class TestRootView(TestCase):
 | 
				
			||||||
        with self.assertNumQueries(0):
 | 
					        with self.assertNumQueries(0):
 | 
				
			||||||
            response = self.view(request).render()
 | 
					            response = self.view(request).render()
 | 
				
			||||||
        self.assertEqual(response.status_code, status.HTTP_405_METHOD_NOT_ALLOWED)
 | 
					        self.assertEqual(response.status_code, status.HTTP_405_METHOD_NOT_ALLOWED)
 | 
				
			||||||
        self.assertEqual(response.data, {"detail": "Method 'DELETE' not allowed."})
 | 
					        self.assertEqual(response.data, {"detail": 'Method "DELETE" not allowed.'})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_post_cannot_set_id(self):
 | 
					    def test_post_cannot_set_id(self):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
| 
						 | 
					@ -181,7 +181,7 @@ class TestInstanceView(TestCase):
 | 
				
			||||||
        with self.assertNumQueries(0):
 | 
					        with self.assertNumQueries(0):
 | 
				
			||||||
            response = self.view(request).render()
 | 
					            response = self.view(request).render()
 | 
				
			||||||
        self.assertEqual(response.status_code, status.HTTP_405_METHOD_NOT_ALLOWED)
 | 
					        self.assertEqual(response.status_code, status.HTTP_405_METHOD_NOT_ALLOWED)
 | 
				
			||||||
        self.assertEqual(response.data, {"detail": "Method 'POST' not allowed."})
 | 
					        self.assertEqual(response.data, {"detail": 'Method "POST" not allowed.'})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_put_instance_view(self):
 | 
					    def test_put_instance_view(self):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -33,7 +33,7 @@ class TestPrimaryKeyRelatedField(APISimpleTestCase):
 | 
				
			||||||
        with pytest.raises(serializers.ValidationError) as excinfo:
 | 
					        with pytest.raises(serializers.ValidationError) as excinfo:
 | 
				
			||||||
            self.field.to_internal_value(4)
 | 
					            self.field.to_internal_value(4)
 | 
				
			||||||
        msg = excinfo.value.detail[0]
 | 
					        msg = excinfo.value.detail[0]
 | 
				
			||||||
        assert msg == "Invalid pk '4' - object does not exist."
 | 
					        assert msg == 'Invalid pk "4" - object does not exist.'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_pk_related_lookup_invalid_type(self):
 | 
					    def test_pk_related_lookup_invalid_type(self):
 | 
				
			||||||
        with pytest.raises(serializers.ValidationError) as excinfo:
 | 
					        with pytest.raises(serializers.ValidationError) as excinfo:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -101,7 +101,7 @@ class BulkCreateSerializerTests(TestCase):
 | 
				
			||||||
        serializer = self.BookSerializer(data=data, many=True)
 | 
					        serializer = self.BookSerializer(data=data, many=True)
 | 
				
			||||||
        self.assertEqual(serializer.is_valid(), False)
 | 
					        self.assertEqual(serializer.is_valid(), False)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        expected_errors = {'non_field_errors': ['Expected a list of items but got type `int`.']}
 | 
					        expected_errors = {'non_field_errors': ['Expected a list of items but got type "int".']}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.assertEqual(serializer.errors, expected_errors)
 | 
					        self.assertEqual(serializer.errors, expected_errors)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -118,6 +118,6 @@ class BulkCreateSerializerTests(TestCase):
 | 
				
			||||||
        serializer = self.BookSerializer(data=data, many=True)
 | 
					        serializer = self.BookSerializer(data=data, many=True)
 | 
				
			||||||
        self.assertEqual(serializer.is_valid(), False)
 | 
					        self.assertEqual(serializer.is_valid(), False)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        expected_errors = {'non_field_errors': ['Expected a list of items but got type `dict`.']}
 | 
					        expected_errors = {'non_field_errors': ['Expected a list of items but got type "dict".']}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.assertEqual(serializer.errors, expected_errors)
 | 
					        self.assertEqual(serializer.errors, expected_errors)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user