From 9a62a9dbd48e45fb634022273b50ac5d2154a994 Mon Sep 17 00:00:00 2001 From: Graham Ullrich Date: Wed, 21 Feb 2018 15:51:39 -0700 Subject: [PATCH 1/2] Update guidance for pinax-images usage Clarify `pinax-images` requirement, verify usage in tests. Fix form initialization error. Add django-test-plus testing dependency. Update testing configuration for view tests and authentication. --- README.md | 37 ++++++++++++++- pinax/blog/forms.py | 24 +++++----- pinax/blog/tests/templates/site_base.html | 9 ++++ pinax/blog/tests/tests.py | 55 +++++++++++++++++++---- pinax/blog/tests/urls.py | 1 + runtests.py | 19 +++++++- setup.py | 11 +++-- 7 files changed, 128 insertions(+), 28 deletions(-) create mode 100644 pinax/blog/tests/templates/site_base.html diff --git a/README.md b/README.md index 460a4ed..41b7ad8 100644 --- a/README.md +++ b/README.md @@ -92,12 +92,13 @@ To install pinax-blog: $ pip install pinax-blog ``` -Add `pinax.blog` to your `INSTALLED_APPS` setting: +Add `pinax.blog` and dependency `pinax.images` to your `INSTALLED_APPS` setting: ```python INSTALLED_APPS = [ # other apps "pinax.blog", + "pinax.images", ] ``` @@ -110,7 +111,35 @@ Add `pinax.blog.urls` to your project urlpatterns: ] ``` -Optionally, if you want `creole` support for a mark up choice: +### Optional Requirements + +`pinax-blog` ships with a few management view templates. These templates reference pinax-images +URLs for adding and viewing images. They also use "bootstrap" formatting. + +In order to use these built-in templates, add `django-bootstrap-form` to your project requirements +and ``"bootstrapform",` to your INSTALLED_APPS: + +```python + INSTALLED_APPS = [ + # other apps + "pinax.blog", + "pinax.images", + "bootstrapform", + ] +``` + +Then add pinax.images.urls` to your project urlpatterns: + +```python + urlpatterns = [ + # other urls + url(r"^blog/", include("pinax.blog.urls", namespace="pinax_blog")), + url(r"^ajax/images/", include("pinax.images.urls", namespace="pinax_images")), + ] +``` + + +If you want `creole` support for mark-up: ```shell $ pip install creole @@ -363,6 +392,10 @@ Both templates ship already configured to work out of the box. ## Change Log +### 7.0.2 + +* Restore and improve documentation guidance for pinax-images usage + ### 7.0.1 * Replace pinax-theme-bootstrap test dependency with pinax-templates diff --git a/pinax/blog/forms.py b/pinax/blog/forms.py index b83717e..9aad071 100644 --- a/pinax/blog/forms.py +++ b/pinax/blog/forms.py @@ -120,13 +120,24 @@ class PostForm(PostFormMixin, forms.ModelForm): teaser = forms.CharField(widget=forms.Textarea()) content = forms.CharField(widget=forms.Textarea()) + class Meta: + model = Post + fields = [ + "section", + "title", + "teaser", + "content", + "description", + "state" + ] + def __init__(self, *args, **kwargs): super(PostForm, self).__init__(*args, **kwargs) if Section.objects.count() < 2: self.section = Section.objects.first() del self.fields["section"] else: - self.section is None + self.section = None def save(self, blog=None, author=None): post = super(PostForm, self).save(commit=False) @@ -140,14 +151,3 @@ def save(self, blog=None, author=None): post.slug = slugify(post.title) post.markup = self.markup_choice return self.save_post(post) - - class Meta: - model = Post - fields = [ - "section", - "title", - "teaser", - "content", - "description", - "state" - ] diff --git a/pinax/blog/tests/templates/site_base.html b/pinax/blog/tests/templates/site_base.html new file mode 100644 index 0000000..416269b --- /dev/null +++ b/pinax/blog/tests/templates/site_base.html @@ -0,0 +1,9 @@ +
+{% block head_title %} +Title +{% endblock %} +
+
+{% block body %} +{% endblock %} +
\ No newline at end of file diff --git a/pinax/blog/tests/tests.py b/pinax/blog/tests/tests.py index 978b667..676d0c6 100644 --- a/pinax/blog/tests/tests.py +++ b/pinax/blog/tests/tests.py @@ -2,13 +2,13 @@ import random -from django.contrib.auth import get_user_model from django.core.exceptions import ValidationError from django.http.request import HttpRequest -from django.test import TestCase from django.urls import reverse from django.utils.text import slugify +from test_plus import TestCase + from ..context_processors import scoped from ..models import Blog, Post, Section @@ -29,12 +29,7 @@ def setUp(self): self.apples = Section.objects.create(name="Apples", slug="apples") self.oranges = Section.objects.create(name="Oranges", slug="oranges") - self.password = "eldarion" - self.user = get_user_model().objects.create_user( - username="patrick", - password=self.password - ) - self.user.save() + self.user = self.make_user("patrick") self.markup = "markdown" # Create two published Posts, one in each section. @@ -68,7 +63,7 @@ def test_invalid_section_slug(self): invalid_slug = "bananas" url = reverse("pinax_blog:blog_section", kwargs={"section": invalid_slug}) try: - response = self.client.get(url) + response = self.get(url) except Section.DoesNotExist: self.fail("section '{}' does not exist".format(invalid_slug)) self.assertEqual(response.status_code, 404) @@ -140,3 +135,45 @@ def test_no_resolver_match(self): self.assertEqual(request.resolver_match, None) result = scoped(request) self.assertEqual(result, {"scoper_lookup": ""}) + + +class TestViews(TestBlog): + + def test_manage_post_create_get(self): + """ + Ensure template with external URL references renders properly + for user with proper credentials. + """ + with self.login(self.user): + response = self.client.get("pinax_blog:manage_post_create") + self.assertEqual(response.status_code, 404) + + self.user.is_staff = True + self.user.save() + with self.login(self.user): + self.get("pinax_blog:manage_post_create") + self.response_200() + self.assertTemplateUsed("pinax/blog/manage_post_create") + pinax_images_upload_url = reverse("pinax_images:imageset_new_upload") + self.assertResponseContains(pinax_images_upload_url, html=False) + + def test_manage_post_create_post(self): + """ + Ensure template with external URL references renders properly + for user with proper credentials. + """ + self.user.is_staff = True + self.user.save() + post_title = "You'll never believe what happened next!" + post_data = dict( + section=self.apples.pk, + title=post_title, + teaser="teaser", + content="content", + description="description", + state=Post.STATE_CHOICES[-1][0], + ) + with self.login(self.user): + self.post("pinax_blog:manage_post_create", data=post_data) + self.assertRedirects(self.last_response, reverse("pinax_blog:manage_post_list")) + self.assertTrue(Post.objects.get(title=post_title)) diff --git a/pinax/blog/tests/urls.py b/pinax/blog/tests/urls.py index 8e86b76..3bebd0b 100644 --- a/pinax/blog/tests/urls.py +++ b/pinax/blog/tests/urls.py @@ -2,4 +2,5 @@ urlpatterns = [ url(r"^", include("pinax.blog.urls", namespace="pinax_blog")), + url(r"^ajax/images/", include("pinax.images.urls", namespace="pinax_images")), ] diff --git a/runtests.py b/runtests.py index a2e0d44..18669ee 100644 --- a/runtests.py +++ b/runtests.py @@ -12,12 +12,19 @@ INSTALLED_APPS=[ "django.contrib.auth", "django.contrib.contenttypes", + "django.contrib.sessions", "django.contrib.sites", - "pinax.images", + + "bootstrapform", "pinax.blog", "pinax.blog.tests", + "pinax.images", "pinax.templates", ], + MIDDLEWARE=[ + "django.contrib.sessions.middleware.SessionMiddleware", + "django.contrib.auth.middleware.AuthenticationMiddleware", + ], DATABASES={ "default": { "ENGINE": "django.db.backends.sqlite3", @@ -30,11 +37,21 @@ TEMPLATES=[ { "BACKEND": "django.template.backends.django.DjangoTemplates", + "DIRS": [ + os.path.join(PACKAGE_ROOT, "templates"), + ], "APP_DIRS": True, "OPTIONS": { "debug": True, "context_processors": [ "django.contrib.auth.context_processors.auth", + "django.template.context_processors.debug", + "django.template.context_processors.i18n", + "django.template.context_processors.media", + "django.template.context_processors.static", + "django.template.context_processors.tz", + "django.template.context_processors.request", + "django.contrib.messages.context_processors.messages", ] } }, diff --git a/setup.py b/setup.py index 182681a..8943a6c 100644 --- a/setup.py +++ b/setup.py @@ -1,6 +1,6 @@ from setuptools import find_packages, setup -VERSION = "7.0.1" +VERSION = "7.0.2" LONG_DESCRIPTION = """ .. image:: http://pinaxproject.com/pinax-design/patches/pinax-blog.svg :target: https://pypi.python.org/pypi/pinax-blog/ @@ -97,13 +97,16 @@ install_requires=[ "django>=1.11", "django-appconf>=1.0.1", + "markdown>=2.6.5", + "pillow>=3.0.0", "pinax-images>=3.0.1", + "pygments>=2.0.2", "pytz>=2016.6.1", - "Pillow>=3.0.0", - "Markdown>=2.6.5", - "Pygments>=2.0.2", ], tests_require=[ + "django-bootstrap-form>=3.0.0", + "django-test-plus>=1.0.22", + "mock>=2.0.0", "pinax-templates>=1.0.0", ], test_suite="runtests.runtests", From 1203e59ba9aee31b548b6bf042a42d209d013b6b Mon Sep 17 00:00:00 2001 From: Graham Ullrich Date: Wed, 21 Feb 2018 16:24:52 -0700 Subject: [PATCH 2/2] Fix syntax highlighting typos --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 41b7ad8..27db66b 100644 --- a/README.md +++ b/README.md @@ -117,7 +117,7 @@ Add `pinax.blog.urls` to your project urlpatterns: URLs for adding and viewing images. They also use "bootstrap" formatting. In order to use these built-in templates, add `django-bootstrap-form` to your project requirements -and ``"bootstrapform",` to your INSTALLED_APPS: +and `"bootstrapform",` to your INSTALLED_APPS: ```python INSTALLED_APPS = [ @@ -128,7 +128,7 @@ and ``"bootstrapform",` to your INSTALLED_APPS: ] ``` -Then add pinax.images.urls` to your project urlpatterns: +Then add `pinax.images.urls` to your project urlpatterns: ```python urlpatterns = [