mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-02-02 20:54:42 +03:00
Merge pull request #1820 from carltongibson/login-dropdown
Hide login link in browsable API if the login view is not registered.
This commit is contained in:
commit
2e632e5af2
|
@ -5,14 +5,14 @@
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
{% block head %}
|
{% block head %}
|
||||||
|
|
||||||
{% block meta %}
|
{% block meta %}
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
||||||
<meta name="robots" content="NONE,NOARCHIVE" />
|
<meta name="robots" content="NONE,NOARCHIVE" />
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
<title>{% block title %}Django REST framework{% endblock %}</title>
|
<title>{% block title %}Django REST framework{% endblock %}</title>
|
||||||
|
|
||||||
{% block style %}
|
{% block style %}
|
||||||
{% block bootstrap_theme %}
|
{% block bootstrap_theme %}
|
||||||
<link rel="stylesheet" type="text/css" href="{% static "rest_framework/css/bootstrap.min.css" %}"/>
|
<link rel="stylesheet" type="text/css" href="{% static "rest_framework/css/bootstrap.min.css" %}"/>
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
<link rel="stylesheet" type="text/css" href="{% static "rest_framework/css/prettify.css" %}"/>
|
<link rel="stylesheet" type="text/css" href="{% static "rest_framework/css/prettify.css" %}"/>
|
||||||
<link rel="stylesheet" type="text/css" href="{% static "rest_framework/css/default.css" %}"/>
|
<link rel="stylesheet" type="text/css" href="{% static "rest_framework/css/default.css" %}"/>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
|
@ -44,17 +44,9 @@
|
||||||
<ul class="nav pull-right">
|
<ul class="nav pull-right">
|
||||||
{% block userlinks %}
|
{% block userlinks %}
|
||||||
{% if user.is_authenticated %}
|
{% if user.is_authenticated %}
|
||||||
<li class="dropdown">
|
{% optional_logout request user %}
|
||||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
|
|
||||||
{{ user }}
|
|
||||||
<b class="caret"></b>
|
|
||||||
</a>
|
|
||||||
<ul class="dropdown-menu">
|
|
||||||
<li>{% optional_logout request %}</li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
{% else %}
|
{% else %}
|
||||||
<li>{% optional_login request %}</li>
|
{% optional_login request %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -85,7 +77,7 @@
|
||||||
<div class="btn-group format-selection">
|
<div class="btn-group format-selection">
|
||||||
<a class="btn btn-primary js-tooltip" href='{{ request.get_full_path }}'
|
<a class="btn btn-primary js-tooltip" href='{{ request.get_full_path }}'
|
||||||
rel="nofollow" title="Make a GET request on the {{ name }} resource">GET</a>
|
rel="nofollow" title="Make a GET request on the {{ name }} resource">GET</a>
|
||||||
|
|
||||||
<button class="btn btn-primary dropdown-toggle js-tooltip" data-toggle="dropdown"
|
<button class="btn btn-primary dropdown-toggle js-tooltip" data-toggle="dropdown"
|
||||||
title="Specify a format for the GET request">
|
title="Specify a format for the GET request">
|
||||||
<span class="caret"></span>
|
<span class="caret"></span>
|
||||||
|
@ -144,7 +136,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% if display_edit_forms %}
|
{% if display_edit_forms %}
|
||||||
|
|
||||||
{% if post_form or raw_data_post_form %}
|
{% if post_form or raw_data_post_form %}
|
||||||
<div {% if post_form %}class="tabbable"{% endif %}>
|
<div {% if post_form %}class="tabbable"{% endif %}>
|
||||||
{% if post_form %}
|
{% if post_form %}
|
||||||
|
@ -190,7 +182,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if put_form or raw_data_put_form or raw_data_patch_form %}
|
{% if put_form or raw_data_put_form or raw_data_patch_form %}
|
||||||
<div {% if put_form %}class="tabbable"{% endif %}>
|
<div {% if put_form %}class="tabbable"{% endif %}>
|
||||||
{% if put_form %}
|
{% if put_form %}
|
||||||
|
@ -246,7 +238,7 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
<!-- END Content -->
|
<!-- END Content -->
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
{% block footer %}
|
{% block footer %}
|
||||||
<p>Sponsored by <a href="http://dabapps.com/">DabApps</a>.</p>
|
<p>Sponsored by <a href="http://dabapps.com/">DabApps</a>.</p>
|
||||||
|
|
|
@ -41,22 +41,31 @@ def optional_login(request):
|
||||||
except NoReverseMatch:
|
except NoReverseMatch:
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
snippet = "<a href='%s?next=%s'>Log in</a>" % (login_url, escape(request.path))
|
snippet = "<li><a href='{href}?next={next}'>Log in</a></li>".format(href=login_url, next=escape(request.path))
|
||||||
return snippet
|
return snippet
|
||||||
|
|
||||||
|
|
||||||
@register.simple_tag
|
@register.simple_tag
|
||||||
def optional_logout(request):
|
def optional_logout(request, user):
|
||||||
"""
|
"""
|
||||||
Include a logout snippet if REST framework's logout view is in the URLconf.
|
Include a logout snippet if REST framework's logout view is in the URLconf.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
logout_url = reverse('rest_framework:logout')
|
logout_url = reverse('rest_framework:logout')
|
||||||
except NoReverseMatch:
|
except NoReverseMatch:
|
||||||
return ''
|
return '<li class="navbar-text">{user}</li>'.format(user=user)
|
||||||
|
|
||||||
snippet = "<a href='%s?next=%s'>Log out</a>" % (logout_url, escape(request.path))
|
snippet = """<li class="dropdown">
|
||||||
return snippet
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
|
||||||
|
{user}
|
||||||
|
<b class="caret"></b>
|
||||||
|
</a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href='{href}?next={next}'>Log out</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>"""
|
||||||
|
|
||||||
|
return snippet.format(user=user, href=logout_url, next=escape(request.path))
|
||||||
|
|
||||||
|
|
||||||
@register.simple_tag
|
@register.simple_tag
|
||||||
|
|
0
tests/browsable_api/__init__.py
Normal file
0
tests/browsable_api/__init__.py
Normal file
10
tests/browsable_api/auth_urls.py
Normal file
10
tests/browsable_api/auth_urls.py
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
from django.conf.urls import patterns, url, include
|
||||||
|
|
||||||
|
from .views import MockView
|
||||||
|
|
||||||
|
urlpatterns = patterns(
|
||||||
|
'',
|
||||||
|
(r'^$', MockView.as_view()),
|
||||||
|
url(r'^auth/', include('rest_framework.urls', namespace='rest_framework')),
|
||||||
|
)
|
9
tests/browsable_api/no_auth_urls.py
Normal file
9
tests/browsable_api/no_auth_urls.py
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
from django.conf.urls import patterns
|
||||||
|
|
||||||
|
from .views import MockView
|
||||||
|
|
||||||
|
urlpatterns = patterns(
|
||||||
|
'',
|
||||||
|
(r'^$', MockView.as_view()),
|
||||||
|
)
|
65
tests/browsable_api/test_browsable_api.py
Normal file
65
tests/browsable_api/test_browsable_api.py
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
from django.contrib.auth.models import User
|
||||||
|
from django.test import TestCase
|
||||||
|
|
||||||
|
from rest_framework.test import APIClient
|
||||||
|
|
||||||
|
|
||||||
|
class DropdownWithAuthTests(TestCase):
|
||||||
|
"""Tests correct dropdown behaviour with Auth views enabled."""
|
||||||
|
|
||||||
|
urls = 'tests.browsable_api.auth_urls'
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.client = APIClient(enforce_csrf_checks=True)
|
||||||
|
self.username = 'john'
|
||||||
|
self.email = 'lennon@thebeatles.com'
|
||||||
|
self.password = 'password'
|
||||||
|
self.user = User.objects.create_user(self.username, self.email, self.password)
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
self.client.logout()
|
||||||
|
|
||||||
|
def test_name_shown_when_logged_in(self):
|
||||||
|
self.client.login(username=self.username, password=self.password)
|
||||||
|
response = self.client.get('/')
|
||||||
|
self.assertContains(response, 'john')
|
||||||
|
|
||||||
|
def test_logout_shown_when_logged_in(self):
|
||||||
|
self.client.login(username=self.username, password=self.password)
|
||||||
|
response = self.client.get('/')
|
||||||
|
self.assertContains(response, '>Log out<')
|
||||||
|
|
||||||
|
def test_login_shown_when_logged_out(self):
|
||||||
|
response = self.client.get('/')
|
||||||
|
self.assertContains(response, '>Log in<')
|
||||||
|
|
||||||
|
|
||||||
|
class NoDropdownWithoutAuthTests(TestCase):
|
||||||
|
"""Tests correct dropdown behaviour with Auth views NOT enabled."""
|
||||||
|
|
||||||
|
urls = 'tests.browsable_api.no_auth_urls'
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.client = APIClient(enforce_csrf_checks=True)
|
||||||
|
self.username = 'john'
|
||||||
|
self.email = 'lennon@thebeatles.com'
|
||||||
|
self.password = 'password'
|
||||||
|
self.user = User.objects.create_user(self.username, self.email, self.password)
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
self.client.logout()
|
||||||
|
|
||||||
|
def test_name_shown_when_logged_in(self):
|
||||||
|
self.client.login(username=self.username, password=self.password)
|
||||||
|
response = self.client.get('/')
|
||||||
|
self.assertContains(response, 'john')
|
||||||
|
|
||||||
|
def test_dropdown_not_shown_when_logged_in(self):
|
||||||
|
self.client.login(username=self.username, password=self.password)
|
||||||
|
response = self.client.get('/')
|
||||||
|
self.assertNotContains(response, '<li class="dropdown">')
|
||||||
|
|
||||||
|
def test_dropdown_not_shown_when_logged_out(self):
|
||||||
|
response = self.client.get('/')
|
||||||
|
self.assertNotContains(response, '<li class="dropdown">')
|
15
tests/browsable_api/views.py
Normal file
15
tests/browsable_api/views.py
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from rest_framework.views import APIView
|
||||||
|
from rest_framework import authentication
|
||||||
|
from rest_framework import renderers
|
||||||
|
from rest_framework.response import Response
|
||||||
|
|
||||||
|
|
||||||
|
class MockView(APIView):
|
||||||
|
|
||||||
|
authentication_classes = (authentication.SessionAuthentication,)
|
||||||
|
renderer_classes = (renderers.BrowsableAPIRenderer,)
|
||||||
|
|
||||||
|
def get(self, request):
|
||||||
|
return Response({'a': 1, 'b': 2, 'c': 3})
|
Loading…
Reference in New Issue
Block a user