mirror of
https://github.com/pinry/pinry.git
synced 2026-01-26 17:19:23 +01:00
Use django-braces for CBV Mixins like LoginRequiredMixin
This commit is contained in:
37
pinry/pins/tests.py
Normal file
37
pinry/pins/tests.py
Normal 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)
|
||||
@@ -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'),
|
||||
|
||||
@@ -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!'})
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user