diff --git a/pinry/pins/tests.py b/pinry/pins/tests.py new file mode 100644 index 0000000..69faeeb --- /dev/null +++ b/pinry/pins/tests.py @@ -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) \ No newline at end of file diff --git a/pinry/pins/urls.py b/pinry/pins/urls.py index 1848b91..e548b39 100644 --- a/pinry/pins/urls.py +++ b/pinry/pins/urls.py @@ -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(\w|-)+)/$', TemplateView.as_view(template_name='core/pins.html'), diff --git a/pinry/pins/views.py b/pinry/pins/views.py index 21779c4..b70ad36 100644 --- a/pinry/pins/views.py +++ b/pinry/pins/views.py @@ -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!'}) diff --git a/requirements.txt b/requirements.txt index df2ee29..76f450a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -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