Use django-braces for CBV Mixins like LoginRequiredMixin

This commit is contained in:
Krzysztof Klimonda
2013-02-26 11:21:13 -08:00
parent 974d2a8720
commit d2727aa12c
4 changed files with 45 additions and 68 deletions

37
pinry/pins/tests.py Normal file
View File

@@ -0,0 +1,37 @@
from django.core.urlresolvers import reverse
from django.test import TestCase
from pinry.core.models import User
class CreateImageTest(TestCase):
fixtures = ['test_resources.json']
def setUp(self):
self.client.login(username='jdoe', password='password')
def test_form_post_unauthenticated(self):
post_data = {
'image': 'foobar.jpg'
}
self.client.logout()
response = self.client.post(reverse('pins:new-pin'), data=post_data)
expected_url = '{login_url}?next={next_url}'.format(**{
'login_url': reverse('core:login'),
'next_url': reverse('pins:new-pin')
})
self.assertRedirects(response, expected_url=expected_url)
def test_form_post_browser(self):
post_data = {
'image': 'foobar.jpg'
}
response = self.client.post(reverse('pins:new-pin'), data=post_data)
self.assertEqual(response.status_code, 200)
def test_form_post_ajax(self):
post_data = {
'image': 'foobar.jpg'
}
response = self.client.post(reverse('pins:new-pin'), data=post_data, HTTP_X_REQUESTED_WITH='XMLHttpRequest')
self.assertEqual(response.status_code, 200)

View File

@@ -1,11 +1,11 @@
from django.conf.urls import patterns, url
from django.views.generic import TemplateView
from .views import UploadImage
from .views import CreateImage
urlpatterns = patterns('pinry.pins.views',
url(r'^upload-pin/$', UploadImage.as_view(), name='new-pin'),
url(r'^upload-pin/$', CreateImage.as_view(), name='new-pin'),
url(r'^$', TemplateView.as_view(template_name='core/pins.html'),
name='recent-pins'),
url(r'^tag/(?P<tag>(\w|-)+)/$', TemplateView.as_view(template_name='core/pins.html'),

View File

@@ -5,82 +5,21 @@ from django.contrib.auth.decorators import login_required
from django.contrib import messages
from django.http import HttpResponse
from django.utils.decorators import method_decorator
from django.utils.functional import lazy
from django.views.generic import CreateView
from braces.views import LoginRequiredMixin, JSONResponseMixin
from django_images.models import Image
from .forms import ImageForm
class LoginRequiredMixin(object):
"""
A login required mixin for use with class based views. This Class is a light wrapper around the
`login_required` decorator and hence function parameters are just attributes defined on the class.
Due to parent class order traversal this mixin must be added as the left most
mixin of a view.
The mixin has exactly the same flow as `login_required` decorator:
If the user isn't logged in, redirect to settings.LOGIN_URL, passing the current
absolute path in the query string. Example: /accounts/login/?next=/polls/3/.
If the user is logged in, execute the view normally. The view code is free to
assume the user is logged in.
**Class Settings**
`redirect_field_name - defaults to "next"
`login_url` - the login url of your site
"""
redirect_field_name = REDIRECT_FIELD_NAME
login_url = None
@method_decorator(login_required(redirect_field_name=redirect_field_name, login_url=login_url))
def dispatch(self, request, *args, **kwargs):
return super(LoginRequiredMixin, self).dispatch(request, *args, **kwargs)
class JSONResponseMixin(object):
"""
A mixin that can be used to render a JSON response.
"""
def render_to_response(self, context, **response_kwargs):
"""
Returns a JSON response, transforming 'context' to make the payload.
"""
response_kwargs['content_type'] = 'application/json'
return HttpResponse(
self.convert_context_to_json(context),
**response_kwargs
)
def convert_context_to_json(self, context):
"""Convert the context dictionary into a JSON object"""
return json.dumps(context)
class UploadImage(JSONResponseMixin, LoginRequiredMixin, CreateView):
template_name = 'core/pin_form.html'
class CreateImage(JSONResponseMixin, LoginRequiredMixin, CreateView):
template_name = None # JavaScript-only view
model = Image
form_class = ImageForm
def form_valid(self, form):
message = 'New pin successfully added.'
if self.request.is_ajax():
self.object = form.save()
context = {'image_id': self.object.pk}
return JSONResponseMixin.render_to_response(self, context)
else:
messages.success(self.request, message)
return super(UploadImage, self).form_valid(form)
return self.render_json_response({'image_id': self.object.pk})
def form_invalid(self, form):
message = 'Pin did not pass validation!'
if self.request.is_ajax():
context = {'error': message}
return JSONResponseMixin.render_to_response(self, context)
else:
messages.error(self.request, message)
return super(UploadImage, self).form_invalid(form)
return self.render_json_response({'error': 'Error message goes here!'})

View File

@@ -2,5 +2,6 @@ http://github.com/django/django/tarball/stable/1.5.x#egg=Django
Pillow
South
django-tastypie
django-braces
django-images
http://github.com/hcarvalhoalves/django-taggit/tarball/master#egg=django-taggit