mirror of
https://github.com/encode/django-rest-framework.git
synced 2024-11-29 13:04:03 +03:00
Remove InstanceMixin auto-url magicks.
This commit is contained in:
parent
2b59df004a
commit
e15494a172
|
@ -25,14 +25,13 @@ __all__ = (
|
||||||
'ResponseMixin',
|
'ResponseMixin',
|
||||||
'AuthMixin',
|
'AuthMixin',
|
||||||
'ResourceMixin',
|
'ResourceMixin',
|
||||||
# Reverse URL lookup behavior
|
|
||||||
'InstanceMixin',
|
|
||||||
# Model behavior mixins
|
# Model behavior mixins
|
||||||
'ReadModelMixin',
|
'ReadModelMixin',
|
||||||
'CreateModelMixin',
|
'CreateModelMixin',
|
||||||
'UpdateModelMixin',
|
'UpdateModelMixin',
|
||||||
'DeleteModelMixin',
|
'DeleteModelMixin',
|
||||||
'ListModelMixin'
|
'ListModelMixin',
|
||||||
|
'PaginatorMixin'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -444,30 +443,6 @@ class ResourceMixin(object):
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
##########
|
|
||||||
|
|
||||||
|
|
||||||
class InstanceMixin(object):
|
|
||||||
"""
|
|
||||||
`Mixin` class that is used to identify a `View` class as being the canonical identifier
|
|
||||||
for the resources it is mapped to.
|
|
||||||
"""
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def as_view(cls, **initkwargs):
|
|
||||||
"""
|
|
||||||
Store the callable object on the resource class that has been associated with this view.
|
|
||||||
"""
|
|
||||||
view = super(InstanceMixin, cls).as_view(**initkwargs)
|
|
||||||
resource = getattr(cls(**initkwargs), 'resource', None)
|
|
||||||
if resource:
|
|
||||||
# We do a little dance when we store the view callable...
|
|
||||||
# we need to store it wrapped in a 1-tuple, so that inspect will treat it
|
|
||||||
# as a function when we later look it up (rather than turning it into a method).
|
|
||||||
# This makes sure our URL reversing works ok.
|
|
||||||
resource.view_callable = (view,)
|
|
||||||
return view
|
|
||||||
|
|
||||||
|
|
||||||
########## Model Mixins ##########
|
########## Model Mixins ##########
|
||||||
|
|
||||||
|
@ -599,7 +574,7 @@ class CreateModelMixin(ModelMixin):
|
||||||
manager.through(**data).save()
|
manager.through(**data).save()
|
||||||
|
|
||||||
headers = {}
|
headers = {}
|
||||||
if hasattr(instance, 'get_absolute_url'):
|
if hasattr(self.resource, 'url'):
|
||||||
headers['Location'] = self.resource(self).url(instance)
|
headers['Location'] = self.resource(self).url(instance)
|
||||||
return Response(status.HTTP_201_CREATED, instance, headers)
|
return Response(status.HTTP_201_CREATED, instance, headers)
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,7 @@
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.core.urlresolvers import get_urlconf, get_resolver, NoReverseMatch
|
|
||||||
from django.db import models
|
|
||||||
|
|
||||||
from djangorestframework.response import ErrorResponse
|
from djangorestframework.response import ErrorResponse
|
||||||
from djangorestframework.reverse import reverse
|
from djangorestframework.serializer import Serializer
|
||||||
from djangorestframework.serializer import Serializer, _SkipField
|
|
||||||
from djangorestframework.utils import as_tuple
|
from djangorestframework.utils import as_tuple
|
||||||
|
|
||||||
|
|
||||||
|
@ -20,7 +17,7 @@ class BaseResource(Serializer):
|
||||||
def __init__(self, view=None, depth=None, stack=[], **kwargs):
|
def __init__(self, view=None, depth=None, stack=[], **kwargs):
|
||||||
super(BaseResource, self).__init__(depth, stack, **kwargs)
|
super(BaseResource, self).__init__(depth, stack, **kwargs)
|
||||||
self.view = view
|
self.view = view
|
||||||
self.request = view.request
|
self.request = getattr(view, 'request', None)
|
||||||
|
|
||||||
def validate_request(self, data, files=None):
|
def validate_request(self, data, files=None):
|
||||||
"""
|
"""
|
||||||
|
@ -224,9 +221,6 @@ class ModelResource(FormResource):
|
||||||
Also provides a :meth:`get_bound_form` method which may be used by some renderers.
|
Also provides a :meth:`get_bound_form` method which may be used by some renderers.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Auto-register new ModelResource classes into _model_to_resource
|
|
||||||
#__metaclass__ = _RegisterModelResource
|
|
||||||
|
|
||||||
form = None
|
form = None
|
||||||
"""
|
"""
|
||||||
The form class that should be used for request validation.
|
The form class that should be used for request validation.
|
||||||
|
@ -260,7 +254,7 @@ class ModelResource(FormResource):
|
||||||
The list of fields to exclude. This is only used if :attr:`fields` is not set.
|
The list of fields to exclude. This is only used if :attr:`fields` is not set.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
include = ('url',)
|
include = ()
|
||||||
"""
|
"""
|
||||||
The list of extra fields to include. This is only used if :attr:`fields` is not set.
|
The list of extra fields to include. This is only used if :attr:`fields` is not set.
|
||||||
"""
|
"""
|
||||||
|
@ -323,49 +317,6 @@ class ModelResource(FormResource):
|
||||||
|
|
||||||
return form()
|
return form()
|
||||||
|
|
||||||
def url(self, instance):
|
|
||||||
"""
|
|
||||||
Attempts to reverse resolve the url of the given model *instance* for this resource.
|
|
||||||
|
|
||||||
Requires a ``View`` with :class:`mixins.InstanceMixin` to have been created for this resource.
|
|
||||||
|
|
||||||
This method can be overridden if you need to set the resource url reversing explicitly.
|
|
||||||
"""
|
|
||||||
|
|
||||||
if not hasattr(self, 'view_callable'):
|
|
||||||
raise _SkipField
|
|
||||||
|
|
||||||
# dis does teh magicks...
|
|
||||||
urlconf = get_urlconf()
|
|
||||||
resolver = get_resolver(urlconf)
|
|
||||||
|
|
||||||
possibilities = resolver.reverse_dict.getlist(self.view_callable[0])
|
|
||||||
for tuple_item in possibilities:
|
|
||||||
possibility = tuple_item[0]
|
|
||||||
# pattern = tuple_item[1]
|
|
||||||
# Note: defaults = tuple_item[2] for django >= 1.3
|
|
||||||
for result, params in possibility:
|
|
||||||
|
|
||||||
#instance_attrs = dict([ (param, getattr(instance, param)) for param in params if hasattr(instance, param) ])
|
|
||||||
|
|
||||||
instance_attrs = {}
|
|
||||||
for param in params:
|
|
||||||
if not hasattr(instance, param):
|
|
||||||
continue
|
|
||||||
attr = getattr(instance, param)
|
|
||||||
if isinstance(attr, models.Model):
|
|
||||||
instance_attrs[param] = attr.pk
|
|
||||||
else:
|
|
||||||
instance_attrs[param] = attr
|
|
||||||
|
|
||||||
try:
|
|
||||||
return reverse(self.view_callable[0],
|
|
||||||
kwargs=instance_attrs,
|
|
||||||
request=self.view.request)
|
|
||||||
except NoReverseMatch:
|
|
||||||
pass
|
|
||||||
raise _SkipField
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def _model_fields_set(self):
|
def _model_fields_set(self):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -5,7 +5,7 @@ from django.core.urlresolvers import reverse as django_reverse
|
||||||
from django.utils.functional import lazy
|
from django.utils.functional import lazy
|
||||||
|
|
||||||
|
|
||||||
def reverse(viewname, request, *args, **kwargs):
|
def reverse(viewname, *args, **kwargs):
|
||||||
"""
|
"""
|
||||||
Same as `django.core.urlresolvers.reverse`, but optionally takes a request
|
Same as `django.core.urlresolvers.reverse`, but optionally takes a request
|
||||||
and returns a fully qualified URL, using the request to get the base URL.
|
and returns a fully qualified URL, using the request to get the base URL.
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
from django.conf.urls.defaults import patterns, url
|
from django.conf.urls.defaults import patterns, url
|
||||||
from django.test import TestCase
|
|
||||||
from django.forms import ModelForm
|
from django.forms import ModelForm
|
||||||
from django.contrib.auth.models import Group, User
|
from django.contrib.auth.models import Group, User
|
||||||
from djangorestframework.resources import ModelResource
|
from djangorestframework.resources import ModelResource
|
||||||
|
@ -7,18 +6,22 @@ from djangorestframework.views import ListOrCreateModelView, InstanceModelView
|
||||||
from djangorestframework.tests.models import CustomUser
|
from djangorestframework.tests.models import CustomUser
|
||||||
from djangorestframework.tests.testcases import TestModelsTestCase
|
from djangorestframework.tests.testcases import TestModelsTestCase
|
||||||
|
|
||||||
|
|
||||||
class GroupResource(ModelResource):
|
class GroupResource(ModelResource):
|
||||||
model = Group
|
model = Group
|
||||||
|
|
||||||
|
|
||||||
class UserForm(ModelForm):
|
class UserForm(ModelForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = User
|
model = User
|
||||||
exclude = ('last_login', 'date_joined')
|
exclude = ('last_login', 'date_joined')
|
||||||
|
|
||||||
|
|
||||||
class UserResource(ModelResource):
|
class UserResource(ModelResource):
|
||||||
model = User
|
model = User
|
||||||
form = UserForm
|
form = UserForm
|
||||||
|
|
||||||
|
|
||||||
class CustomUserResource(ModelResource):
|
class CustomUserResource(ModelResource):
|
||||||
model = CustomUser
|
model = CustomUser
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,6 @@ By setting or modifying class attributes on your view, you change it's predefine
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import re
|
import re
|
||||||
from django.core.urlresolvers import set_script_prefix, get_script_prefix
|
|
||||||
from django.http import HttpResponse
|
from django.http import HttpResponse
|
||||||
from django.utils.html import escape
|
from django.utils.html import escape
|
||||||
from django.utils.safestring import mark_safe
|
from django.utils.safestring import mark_safe
|
||||||
|
@ -269,7 +268,7 @@ class ModelView(View):
|
||||||
resource = resources.ModelResource
|
resource = resources.ModelResource
|
||||||
|
|
||||||
|
|
||||||
class InstanceModelView(InstanceMixin, ReadModelMixin, UpdateModelMixin, DeleteModelMixin, ModelView):
|
class InstanceModelView(ReadModelMixin, UpdateModelMixin, DeleteModelMixin, ModelView):
|
||||||
"""
|
"""
|
||||||
A view which provides default operations for read/update/delete against a model instance.
|
A view which provides default operations for read/update/delete against a model instance.
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -2,6 +2,7 @@ from django.db import models
|
||||||
from django.template.defaultfilters import slugify
|
from django.template.defaultfilters import slugify
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
|
|
||||||
def uuid_str():
|
def uuid_str():
|
||||||
return str(uuid.uuid1())
|
return str(uuid.uuid1())
|
||||||
|
|
||||||
|
@ -14,6 +15,7 @@ RATING_CHOICES = ((0, 'Awful'),
|
||||||
|
|
||||||
MAX_POSTS = 10
|
MAX_POSTS = 10
|
||||||
|
|
||||||
|
|
||||||
class BlogPost(models.Model):
|
class BlogPost(models.Model):
|
||||||
key = models.CharField(primary_key=True, max_length=64, default=uuid_str, editable=False)
|
key = models.CharField(primary_key=True, max_length=64, default=uuid_str, editable=False)
|
||||||
title = models.CharField(max_length=128)
|
title = models.CharField(max_length=128)
|
||||||
|
@ -37,4 +39,3 @@ class Comment(models.Model):
|
||||||
comment = models.TextField()
|
comment = models.TextField()
|
||||||
rating = models.IntegerField(blank=True, null=True, choices=RATING_CHOICES, help_text='How did you rate this post?')
|
rating = models.IntegerField(blank=True, null=True, choices=RATING_CHOICES, help_text='How did you rate this post?')
|
||||||
created = models.DateTimeField(auto_now_add=True)
|
created = models.DateTimeField(auto_now_add=True)
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,11 @@ class BlogPostResource(ModelResource):
|
||||||
fields = ('created', 'title', 'slug', 'content', 'url', 'comments')
|
fields = ('created', 'title', 'slug', 'content', 'url', 'comments')
|
||||||
ordering = ('-created',)
|
ordering = ('-created',)
|
||||||
|
|
||||||
|
def url(self, instance):
|
||||||
|
return reverse('blog-post',
|
||||||
|
kwargs={'key': instance.key},
|
||||||
|
request=self.request)
|
||||||
|
|
||||||
def comments(self, instance):
|
def comments(self, instance):
|
||||||
return reverse('comments',
|
return reverse('comments',
|
||||||
kwargs={'blogpost': instance.key},
|
kwargs={'blogpost': instance.key},
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
from djangorestframework.resources import ModelResource
|
from djangorestframework.resources import ModelResource
|
||||||
|
from djangorestframework.reverse import reverse
|
||||||
from modelresourceexample.models import MyModel
|
from modelresourceexample.models import MyModel
|
||||||
|
|
||||||
|
|
||||||
|
@ -6,3 +7,8 @@ class MyModelResource(ModelResource):
|
||||||
model = MyModel
|
model = MyModel
|
||||||
fields = ('foo', 'bar', 'baz', 'url')
|
fields = ('foo', 'bar', 'baz', 'url')
|
||||||
ordering = ('created',)
|
ordering = ('created',)
|
||||||
|
|
||||||
|
def url(self, instance):
|
||||||
|
return reverse('model-resource-instance',
|
||||||
|
kwargs={'id': instance.id},
|
||||||
|
request=self.request)
|
||||||
|
|
|
@ -2,7 +2,10 @@ from django.conf.urls.defaults import patterns, url
|
||||||
from djangorestframework.views import ListOrCreateModelView, InstanceModelView
|
from djangorestframework.views import ListOrCreateModelView, InstanceModelView
|
||||||
from modelresourceexample.resources import MyModelResource
|
from modelresourceexample.resources import MyModelResource
|
||||||
|
|
||||||
|
my_model_list = ListOrCreateModelView.as_view(resource=MyModelResource)
|
||||||
|
my_model_instance = InstanceModelView.as_view(resource=MyModelResource)
|
||||||
|
|
||||||
urlpatterns = patterns('',
|
urlpatterns = patterns('',
|
||||||
url(r'^$', ListOrCreateModelView.as_view(resource=MyModelResource), name='model-resource-root'),
|
url(r'^$', my_model_list, name='model-resource-root'),
|
||||||
url(r'^(?P<id>[0-9]+)/$', InstanceModelView.as_view(resource=MyModelResource), name='model-resource-instance'),
|
url(r'^(?P<id>[0-9]+)/$', my_model_instance, name='model-resource-instance'),
|
||||||
)
|
)
|
||||||
|
|
|
@ -15,7 +15,11 @@ class ExampleView(View):
|
||||||
"""
|
"""
|
||||||
Handle GET requests, returning a list of URLs pointing to 3 other views.
|
Handle GET requests, returning a list of URLs pointing to 3 other views.
|
||||||
"""
|
"""
|
||||||
return {"Some other resources": [reverse('another-example', kwargs={'num':num}, request=request) for num in range(3)]}
|
resource_urls = [reverse('another-example',
|
||||||
|
kwargs={'num': num},
|
||||||
|
request=request)
|
||||||
|
for num in range(3)]
|
||||||
|
return {"Some other resources": resource_urls}
|
||||||
|
|
||||||
|
|
||||||
class AnotherExampleView(View):
|
class AnotherExampleView(View):
|
||||||
|
|
Loading…
Reference in New Issue
Block a user