mirror of
https://github.com/encode/django-rest-framework.git
synced 2024-11-25 19:14:01 +03:00
Remove InstanceMixin auto-url magicks.
This commit is contained in:
parent
2b59df004a
commit
e15494a172
|
@ -25,14 +25,13 @@ __all__ = (
|
|||
'ResponseMixin',
|
||||
'AuthMixin',
|
||||
'ResourceMixin',
|
||||
# Reverse URL lookup behavior
|
||||
'InstanceMixin',
|
||||
# Model behavior mixins
|
||||
'ReadModelMixin',
|
||||
'CreateModelMixin',
|
||||
'UpdateModelMixin',
|
||||
'DeleteModelMixin',
|
||||
'ListModelMixin'
|
||||
'ListModelMixin',
|
||||
'PaginatorMixin'
|
||||
)
|
||||
|
||||
|
||||
|
@ -444,30 +443,6 @@ class ResourceMixin(object):
|
|||
else:
|
||||
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 ##########
|
||||
|
||||
|
@ -599,7 +574,7 @@ class CreateModelMixin(ModelMixin):
|
|||
manager.through(**data).save()
|
||||
|
||||
headers = {}
|
||||
if hasattr(instance, 'get_absolute_url'):
|
||||
if hasattr(self.resource, 'url'):
|
||||
headers['Location'] = self.resource(self).url(instance)
|
||||
return Response(status.HTTP_201_CREATED, instance, headers)
|
||||
|
||||
|
|
|
@ -1,10 +1,7 @@
|
|||
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.reverse import reverse
|
||||
from djangorestframework.serializer import Serializer, _SkipField
|
||||
from djangorestframework.serializer import Serializer
|
||||
from djangorestframework.utils import as_tuple
|
||||
|
||||
|
||||
|
@ -20,7 +17,7 @@ class BaseResource(Serializer):
|
|||
def __init__(self, view=None, depth=None, stack=[], **kwargs):
|
||||
super(BaseResource, self).__init__(depth, stack, **kwargs)
|
||||
self.view = view
|
||||
self.request = view.request
|
||||
self.request = getattr(view, 'request', 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.
|
||||
"""
|
||||
|
||||
# Auto-register new ModelResource classes into _model_to_resource
|
||||
#__metaclass__ = _RegisterModelResource
|
||||
|
||||
form = None
|
||||
"""
|
||||
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.
|
||||
"""
|
||||
|
||||
include = ('url',)
|
||||
include = ()
|
||||
"""
|
||||
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()
|
||||
|
||||
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
|
||||
def _model_fields_set(self):
|
||||
"""
|
||||
|
|
|
@ -5,7 +5,7 @@ from django.core.urlresolvers import reverse as django_reverse
|
|||
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
|
||||
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.test import TestCase
|
||||
from django.forms import ModelForm
|
||||
from django.contrib.auth.models import Group, User
|
||||
from djangorestframework.resources import ModelResource
|
||||
|
@ -7,18 +6,22 @@ from djangorestframework.views import ListOrCreateModelView, InstanceModelView
|
|||
from djangorestframework.tests.models import CustomUser
|
||||
from djangorestframework.tests.testcases import TestModelsTestCase
|
||||
|
||||
|
||||
class GroupResource(ModelResource):
|
||||
model = Group
|
||||
|
||||
|
||||
class UserForm(ModelForm):
|
||||
class Meta:
|
||||
model = User
|
||||
exclude = ('last_login', 'date_joined')
|
||||
|
||||
|
||||
class UserResource(ModelResource):
|
||||
model = User
|
||||
form = UserForm
|
||||
|
||||
|
||||
class CustomUserResource(ModelResource):
|
||||
model = CustomUser
|
||||
|
||||
|
|
|
@ -6,7 +6,6 @@ By setting or modifying class attributes on your view, you change it's predefine
|
|||
"""
|
||||
|
||||
import re
|
||||
from django.core.urlresolvers import set_script_prefix, get_script_prefix
|
||||
from django.http import HttpResponse
|
||||
from django.utils.html import escape
|
||||
from django.utils.safestring import mark_safe
|
||||
|
@ -269,7 +268,7 @@ class ModelView(View):
|
|||
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.
|
||||
"""
|
||||
|
|
|
@ -2,6 +2,7 @@ from django.db import models
|
|||
from django.template.defaultfilters import slugify
|
||||
import uuid
|
||||
|
||||
|
||||
def uuid_str():
|
||||
return str(uuid.uuid1())
|
||||
|
||||
|
@ -14,6 +15,7 @@ RATING_CHOICES = ((0, 'Awful'),
|
|||
|
||||
MAX_POSTS = 10
|
||||
|
||||
|
||||
class BlogPost(models.Model):
|
||||
key = models.CharField(primary_key=True, max_length=64, default=uuid_str, editable=False)
|
||||
title = models.CharField(max_length=128)
|
||||
|
@ -37,4 +39,3 @@ class Comment(models.Model):
|
|||
comment = models.TextField()
|
||||
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)
|
||||
|
||||
|
|
|
@ -11,6 +11,11 @@ class BlogPostResource(ModelResource):
|
|||
fields = ('created', 'title', 'slug', 'content', 'url', 'comments')
|
||||
ordering = ('-created',)
|
||||
|
||||
def url(self, instance):
|
||||
return reverse('blog-post',
|
||||
kwargs={'key': instance.key},
|
||||
request=self.request)
|
||||
|
||||
def comments(self, instance):
|
||||
return reverse('comments',
|
||||
kwargs={'blogpost': instance.key},
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
from djangorestframework.resources import ModelResource
|
||||
from djangorestframework.reverse import reverse
|
||||
from modelresourceexample.models import MyModel
|
||||
|
||||
|
||||
|
@ -6,3 +7,8 @@ class MyModelResource(ModelResource):
|
|||
model = MyModel
|
||||
fields = ('foo', 'bar', 'baz', 'url')
|
||||
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 modelresourceexample.resources import MyModelResource
|
||||
|
||||
my_model_list = ListOrCreateModelView.as_view(resource=MyModelResource)
|
||||
my_model_instance = InstanceModelView.as_view(resource=MyModelResource)
|
||||
|
||||
urlpatterns = patterns('',
|
||||
url(r'^$', ListOrCreateModelView.as_view(resource=MyModelResource), name='model-resource-root'),
|
||||
url(r'^(?P<id>[0-9]+)/$', InstanceModelView.as_view(resource=MyModelResource), name='model-resource-instance'),
|
||||
url(r'^$', my_model_list, name='model-resource-root'),
|
||||
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.
|
||||
"""
|
||||
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):
|
||||
|
|
Loading…
Reference in New Issue
Block a user