david / django-modelviews
Backup of an old repository with useful ideas. Initial goal: integrating REST to django admin (class-based views).
Clone this repository (size: 85.8 KB): HTTPS / SSH
$ hg clone http://code.welldev.org/django-modelviews
| commit 39: | 7bb34b38501f |
| parent 38: | 7a46edcc917a |
| branch: | default |
Draft of authentication, still hesitating between dictionaries vs. decorators
2 years ago
Changed (Δ1.0 KB):
raw changeset »
generic/rest_views.py (13 lines added, 3 lines removed)
tests/settings.py (7 lines added, 7 lines removed)
tests/test_modelview/tests.py (14 lines added, 4 lines removed)
tests/urls.py (4 lines added, 0 lines removed)
Up to file-list generic/rest_views.py:
| … | … | @@ -12,6 +12,10 @@ try: |
12 |
12 |
except ImportError: |
13 |
13 |
from compatability import BaseDetailView |
14 |
14 |
|
15 |
def django_authentication(request, **kwargs): |
|
16 |
return request.user.is_authenticated() |
|
17 |
||
18 |
||
15 |
19 |
class BaseResponder(object): |
16 |
20 |
def __init__(self, queryset): |
17 |
21 |
self.queryset = queryset |
| … | … | @@ -314,11 +318,14 @@ class ModelView(BaseDetailView): |
314 |
318 |
self.paginate_by = paginate_by |
315 |
319 |
self.allow_empty = allow_empty |
316 |
320 |
self.responders = dict((responder.__name__, responder) for responder in responders) |
317 |
|
|
321 |
if isinstance(methods, tuple): |
|
322 |
self.methods = dict(zip(methods, len(methods)*(False,))) |
|
323 |
else: |
|
324 |
self.methods = methods |
|
318 |
325 |
super(ModelView, self).__init__(queryset, slug_field) |
319 |
326 |
|
320 |
327 |
|
321 |
def __call__(self, request, object_pk=None, slug=None, format='html' |
|
328 |
def __call__(self, request, object_pk=None, slug=None, format='html', **kwargs): |
|
322 |
329 |
""" |
323 |
330 |
Redirects to one of the CRUD methods depending on the HTTP method of |
324 |
331 |
the request. Checks whether the requested method is allowed for this |
| … | … | @@ -326,8 +333,11 @@ class ModelView(BaseDetailView): |
326 |
333 |
""" |
327 |
334 |
# Restrict |
328 |
335 |
request_method = request.method.upper() |
329 |
if request_method not in self.methods |
|
336 |
if request_method not in self.methods.keys(): |
|
330 |
337 |
return HttpResponseNotAllowed(request_method) |
338 |
if self.methods[request_method]: |
|
339 |
if not self.methods[request_method](request, **kwargs): |
|
340 |
return HttpResponseNotAllowed(request_method) |
|
331 |
341 |
|
332 |
342 |
# Unmatched regex groups in the url will not recieve |
333 |
343 |
# the default value specified for the method, but |
Up to file-list tests/settings.py:
| … | … | @@ -24,9 +24,9 @@ TEMPLATE_LOADERS = ( |
24 |
24 |
) |
25 |
25 |
|
26 |
26 |
MIDDLEWARE_CLASSES = ( |
27 |
# 'django.middleware.common.CommonMiddleware', |
|
28 |
# 'django.contrib.sessions.middleware.SessionMiddleware', |
|
29 |
|
|
27 |
'django.middleware.common.CommonMiddleware', |
|
28 |
'django.contrib.sessions.middleware.SessionMiddleware', |
|
29 |
'django.contrib.auth.middleware.AuthenticationMiddleware', |
|
30 |
30 |
# 'django.middleware.doc.XViewMiddleware', |
31 |
31 |
) |
32 |
32 |
|
| … | … | @@ -39,8 +39,8 @@ TEMPLATE_DIRS = ( |
39 |
39 |
INSTALLED_APPS = ( |
40 |
40 |
'django_modelview.generic', |
41 |
41 |
'django_modelview.tests.test_modelview', |
42 |
# 'django.contrib.auth', |
|
43 |
# 'django.contrib.contenttypes', |
|
44 |
# 'django.contrib.sessions', |
|
45 |
# 'django.contrib.sites', |
|
42 |
'django.contrib.auth', |
|
43 |
'django.contrib.contenttypes', |
|
44 |
'django.contrib.sessions', |
|
45 |
'django.contrib.sites', |
|
46 |
46 |
) |
Up to file-list tests/test_modelview/tests.py:
1 |
1 |
from django.test import TestCase |
2 |
2 |
from models import Article |
3 |
3 |
from django.utils import simplejson |
4 |
from django.contrib.auth.models import User |
|
4 |
5 |
from xml.dom.minidom import parseString |
5 |
6 |
|
6 |
7 |
|
| … | … | @@ -19,7 +20,7 @@ class ModelViewTest(TestCase): |
19 |
20 |
Article.objects.create(name="My Story", |
20 |
21 |
slug="my-story", |
21 |
22 |
body="My thrilling story!") |
22 |
||
23 |
User.objects.create_user('david', 'foo@bar.com', 'baz') |
|
23 |
24 |
|
24 |
25 |
def test_restricting_exposed_methods(self): |
25 |
26 |
""" |
| … | … | @@ -28,9 +29,7 @@ class ModelViewTest(TestCase): |
28 |
29 |
all other http methods. |
29 |
30 |
""" |
30 |
31 |
a = Article.objects.all()[0] |
31 |
response = self.client.post('/articles/', {'name': "Not allowed article", |
|
32 |
'slug': "not-allowed-article", |
|
33 |
|
|
32 |
response = self.client.post('/articles/', {}) |
|
34 |
33 |
self.assertEqual(response.status_code, 405) |
35 |
34 |
# no explicit way to send DELETE or PUT methods, so get |
36 |
35 |
# a bit sneaky here. |
| … | … | @@ -42,6 +41,17 @@ class ModelViewTest(TestCase): |
42 |
41 |
self.assertEqual(response.status_code, 405) |
43 |
42 |
|
44 |
43 |
|
44 |
def test_restricting_authentication(self): |
|
45 |
u = User.objects.all()[0] |
|
46 |
response = self.client.get('/auth-articles/') |
|
47 |
self.assertEqual(response.status_code, 405) |
|
48 |
response = self.client.post('/auth-articles/', {}) |
|
49 |
self.assertEqual(response.status_code, 405) |
|
50 |
response = self.client.login(username='david', password='baz') |
|
51 |
response = self.client.get('/auth-articles/') |
|
52 |
self.assertEqual(response.status_code, 200) |
|
53 |
||
54 |
||
45 |
55 |
def test_default_responder(self): |
46 |
56 |
a = Article.objects.all()[0] |
47 |
57 |
response = self.client.get('/articles/%s/' % a.slug) |
Up to file-list tests/urls.py:
| … | … | @@ -10,6 +10,9 @@ articles = ModelView(Article.objects.all |
10 |
10 |
rw_articles = ModelView(Article.objects.all(), |
11 |
11 |
responders=(HtmlResponder,), |
12 |
12 |
methods=('GET', 'POST', 'PUT', 'DELETE')) |
13 |
auth_articles = ModelView(Article.objects.all(), |
|
14 |
responders=(HtmlResponder,), |
|
15 |
methods={'GET': django_authentication}) |
|
13 |
16 |
|
14 |
17 |
formats = '(?P<format>(html|json|xml|yaml|atom|rss))?/?' |
15 |
18 |
slug = '(?P<slug>[-\w]+)?/?' |
| … | … | @@ -18,4 +21,5 @@ urlpatterns = patterns('', |
18 |
21 |
('^articles/%(formats)s$' % locals(), articles), |
19 |
22 |
('^articles/%(slug)s%(formats)s$' % locals(), articles), |
20 |
23 |
('^rw-articles/%(slug)s$' % locals(), rw_articles), |
24 |
('^auth-articles/%(slug)s$' % locals(), auth_articles), |
|
21 |
25 |
) |
