]> gitweb.fperrin.net Git - djsite.git/commitdiff
Create an administrative interface
authorFrédéric Perrin <frederic.perrin@resel.fr>
Wed, 9 Nov 2016 23:59:50 +0000 (23:59 +0000)
committerFrédéric Perrin <frederic.perrin@resel.fr>
Wed, 9 Nov 2016 23:59:50 +0000 (23:59 +0000)
djsite/urls.py
quotes/adminviews.py [new file with mode: 0644]
quotes/conftest.py
quotes/templates/quotes/listadmintools.html [new file with mode: 0644]
quotes/test_massimport.py
quotes/urls.py
quotes/views.py

index 3ffc7fc3ead6c0fc2bc47494fc1d2819be687c24..6eaff7d92d754dc9fd16ae942fd134ea1ef15cfe 100644 (file)
@@ -17,7 +17,7 @@ from django.conf.urls import include, url
 from django.contrib import admin
 
 urlpatterns = [
 from django.contrib import admin
 
 urlpatterns = [
-    url(r'^admin/', include(admin.site.urls)),
+    url(r'^cntrl/', include(admin.site.urls)),
     url(r'^tinymce/', include('tinymce.urls')),
     url(r'^quotes/', include('quotes.urls', namespace='quotes')),
 ]
     url(r'^tinymce/', include('tinymce.urls')),
     url(r'^quotes/', include('quotes.urls', namespace='quotes')),
 ]
diff --git a/quotes/adminviews.py b/quotes/adminviews.py
new file mode 100644 (file)
index 0000000..757418c
--- /dev/null
@@ -0,0 +1,19 @@
+from django.shortcuts import render
+from django.contrib.auth.decorators import permission_required
+
+from quotes.massimport import domassimport
+
+check_admin = permission_required('quotes.can_add',
+                                  login_url='/quotes/admin/login')
+
+@check_admin
+def massimport(request):
+    if 'quotes' in request.POST:
+        resultcontext = domassimport(request.POST['quotes'])
+        return render(request, 'quotes/domassimport.html', resultcontext)
+    else:
+        return render(request, 'quotes/massimport.html', {})
+
+@check_admin
+def listadmintools(request):
+    return render(request, 'quotes/listadmintools.html', {})
index 5cdf30a8431f17093e24322ca3e8ba8892103adb..b87a6baf2a756894143ec20c6f2db398144f8f01 100644 (file)
@@ -17,18 +17,24 @@ class ValidatingClient(object):
         else:
             raise RuntimeError('Unknown method %s for %s' % (method, url))
         assert response.status_code == exp_status
         else:
             raise RuntimeError('Unknown method %s for %s' % (method, url))
         assert response.status_code == exp_status
+        if response.status_code != 200:
+            return None
         assert response.charset == 'utf-8'
         document = response.content.decode(response.charset)
         lxml.etree.fromstring(document)
         assert '<script>' not in document
         return document
 
         assert response.charset == 'utf-8'
         document = response.content.decode(response.charset)
         lxml.etree.fromstring(document)
         assert '<script>' not in document
         return document
 
-    def getPage(self, url):
-        return self.request(url, 'get')
+    def getPage(self, url, exp_status=200):
+        return self.request(url, 'get', exp_status=exp_status)
 
 
-    def postPage(self, url, params):
-        return self.request(url, 'post', params=params)
+    def postPage(self, url, params, exp_status=200):
+        return self.request(url, 'post', params=params, exp_status=exp_status)
 
 @pytest.fixture
 def c(client):
     return ValidatingClient(client)
 
 @pytest.fixture
 def c(client):
     return ValidatingClient(client)
+
+@pytest.fixture
+def c_adm(admin_client):
+    return ValidatingClient(admin_client)
diff --git a/quotes/templates/quotes/listadmintools.html b/quotes/templates/quotes/listadmintools.html
new file mode 100644 (file)
index 0000000..a114110
--- /dev/null
@@ -0,0 +1,15 @@
+{% extends 'quotes/base.html' %}
+
+{% block title %}Administration tools{% endblock %}
+
+{% block body %}
+
+<p>Available administration tools:</p>
+
+<ul>
+  <li><a href="/cntrl/quotes/">Manage individual quotes</a>, in
+    particular add and edit single quotes</li>
+  <li><a href="/quotes/admin/massimport/">Import many quotes at once</a></li>
+</ul>
+
+{% endblock %}
index 0a9fb4f70fafe6ea0ceb622b59f4904ae4dcfb81..fb5ea368aca5f93de9d033cbd5e7a87d4995ac57 100644 (file)
@@ -11,7 +11,7 @@ class Test_MassImport():
         return q1
 
     @pytest.mark.django_db
         return q1
 
     @pytest.mark.django_db
-    def test_massimport_1(self, q1, c):
+    def test_massimport_1(self, q1, c_adm):
         allquotes = """\
 Ich bin ein Berliner
 ---
         allquotes = """\
 Ich bin ein Berliner
 ---
@@ -42,7 +42,7 @@ Romeo and Juliet
 tag1, tag555
 ==="""
 
 tag1, tag555
 ==="""
 
-        results = c.postPage('massimport/', {'quotes': allquotes})
+        results = c_adm.postPage('massimport/', {'quotes': allquotes})
 
         assert "rejected" not in results
 
 
         assert "rejected" not in results
 
