For example we want to modify the default login form with only add new reCAPTCHA feature. Ya, because previously I have an issue about brute forcing password to this page. So, we should add it reCAPTCHA to fix the fuln issue.
We can just overwrite the default admin site from django.
myapp/forms.py
from django import forms
from django.conf import settings
from django.contrib.auth.forms import AuthenticationForm
from captcha.fields import ReCaptchaField
from captcha.widgets import ReCaptchaV2Checkbox
class AuthAdminForm(AuthenticationForm):
if settings.DEBUG:
captcha = ReCaptchaField(widget=ReCaptchaV2Checkbox(
attrs={
'data-theme': 'light',
'data-size': 'normal',
# 'style': ('transform:scale(1.057);-webkit-transform:scale(1.057);'
# 'transform-origin:0 0;-webkit-transform-origin:0 0;')
}
))
templates/myapp/admin/login.html
The point in this template is, we just add a new reCAPTCHA field. Here is the default: https://github.com/django/django/blob/main/django/contrib/admin/templates/admin/login.html
{% extends "admin/base_site.html" %}
{% load i18n static %}
{% block extrastyle %}{{ block.super }}<link rel="stylesheet" type="text/css" href="{% static "admin/css/login.css" %}">
{{ form.media }}
{% endblock %}
{% block bodyclass %}{{ block.super }} login{% endblock %}
{% block usertools %}{% endblock %}
{% block nav-global %}{% endblock %}
{% block nav-sidebar %}{% endblock %}
{% block content_title %}{% endblock %}
{% block breadcrumbs %}{% endblock %}
{% block content %}
{% if form.errors and not form.non_field_errors %}
<p class="errornote">
{% if form.errors.items|length == 1 %}{% translate "Please correct the error below." %}{% else %}{% translate "Please correct the errors below." %}{% endif %}
</p>
{% endif %}
{% if form.non_field_errors %}
{% for error in form.non_field_errors %}
<p class="errornote">
{{ error }}
</p>
{% endfor %}
{% endif %}
<div id="content-main">
{% if user.is_authenticated %}
<p class="errornote">
{% blocktranslate trimmed %}
You are authenticated as {{ username }}, but are not authorized to
access this page. Would you like to login to a different account?
{% endblocktranslate %}
</p>
{% endif %}
<form action="{{ app_path }}" method="post" id="login-form">{% csrf_token %}
<div class="form-row">
{{ form.username.errors }}
{{ form.username.label_tag }} {{ form.username }}
</div>
<div class="form-row">
{{ form.password.errors }}
{{ form.password.label_tag }} {{ form.password }}
<input type="hidden" name="next" value="{{ next }}">
</div>
<!-- start: this is the point --->
<div class="form-row">
{{ form.captcha.errors }}
{{ form.captcha.label_tag }} {{ form.captcha }}
</div>
<!-- end: this is the point --->
{% url 'admin_password_reset' as password_reset_url %}
{% if password_reset_url %}
<div class="password-reset-link">
<a href="{{ password_reset_url }}">{% translate 'Forgotten your password or username?' %}</a>
</div>
{% endif %}
<div class="submit-row">
<input type="submit" value="{% translate 'Log in' %}">
</div>
</form>
</div>
{% endblock %}
myproject/urls.py
from django.contrib import admin
from django.urls import include, path
from myapp.forms import AuthAdminForm
admin.autodiscover()
admin.site.login_form = AuthAdminForm
admin.site.login_template = 'account/admin/login.html'
urlpatterns = [
path('admin/', admin.site.urls),
...
]
Just it.
Overwrite the /admin/login/
url with new views.
from django.contrib import admin
from django.urls import include, path
from myapp.views import AuthAdminView
urlpatterns = [
path('admin/login', AuthAdminView.as_view(), name='login'),
path('admin/', admin.site.urls),
...
]
I get this error
AttributeError at /admin/login/
'MyLoginForm' object has no attribute 'get_user'