从DjangoRestFramework 的 TokenAuthentication中和 RDS 项目中得到灵感:DjangoRestFramework 也是有自己的登录页面的
-
DjangoRestFramework 的登录页
urls.pyfrom rest_framework import routers from rest_framework.authtoken import views as drf_auth_views urlpatterns = [ ......... # 学习 restframework 的 login 和 TokenAuthentication # https://blog.csdn.net/qq_39980136/article/details/89503850 url(r'^drf/', include('rest_framework.urls')), ----- DRF 的登录 url 和 视图函数 url(r'^drf_token/', drf_auth_views.obtain_auth_token), ----- DRF 居然给提供了这么现成的接口 url(r'^auth/', include('django.contrib.auth.urls')), ]
D:\xxx\venv\Lib\site-packages\rest_framework\urls.py
from django.conf.urls import url
from django.contrib.auth import views
app_name = 'rest_framework'
urlpatterns = [
url(r'^login/$', views.LoginView.as_view(template_name='rest_framework/login.html'), name='login'),
url(r'^logout/$', views.LogoutView.as_view(), name='logout'),
]
发现了上图就是 D:\xxx\venv\Lib\site-packages\rest_framework\templates\rest_framework\login.html
- Django 原生的登录页, ‘registration/login.html’ Django 框架中并没有该文件只是文件名字固定了,需要开发者提供内容
仔细分析上面的代码 D:\xxx\venv\Lib\site-packages\rest_framework\urls.py 可以看到其使用的就是 Django 原生的 LoginView
urls.py
from rest_framework import routers
from rest_framework.authtoken import views as drf_auth_views
urlpatterns = [
.........
url(r'^auth/', include('django.contrib.auth.urls')),
]
D:\xxx\venv\Lib\site-packages\django\contrib\auth\urls.py
from django.conf.urls import url
from django.contrib.auth import views
urlpatterns = [
url(r'^login/$', views.LoginView.as_view(), name='login'),
url(r'^logout/$', views.LogoutView.as_view(), name='logout'),
url(r'^password_change/$', views.PasswordChangeView.as_view(), name='password_change'),
url(r'^password_change/done/$', views.PasswordChangeDoneView.as_view(), name='password_change_done'),
url(r'^password_reset/$', views.PasswordResetView.as_view(), name='password_reset'),
url(r'^password_reset/done/$', views.PasswordResetDoneView.as_view(), name='password_reset_done'),
url(r'^reset/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$',
views.PasswordResetConfirmView.as_view(), name='password_reset_confirm'),
url(r'^reset/done/$', views.PasswordResetCompleteView.as_view(), name='password_reset_complete'),
]
D:\xxx\venv\Lib\site-packages\django\contrib\auth\views.py
class LoginView(SuccessURLAllowedHostsMixin, FormView):
"""
Displays the login form and handles the login action.
"""
form_class = AuthenticationForm
authentication_form = None
redirect_field_name = REDIRECT_FIELD_NAME
template_name = 'registration/login.html' -------Django 框架中并没有该文件只是文件名字固定了,需要开发者提供内容
redirect_authenticated_user = False
extra_context = None
@method_decorator(sensitive_post_parameters())
@method_decorator(csrf_protect)
@method_decorator(never_cache)
def dispatch(self, request, *args, **kwargs):
if self.redirect_authenticated_user and self.request.user.is_authenticated:
redirect_to = self.get_success_url()
if redirect_to == self.request.path:
raise ValueError(
"Redirection loop for authenticated user detected. Check that "
"your LOGIN_REDIRECT_URL doesn't point to a login page."
)
return HttpResponseRedirect(redirect_to)
return super(LoginView, self).dispatch(request, *args, **kwargs)
def get_success_url(self):
url = self.get_redirect_url()
return url or resolve_url(settings.LOGIN_REDIRECT_URL)
[root@JXQ-240-90-228 site-packages]# find . -name login.html
./Django-1.11.16-py2.7.egg/django/contrib/admin/templates/admin/login.html
./djangorestframework-3.8.2-py2.7.egg/rest_framework/templates/rest_framework/login.html
[root@JXQ-240-90-228 site-packages]#
- Django admin URL 的 login
urls.py:
from app01 import views
from app02 import views as app02_view
from app03 import views as app03_view
from rest_framework import routers
app02_router = routers.DefaultRouter()
app02_router.register(r'autoregister', app02_view.RoleViewSet)
from rest_framework.authtoken import views as drf_auth_views
urlpatterns = [
url(r'^admin/', admin.site.urls),
]
D:\xxx\venv\Lib\site-packages\django\contrib\admin\sites.py
class AdminSite(object):
........
def get_urls(self):
from django.conf.urls import url, include
# Since this module gets imported in the application's root package,
# it cannot import models from other applications at the module level,
# and django.contrib.contenttypes.views imports ContentType.
from django.contrib.contenttypes import views as contenttype_views
def wrap(view, cacheable=False):
def wrapper(*args, **kwargs):
return self.admin_view(view, cacheable)(*args, **kwargs)
wrapper.admin_site = self
return update_wrapper(wrapper, view)
# Admin-site-wide views.
urlpatterns = [
url(r'^$', wrap(self.index), name='index'),
url(r'^login/$', self.login, name='login'),
url(r'^logout/$', wrap(self.logout), name='logout'),
url(r'^password_change/$', wrap(self.password_change, cacheable=True), name='password_change'),
url(r'^password_change/done/$', wrap(self.password_change_done, cacheable=True),
name='password_change_done'),
url(r'^jsi18n/$', wrap(self.i18n_javascript, cacheable=True), name='jsi18n'),
url(r'^r/(?P<content_type_id>\d+)/(?P<object_id>.+)/$', wrap(contenttype_views.shortcut),
name='view_on_site'),
]
# Add in each model's views, and create a list of valid URLS for the
# app_index
valid_app_labels = []
for model, model_admin in self._registry.items():
urlpatterns += [
url(r'^%s/%s/' % (model._meta.app_label, model._meta.model_name), include(model_admin.urls)),
]
if model._meta.app_label not in valid_app_labels:
valid_app_labels.append(model._meta.app_label)
# If there were ModelAdmins registered, we should have a list of app
# labels for which we need to allow access to the app_index view,
if valid_app_labels:
regex = r'^(?P<app_label>' + '|'.join(valid_app_labels) + ')/$'
urlpatterns += [
url(regex, wrap(self.app_index), name='app_list'),
]
return urlpatterns
@property
def urls(self):
return self.get_urls(), 'admin', self.name
@never_cache
def login(self, request, extra_context=None):
"""
Displays the login form for the given HttpRequest.
"""
if request.method == 'GET' and self.has_permission(request):
# Already logged-in, redirect to admin index
index_path = reverse('admin:index', current_app=self.name)
return HttpResponseRedirect(index_path)
from django.contrib.auth.views import LoginView
# Since this module gets imported in the application's root package,
# it cannot import models from other applications at the module level,
# and django.contrib.admin.forms eventually imports User.
from django.contrib.admin.forms import AdminAuthenticationForm
context = dict(
self.each_context(request),
title=_('Log in'),
app_path=request.get_full_path(),
username=request.user.get_username(),
)
if (REDIRECT_FIELD_NAME not in request.GET and
REDIRECT_FIELD_NAME not in request.POST):
context[REDIRECT_FIELD_NAME] = reverse('admin:index', current_app=self.name)
context.update(extra_context or {})
defaults = {
'extra_context': context,
'authentication_form': self.login_form or AdminAuthenticationForm,
'template_name': self.login_template or 'admin/login.html', --- 就是上图看到的 admin login 页面
}
request.current_app = self.name
return LoginView.as_view(**defaults)(request)
site = AdminSite() ----------正好和 urls.py 中的 url(r'^admin/', admin.site.urls), 呼应