@@ -58,10 +58,10 @@ tag1, tag555
         assert hamlet.author == Author.objects.get(name="William Shakespeare")
 
         for quote in Quote.objects.all():
         assert hamlet.author == Author.objects.get(name="William Shakespeare")
 
         for quote in Quote.objects.all():
-            assert c.getPage(quote.get_absolute_url())
+            assert c_adm.getPage(quote.get_absolute_url())
 
     @pytest.mark.django_db
 
     @pytest.mark.django_db
-    def test_massimport_2(self, q1, c):
+    def test_massimport_2(self, q1, c_adm):
         allquotes = """\
 <script>somethingevil()</script>
 A rose by any other name...
         allquotes = """\
 <script>somethingevil()</script>
 A rose by any other name...
@@ -73,13 +73,13 @@ Romeo and Juliet
 tag1, tag555
 ==="""
 
 tag1, tag555
 ==="""
 
-        results = c.postPage('massimport/', {'quotes': allquotes})
+        results = c_adm.postPage('massimport/', {'quotes': allquotes})
         assert "<script>" not in results
         with pytest.raises(Quote.DoesNotExist):
             Quote.objects.get(text__contains="<script>")
 
     @pytest.mark.django_db
         assert "<script>" not in results
         with pytest.raises(Quote.DoesNotExist):
             Quote.objects.get(text__contains="<script>")
 
     @pytest.mark.django_db
-    def test_massimport_3(self, c):
+    def test_massimport_3(self, c_adm):
         """Whitespace and stuff"""
         allquotes = """\
 A rose by any other name...
         """Whitespace and stuff"""
         allquotes = """\
 A rose by any other name...
@@ -106,7 +106,7 @@ Hamlet
 
 """
 
 
 """
 
-        results = c.postPage('massimport/', {'quotes': allquotes})
+        results = c_adm.postPage('massimport/', {'quotes': allquotes})
         assert "rejected" not in results
         assert Quote.objects.get(text="<p>A rose by any other name...</p>")
         assert Author.objects.get(name="William Shakespeare")
         assert "rejected" not in results
         assert Quote.objects.get(text="<p>A rose by any other name...</p>")
         assert Author.objects.get(name="William Shakespeare")
@@ -119,3 +119,6 @@ Hamlet
         assert tirade.work.author.name == "William Shakespeare"
         assert Author.objects.filter(name__contains="Shakespeare").count() == 1
 
         assert tirade.work.author.name == "William Shakespeare"
         assert Author.objects.filter(name__contains="Shakespeare").count() == 1
 
+    def test_massimport_noaccess(self, c):
+        c.getPage('massimport/', exp_status=302)
+        c.postPage('massimport/', {}, exp_status=302)
index 55577bb5e7b16fa8cdedc6694642155c542dd438..a8cc355c150d32021d0ac80ac04ac9e5ef7f6dc4 100644 (file)
@@ -1,6 +1,7 @@
 from django.conf.urls import url
 from django.conf.urls import url
+from django.contrib.auth.views import login
 
 
-from . import views
+from . import views, adminviews
 
 urlpatterns = [
     url(r'^$', views.index, name='index'),
 
 urlpatterns = [
     url(r'^$', views.index, name='index'),
@@ -15,7 +16,10 @@ urlpatterns = [
 
     url(r'^cloud/$', views.cloud, name="cloud"),
     url(r'^search/$', views.searchpage, name="search"),
 
     url(r'^cloud/$', views.cloud, name="cloud"),
     url(r'^search/$', views.searchpage, name="search"),
-    url(r'^massimport/$', views.massimport, name="massimport"),
+
+    url(r'^admin/$', adminviews.listadmintools, name='listadmintools'),
+    url(r'^admin/login$', login, {'template_name': 'admin/login.html'}),
+    url(r'^admin/massimport/$', adminviews.massimport, name='massimport'),
 
     url(r'^all/$', views.all, name="all"),
 ]
 
     url(r'^all/$', views.all, name="all"),
 ]
index 9ff7aacc996bd07db6077490ace90d4b8c7b9d7d..d6ca24035c4a9316ad68e9b2b54c715ebd88376e 100644 (file)
@@ -5,7 +5,6 @@ from random import randint
 from quotes.models import Author, Work, Quote, QuoteTag
 from quotes import search
 from quotes import tagcloud
 from quotes.models import Author, Work, Quote, QuoteTag
 from quotes import search
 from quotes import tagcloud
-from quotes.massimport import domassimport
 
 # create your views here.
 def index(request):
 
 # create your views here.
 def index(request):
@@ -52,10 +51,3 @@ def searchpage(request):
 def cloud(request):
     clouddata = tagcloud.build_cloud()
     return render(request, 'quotes/cloud.html', clouddata)
 def cloud(request):
     clouddata = tagcloud.build_cloud()
     return render(request, 'quotes/cloud.html', clouddata)
-
-def massimport(request):
-    if 'quotes' in request.POST:
-        resultcontext = domassimport(request.POST['quotes'])
-        return render(request, 'quotes/domassimport.html', resultcontext)
-    else:
-        return render(request, 'quotes/massimport.html', {})