mirror of
				https://github.com/encode/django-rest-framework.git
				synced 2025-11-04 01:47:59 +03:00 
			
		
		
		
	Merge pull request #1784 from tomchristie/remove-model-attribute
Deprecate `.model` attribute on views
This commit is contained in:
		
						commit
						8f4ae06b3b
					
				
							
								
								
									
										74
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										74
									
								
								README.md
									
									
									
									
									
								
							| 
						 | 
				
			
			@ -39,40 +39,51 @@ Add `'rest_framework'` to your `INSTALLED_APPS` setting.
 | 
			
		|||
 | 
			
		||||
    INSTALLED_APPS = (
 | 
			
		||||
        ...
 | 
			
		||||
        'rest_framework',        
 | 
			
		||||
        'rest_framework',
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
# Example
 | 
			
		||||
 | 
			
		||||
Let's take a look at a quick example of using REST framework to build a simple model-backed API for accessing users and groups.
 | 
			
		||||
 | 
			
		||||
Here's our project's root `urls.py` module:
 | 
			
		||||
Startup up a new project like so... 
 | 
			
		||||
 | 
			
		||||
    pip install django
 | 
			
		||||
    pip install djangorestframework
 | 
			
		||||
    django-admin startproject example .
 | 
			
		||||
    ./manage.py syncdb
 | 
			
		||||
 | 
			
		||||
Now edit the `example/urls.py` module in your project:
 | 
			
		||||
 | 
			
		||||
```python
 | 
			
		||||
from django.conf.urls.defaults import url, patterns, include
 | 
			
		||||
from django.contrib.auth.models import User, Group
 | 
			
		||||
from rest_framework import viewsets, routers
 | 
			
		||||
from django.conf.urls import url, include
 | 
			
		||||
from django.contrib.auth.models import User
 | 
			
		||||
from rest_framework import serializers, viewsets, routers
 | 
			
		||||
 | 
			
		||||
# Serializers define the API representation.
 | 
			
		||||
class UserSerializer(serializers.HyperlinkedModelSerializer):
 | 
			
		||||
    class Meta:
 | 
			
		||||
        model = User
 | 
			
		||||
        fields = ('url', 'username', 'email', 'is_staff')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# ViewSets define the view behavior.
 | 
			
		||||
class UserViewSet(viewsets.ModelViewSet):
 | 
			
		||||
    model = User
 | 
			
		||||
 | 
			
		||||
class GroupViewSet(viewsets.ModelViewSet):
 | 
			
		||||
    model = Group
 | 
			
		||||
    queryset = User.objects.all()
 | 
			
		||||
    serializer_class = UserSerializer
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
# Routers provide an easy way of automatically determining the URL conf
 | 
			
		||||
# Routers provide a way of automatically determining the URL conf.
 | 
			
		||||
router = routers.DefaultRouter()
 | 
			
		||||
router.register(r'users', UserViewSet)
 | 
			
		||||
router.register(r'groups', GroupViewSet)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Wire up our API using automatic URL routing.
 | 
			
		||||
# Additionally, we include login URLs for the browseable API.
 | 
			
		||||
urlpatterns = patterns('',
 | 
			
		||||
urlpatterns = [
 | 
			
		||||
    url(r'^', include(router.urls)),
 | 
			
		||||
    url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework'))
 | 
			
		||||
)
 | 
			
		||||
]
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
We'd also like to configure a couple of settings for our API.
 | 
			
		||||
| 
						 | 
				
			
			@ -80,12 +91,12 @@ We'd also like to configure a couple of settings for our API.
 | 
			
		|||
Add the following to your `settings.py` module:
 | 
			
		||||
 | 
			
		||||
```python
 | 
			
		||||
REST_FRAMEWORK = {
 | 
			
		||||
    # Use hyperlinked styles by default.
 | 
			
		||||
    # Only used if the `serializer_class` attribute is not set on a view.
 | 
			
		||||
    'DEFAULT_MODEL_SERIALIZER_CLASS':
 | 
			
		||||
        'rest_framework.serializers.HyperlinkedModelSerializer',
 | 
			
		||||
INSTALLED_APPS = (
 | 
			
		||||
    ...  # Make sure to include the default installed apps here.
 | 
			
		||||
    'rest_framework',        
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
REST_FRAMEWORK = {
 | 
			
		||||
    # Use Django's standard `django.contrib.auth` permissions,
 | 
			
		||||
    # or allow read-only access for unauthenticated users.
 | 
			
		||||
    'DEFAULT_PERMISSION_CLASSES': [
 | 
			
		||||
| 
						 | 
				
			
			@ -93,10 +104,35 @@ REST_FRAMEWORK = {
 | 
			
		|||
    ]
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
Don't forget to make sure you've also added `rest_framework` to your `INSTALLED_APPS` setting.
 | 
			
		||||
 | 
			
		||||
That's it, we're done!
 | 
			
		||||
 | 
			
		||||
    ./manage.py runserver
 | 
			
		||||
 | 
			
		||||
You can now open the API in your browser at `http://127.0.0.1:8000/`, and view your new 'users' API. If you use the `Login` control in the top right corner you'll also be able to add, create and delete users from the system.
 | 
			
		||||
 | 
			
		||||
You can also interact with the API using command line tools such as [`curl`](http://curl.haxx.se/). For example, to list the users endpoint:
 | 
			
		||||
 | 
			
		||||
    $ curl -H 'Accept: application/json; indent=4' -u admin:password http://127.0.0.1:8000/users/
 | 
			
		||||
	[
 | 
			
		||||
	    {
 | 
			
		||||
	        "url": "http://127.0.0.1:8000/users/1/", 
 | 
			
		||||
	        "username": "admin", 
 | 
			
		||||
	        "email": "admin@example.com", 
 | 
			
		||||
	        "is_staff": true, 
 | 
			
		||||
	    }
 | 
			
		||||
	]
 | 
			
		||||
 | 
			
		||||
Or to create a new user:
 | 
			
		||||
 | 
			
		||||
    $ curl -X POST -d username=new -d email=new@example.com -d is_staff=false -H 'Accept: application/json; indent=4' -u admin:password http://127.0.0.1:8000/users/
 | 
			
		||||
    {
 | 
			
		||||
        "url": "http://127.0.0.1:8000/users/2/", 
 | 
			
		||||
        "username": "new", 
 | 
			
		||||
        "email": "new@example.com", 
 | 
			
		||||
        "is_staff": false, 
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
# Documentation & Support
 | 
			
		||||
 | 
			
		||||
Full documentation for the project is available at [http://www.django-rest-framework.org][docs].
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -74,10 +74,6 @@ The following attributes control the basic view behavior.
 | 
			
		|||
* `lookup_field` - The model field that should be used to for performing object lookup of individual model instances.  Defaults to `'pk'`.  Note that when using hyperlinked APIs you'll need to ensure that *both* the API views *and* the serializer classes set the lookup fields if you need to use a custom value.
 | 
			
		||||
* `lookup_url_kwarg` - The URL keyword argument that should be used for object lookup.  The URL conf should include a keyword argument corresponding to this value.  If unset this defaults to using the same value as `lookup_field`.
 | 
			
		||||
 | 
			
		||||
**Shortcuts**:
 | 
			
		||||
 | 
			
		||||
* `model` - This shortcut may be used instead of setting either (or both) of the `queryset`/`serializer_class` attributes, although using the explicit style is generally preferred.  If used instead of `serializer_class`, then `DEFAULT_MODEL_SERIALIZER_CLASS` setting will determine the base serializer class.  Note that `model` is only ever used for generating a default queryset or serializer class - the `queryset` and `serializer_class` attributes are always preferred if provided.
 | 
			
		||||
 | 
			
		||||
**Pagination**:
 | 
			
		||||
 | 
			
		||||
The following attributes are used to control pagination when used with list views.
 | 
			
		||||
| 
						 | 
				
			
			@ -91,6 +87,10 @@ The following attributes are used to control pagination when used with list view
 | 
			
		|||
 | 
			
		||||
* `filter_backends` - A list of filter backend classes that should be used for filtering the queryset.  Defaults to the same value as the `DEFAULT_FILTER_BACKENDS` setting.
 | 
			
		||||
 | 
			
		||||
**Deprecated attributes**:
 | 
			
		||||
 | 
			
		||||
* `model` - This shortcut may be used instead of setting either (or both) of the `queryset`/`serializer_class` attributes. The explicit style is preferred over the `.model` shortcut, and usage of this attribute is now deprecated.
 | 
			
		||||
 | 
			
		||||
### Methods
 | 
			
		||||
 | 
			
		||||
**Base methods**:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -114,7 +114,7 @@ This permission is suitable if you want to your API to allow read permissions to
 | 
			
		|||
 | 
			
		||||
## DjangoModelPermissions
 | 
			
		||||
 | 
			
		||||
This permission class ties into Django's standard `django.contrib.auth` [model permissions][contribauth].  When applied to a view that has a `.model` property, authorization will only be granted if the user *is authenticated* and has the *relevant model permissions* assigned.
 | 
			
		||||
This permission class ties into Django's standard `django.contrib.auth` [model permissions][contribauth].  This permission must only be applied to views that has a `.queryset` property set. Authorization will only be granted if the user *is authenticated* and has the *relevant model permissions* assigned.
 | 
			
		||||
 | 
			
		||||
* `POST` requests require the user to have the `add` permission on the model.
 | 
			
		||||
* `PUT` and `PATCH` requests require the user to have the `change` permission on the model.
 | 
			
		||||
| 
						 | 
				
			
			@ -124,6 +124,12 @@ The default behaviour can also be overridden to support custom model permissions
 | 
			
		|||
 | 
			
		||||
To use custom model permissions, override `DjangoModelPermissions` and set the `.perms_map` property.  Refer to the source code for details.
 | 
			
		||||
 | 
			
		||||
#### Using with views that do not include a `queryset` attribute.
 | 
			
		||||
 | 
			
		||||
If you're using this permission with a view that uses an overridden `get_queryset()` method there may not be a `queryset` attribute on the view. In this case we suggest also marking the view with a sential queryset, so that this class can determine the required permissions. For example:
 | 
			
		||||
 | 
			
		||||
    queryset = User.objects.none()  # Required for DjangoModelPermissions
 | 
			
		||||
 | 
			
		||||
## DjangoModelPermissionsOrAnonReadOnly
 | 
			
		||||
 | 
			
		||||
Similar to `DjangoModelPermissions`, but also allows unauthenticated users to have read-only access to the API.
 | 
			
		||||
| 
						 | 
				
			
			@ -132,7 +138,7 @@ Similar to `DjangoModelPermissions`, but also allows unauthenticated users to ha
 | 
			
		|||
 | 
			
		||||
This permission class ties into Django's standard [object permissions framework][objectpermissions] that allows per-object permissions on models.  In order to use this permission class, you'll also need to add a permission backend that supports object-level permissions, such as [django-guardian][guardian].
 | 
			
		||||
 | 
			
		||||
When applied to a view that has a `.model` property, authorization will only be granted if the user *is authenticated* and has the *relevant per-object permissions* and *relevant model permissions* assigned.
 | 
			
		||||
As with `DjangoModelPermissions`, this permission must only be applied to views that have a `.queryset` property. Authorization will only be granted if the user *is authenticated* and has the *relevant per-object permissions* and *relevant model permissions* assigned.
 | 
			
		||||
 | 
			
		||||
* `POST` requests require the user to have the `add` permission on the model instance.
 | 
			
		||||
* `PUT` and `PATCH` requests require the user to have the `change` permission on the model instance.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -41,9 +41,9 @@ The example above would generate the following URL patterns:
 | 
			
		|||
 | 
			
		||||
**Note**: The `base_name` argument is used to specify the initial part of the view name pattern.  In the example above, that's the `user` or `account` part.
 | 
			
		||||
 | 
			
		||||
Typically you won't *need* to specify the `base-name` argument, but if you have a viewset where you've defined a custom `get_queryset` method, then the viewset may not have any `.model` or `.queryset` attribute set.  If you try to register that viewset you'll see an error like this:
 | 
			
		||||
Typically you won't *need* to specify the `base-name` argument, but if you have a viewset where you've defined a custom `get_queryset` method, then the viewset may not have a `.queryset` attribute set.  If you try to register that viewset you'll see an error like this:
 | 
			
		||||
 | 
			
		||||
    'base_name' argument not specified, and could not automatically determine the name from the viewset, as it does not have a '.model' or '.queryset' attribute.
 | 
			
		||||
    'base_name' argument not specified, and could not automatically determine the name from the viewset, as it does not have a '.queryset' attribute.
 | 
			
		||||
 | 
			
		||||
This means you'll need to explicitly set the `base_name` argument when registering the viewset, as it could not be automatically determined from the model name.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -100,12 +100,6 @@ Default: `'rest_framework.negotiation.DefaultContentNegotiation'`
 | 
			
		|||
 | 
			
		||||
*The following settings control the behavior of the generic class based views.*
 | 
			
		||||
 | 
			
		||||
#### DEFAULT_MODEL_SERIALIZER_CLASS
 | 
			
		||||
 | 
			
		||||
A class that determines the default type of model serializer that should be used by a generic view if `model` is specified, but `serializer_class` is not provided.
 | 
			
		||||
 | 
			
		||||
Default: `'rest_framework.serializers.ModelSerializer'`
 | 
			
		||||
 | 
			
		||||
#### DEFAULT_PAGINATION_SERIALIZER_CLASS
 | 
			
		||||
 | 
			
		||||
A class the determines the default serialization style for paginated responses.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -96,16 +96,11 @@ Note that the URL path can be whatever you want, but you must include `'rest_fra
 | 
			
		|||
 | 
			
		||||
Let's take a look at a quick example of using REST framework to build a simple model-backed API.
 | 
			
		||||
 | 
			
		||||
We'll create a read-write API for accessing users and groups.
 | 
			
		||||
We'll create a read-write API for accessing information on the users of our project.
 | 
			
		||||
 | 
			
		||||
Any global settings for a REST framework API are kept in a single configuration dictionary named `REST_FRAMEWORK`.  Start off by adding the following to your `settings.py` module:
 | 
			
		||||
 | 
			
		||||
    REST_FRAMEWORK = {
 | 
			
		||||
        # Use hyperlinked styles by default.
 | 
			
		||||
        # Only used if the `serializer_class` attribute is not set on a view.
 | 
			
		||||
        'DEFAULT_MODEL_SERIALIZER_CLASS':
 | 
			
		||||
            'rest_framework.serializers.HyperlinkedModelSerializer',
 | 
			
		||||
 | 
			
		||||
        # Use Django's standard `django.contrib.auth` permissions,
 | 
			
		||||
        # or allow read-only access for unauthenticated users.
 | 
			
		||||
        'DEFAULT_PERMISSION_CLASSES': [
 | 
			
		||||
| 
						 | 
				
			
			@ -118,34 +113,37 @@ Don't forget to make sure you've also added `rest_framework` to your `INSTALLED_
 | 
			
		|||
We're ready to create our API now.
 | 
			
		||||
Here's our project's root `urls.py` module:
 | 
			
		||||
 | 
			
		||||
    from django.conf.urls import url, patterns, include
 | 
			
		||||
    from django.contrib.auth.models import User, Group
 | 
			
		||||
    from rest_framework import viewsets, routers
 | 
			
		||||
    from django.conf.urls import url, include
 | 
			
		||||
    from django.contrib.auth.models import User
 | 
			
		||||
    from rest_framework import routers, serializers, viewsets
 | 
			
		||||
 | 
			
		||||
	# Serializers define the API representation.
 | 
			
		||||
	class UserSerializer(serializers.HyperlinkedModelSerializer):
 | 
			
		||||
	    class Meta:
 | 
			
		||||
	        model = User
 | 
			
		||||
	        fields = ('url', 'username', 'email', 'is_staff')
 | 
			
		||||
 | 
			
		||||
    # ViewSets define the view behavior.
 | 
			
		||||
    class UserViewSet(viewsets.ModelViewSet):
 | 
			
		||||
        model = User
 | 
			
		||||
 | 
			
		||||
    class GroupViewSet(viewsets.ModelViewSet):
 | 
			
		||||
        model = Group
 | 
			
		||||
 | 
			
		||||
        queryset = User.objects.all()
 | 
			
		||||
        serializer_class = UserSerializer
 | 
			
		||||
 | 
			
		||||
    # Routers provide an easy way of automatically determining the URL conf.
 | 
			
		||||
    router = routers.DefaultRouter()
 | 
			
		||||
    router.register(r'users', UserViewSet)
 | 
			
		||||
    router.register(r'groups', GroupViewSet)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    # Wire up our API using automatic URL routing.
 | 
			
		||||
    # Additionally, we include login URLs for the browseable API.
 | 
			
		||||
    urlpatterns = patterns('',
 | 
			
		||||
    urlpatterns = [
 | 
			
		||||
        url(r'^', include(router.urls)),
 | 
			
		||||
        url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework'))
 | 
			
		||||
    )
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
You can now open the API in your browser at [http://127.0.0.1:8000/](http://127.0.0.1:8000/), and view your new 'users' API. If you use the login control in the top right corner you'll also be able to add, create and delete users from the system.
 | 
			
		||||
 | 
			
		||||
## Quickstart
 | 
			
		||||
 | 
			
		||||
Can't wait to get started?  The [quickstart guide][quickstart] is the fastest way to get up and running, and building APIs with REST framework.
 | 
			
		||||
Can't wait to get started? The [quickstart guide][quickstart] is the fastest way to get up and running, and building APIs with REST framework.
 | 
			
		||||
 | 
			
		||||
## Tutorial
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -15,6 +15,16 @@ The optional authtoken application now includes support for *both* Django 1.7 sc
 | 
			
		|||
 | 
			
		||||
**If you are using authtoken, and you want to continue using `south`, you must upgrade your `south` package to version 1.0.**
 | 
			
		||||
 | 
			
		||||
## Deprecation of `.model` view attribute
 | 
			
		||||
 | 
			
		||||
The `.model` attribute on view classes is an optional shortcut for either or both of `.serializer_class` and `.queryset`. It's usage results in more implicit, less obvious behavior.
 | 
			
		||||
 | 
			
		||||
The documentation has previously stated that usage of the more explict style is prefered, and we're now taking that one step further and deprecating the usage of the `.model` shortcut.
 | 
			
		||||
 | 
			
		||||
Doing so will mean that there are cases of API code where you'll now need to include a serializer class where you previously were just using the `.model` shortcut. However we firmly believe that it is the right trade-off to make. Removing the shortcut takes away an unneccessary layer of abstraction, and makes your codebase more explict without any significant extra complexity.
 | 
			
		||||
 | 
			
		||||
The `DEFAULT_MODEL_SERIALIZER_CLASS` API setting is now also deprecated.
 | 
			
		||||
 | 
			
		||||
## Updated test runner
 | 
			
		||||
 | 
			
		||||
We now have a new test runner for developing against the project,, that uses the excellent [py.test](http://pytest.org) library.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -48,6 +48,7 @@ You can determine your currently installed version using `pip freeze`:
 | 
			
		|||
 | 
			
		||||
* Added compatibility with Django 1.7's database migration support.
 | 
			
		||||
* New test runner, using `py.test`.
 | 
			
		||||
* Deprecated `.model` view attribute in favor of explict `.queryset` and `.serializer_class` attributes. The `DEFAULT_MODEL_SERIALIZER_CLASS` setting is also deprecated.
 | 
			
		||||
* `@detail_route` and `@list_route` decorators replace `@action` and `@link`.
 | 
			
		||||
* Support customizable view name and description functions, using the `VIEW_NAME_FUNCTION` and `VIEW_DESCRIPTION_FUNCTION` settings.
 | 
			
		||||
* Added `NUM_PROXIES` setting for smarter client IP identification.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,34 +18,23 @@ Create a new Django project named `tutorial`, then start a new app called `quick
 | 
			
		|||
    pip install django
 | 
			
		||||
    pip install djangorestframework
 | 
			
		||||
 | 
			
		||||
    # Set up a new project
 | 
			
		||||
    django-admin.py startproject tutorial
 | 
			
		||||
    # Set up a new project with a single application
 | 
			
		||||
    django-admin.py startproject tutorial .
 | 
			
		||||
    cd tutorial
 | 
			
		||||
    django-admin.py startapp quickstart
 | 
			
		||||
	cd ..
 | 
			
		||||
 | 
			
		||||
    # Create a new app
 | 
			
		||||
    python manage.py startapp quickstart
 | 
			
		||||
 | 
			
		||||
Next you'll need to get a database set up and synced.  If you just want to use SQLite for now, then you'll want to edit your `tutorial/settings.py` module to include something like this:
 | 
			
		||||
 | 
			
		||||
    DATABASES = {
 | 
			
		||||
        'default': {
 | 
			
		||||
            'ENGINE': 'django.db.backends.sqlite3',
 | 
			
		||||
            'NAME': 'database.sql',
 | 
			
		||||
            'USER': '',
 | 
			
		||||
            'PASSWORD': '',
 | 
			
		||||
            'HOST': '',
 | 
			
		||||
            'PORT': ''
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
The run `syncdb` like so:
 | 
			
		||||
Now sync your database for the first time:
 | 
			
		||||
 | 
			
		||||
    python manage.py syncdb
 | 
			
		||||
 | 
			
		||||
Make sure to create an initial user named `admin` with a password of `password`. We'll authenticate as that user later in our example.
 | 
			
		||||
 | 
			
		||||
Once you've set up a database and got everything synced and ready to go, open up the app's directory and we'll get coding...
 | 
			
		||||
 | 
			
		||||
## Serializers
 | 
			
		||||
 | 
			
		||||
First up we're going to define some serializers in `quickstart/serializers.py` that we'll use for our data representations.
 | 
			
		||||
First up we're going to define some serializers. Let's create a new module named `tutorial/quickstart/serializers.py` that we'll use for our data representations.
 | 
			
		||||
 | 
			
		||||
    from django.contrib.auth.models import User, Group
 | 
			
		||||
    from rest_framework import serializers
 | 
			
		||||
| 
						 | 
				
			
			@ -66,11 +55,11 @@ Notice that we're using hyperlinked relations in this case, with `HyperlinkedMod
 | 
			
		|||
 | 
			
		||||
## Views
 | 
			
		||||
 | 
			
		||||
Right, we'd better write some views then.  Open `quickstart/views.py` and get typing.
 | 
			
		||||
Right, we'd better write some views then.  Open `tutorial/quickstart/views.py` and get typing.
 | 
			
		||||
 | 
			
		||||
    from django.contrib.auth.models import User, Group
 | 
			
		||||
    from rest_framework import viewsets
 | 
			
		||||
    from quickstart.serializers import UserSerializer, GroupSerializer
 | 
			
		||||
    from tutorial.quickstart.serializers import UserSerializer, GroupSerializer
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    class UserViewSet(viewsets.ModelViewSet):
 | 
			
		||||
| 
						 | 
				
			
			@ -100,9 +89,9 @@ For trivial cases you can simply set a `model` attribute on the `ViewSet` class
 | 
			
		|||
 | 
			
		||||
Okay, now let's wire up the API URLs.  On to `tutorial/urls.py`...
 | 
			
		||||
 | 
			
		||||
    from django.conf.urls import patterns, url, include
 | 
			
		||||
    from django.conf.urls import url, include
 | 
			
		||||
    from rest_framework import routers
 | 
			
		||||
    from quickstart import views
 | 
			
		||||
    from tutorial.quickstart import views
 | 
			
		||||
 | 
			
		||||
    router = routers.DefaultRouter()
 | 
			
		||||
    router.register(r'users', views.UserViewSet)
 | 
			
		||||
| 
						 | 
				
			
			@ -110,10 +99,10 @@ Okay, now let's wire up the API URLs.  On to `tutorial/urls.py`...
 | 
			
		|||
 | 
			
		||||
    # Wire up our API using automatic URL routing.
 | 
			
		||||
    # Additionally, we include login URLs for the browseable API.
 | 
			
		||||
    urlpatterns = patterns('',
 | 
			
		||||
    urlpatterns = [
 | 
			
		||||
        url(r'^', include(router.urls)),
 | 
			
		||||
        url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework'))
 | 
			
		||||
    )
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
Because we're using viewsets instead of views, we can automatically generate the URL conf for our API, by simply registering the viewsets with a router class.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -172,6 +161,8 @@ Or directly through the browser...
 | 
			
		|||
 | 
			
		||||
![Quick start image][image]
 | 
			
		||||
 | 
			
		||||
If you're working through the browser, make sure to login using the control in the top right corner.
 | 
			
		||||
 | 
			
		||||
Great, that was easy!
 | 
			
		||||
 | 
			
		||||
If you want to get a more in depth understanding of how REST framework fits together head on over to [the tutorial][tutorial], or start browsing the [API guide][guide].
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -252,6 +252,12 @@ class GenericAPIView(views.APIView):
 | 
			
		|||
        if serializer_class is not None:
 | 
			
		||||
            return serializer_class
 | 
			
		||||
 | 
			
		||||
        warnings.warn(
 | 
			
		||||
            'The `.model` attribute on view classes is now deprecated in favor '
 | 
			
		||||
            'of the more explicit `serializer_class` and `queryset` attributes.',
 | 
			
		||||
            DeprecationWarning, stacklevel=2
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        assert self.model is not None, \
 | 
			
		||||
            "'%s' should either include a 'serializer_class' attribute, " \
 | 
			
		||||
            "or use the 'model' attribute as a shortcut for " \
 | 
			
		||||
| 
						 | 
				
			
			@ -282,6 +288,11 @@ class GenericAPIView(views.APIView):
 | 
			
		|||
            return self.queryset._clone()
 | 
			
		||||
 | 
			
		||||
        if self.model is not None:
 | 
			
		||||
            warnings.warn(
 | 
			
		||||
                'The `.model` attribute on view classes is now deprecated in favor '
 | 
			
		||||
                'of the more explicit `serializer_class` and `queryset` attributes.',
 | 
			
		||||
                DeprecationWarning, stacklevel=2
 | 
			
		||||
            )
 | 
			
		||||
            return self.model._default_manager.all()
 | 
			
		||||
 | 
			
		||||
        error_format = "'%s' must define 'queryset' or 'model'"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -108,6 +108,9 @@ class DjangoModelPermissions(BasePermission):
 | 
			
		|||
        return [perm % kwargs for perm in self.perms_map[method]]
 | 
			
		||||
 | 
			
		||||
    def has_permission(self, request, view):
 | 
			
		||||
        # Note that `.model` attribute on views is deprecated, although we
 | 
			
		||||
        # enforce the deprecation on the view `get_serializer_class()` and
 | 
			
		||||
        # `get_queryset()` methods, rather than here.
 | 
			
		||||
        model_cls = getattr(view, 'model', None)
 | 
			
		||||
        queryset = getattr(view, 'queryset', None)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -128,6 +128,9 @@ class SimpleRouter(BaseRouter):
 | 
			
		|||
        If `base_name` is not specified, attempt to automatically determine
 | 
			
		||||
        it from the viewset.
 | 
			
		||||
        """
 | 
			
		||||
        # Note that `.model` attribute on views is deprecated, although we
 | 
			
		||||
        # enforce the deprecation on the view `get_serializer_class()` and
 | 
			
		||||
        # `get_queryset()` methods, rather than here.
 | 
			
		||||
        model_cls = getattr(viewset, 'model', None)
 | 
			
		||||
        queryset = getattr(viewset, 'queryset', None)
 | 
			
		||||
        if model_cls is None and queryset is not None:
 | 
			
		||||
| 
						 | 
				
			
			@ -135,7 +138,7 @@ class SimpleRouter(BaseRouter):
 | 
			
		|||
 | 
			
		||||
        assert model_cls, '`base_name` argument not specified, and could ' \
 | 
			
		||||
            'not automatically determine the name from the viewset, as ' \
 | 
			
		||||
            'it does not have a `.model` or `.queryset` attribute.'
 | 
			
		||||
            'it does not have a `.queryset` attribute.'
 | 
			
		||||
 | 
			
		||||
        return model_cls._meta.object_name.lower()
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue
	
	Block a user