Django Admin Inline Form не работает в тесте, но работает в интерфейсе администратора
Я в растерянности, почему следующий пример не работает в тестовом случае, но прекрасно работает в интерфейсе администратора.
У меня есть очень простые модели User
и Login
. Модель Login
просто записывает логины пользователей в систему через Django signal.
class User(AbstractUser):
company = models.CharField(
max_length=100, blank=True, null=True
)
class Login(models.Model):
"""Represents a record of a user login event."""
user = models.ForeignKey(
get_user_model(), on_delete=models.CASCADE, related_name="logins"
)
ip = models.GenericIPAddressField()
user_agent = models.TextField()
date = models.DateTimeField(auto_now_add=True, db_index=True)
domain = models.CharField(max_length=255)
http_host = models.CharField(null=True, max_length=255)
remote_host = models.CharField(null=True, max_length=255)
server_name = models.CharField(null=True, max_length=255)
В admin.py
я определяю UserAdmin
с inlines = [LoginInline]
. В принципе, при просмотре пользователя я могу видеть историю входа.
from django.contrib import admin
from django.contrib.auth import admin as auth_admin
from django.contrib.auth import get_user_model
from django.urls import reverse
from django.utils.html import format_html
from users.models import Login
User = get_user_model()
class ReadOnlyModelMixin:
def has_add_permission(self, request, obj=None):
return False
def has_change_permission(self, request, obj=None):
return False
def has_delete_permission(self, request, obj=None):
return False
class LoginAdmin(ReadOnlyModelMixin, admin.ModelAdmin):
list_display = (
'id',
'user_link_with_name',
'user_email',
'user_company',
'domain',
'date',
'ip',
'remote_host',
'http_host',
'server_name',
'user_agent',
)
@admin.display(description='Name', ordering='user__first_name')
def user_link_with_name(self, obj):
url = reverse("admin:users_user_change", args=[obj.user.id])
return format_html(f'<a href="{url}">{obj.user}</a>')
@admin.display(description='Email', ordering='user__email')
def user_email(self, obj):
return format_html(
f'<a href="mailto:{obj.user.email}">{obj.user.email}</a>'
)
@admin.display(description='Company', ordering="user__company")
def user_company(self, obj):
return obj.user.company
class LoginInline(ReadOnlyModelMixin, admin.TabularInline):
model = Login
class UserAdmin(auth_admin.UserAdmin):
inlines = [LoginInline]
admin.site.register(User, UserAdmin)
admin.site.register(Login, LoginAdmin)
В интерфейсе администратора все работает отлично, я могу просматривать и ADD пользователей без проблем.
Затем я представил тест следующим образом:
class TestUserAdmin:
def test_add(self, admin_client):
url = reverse("admin:users_user_add")
response = admin_client.get(url)
assert response.status_code == 200
response = admin_client.post(
url,
data={
"username": "test",
"password1": "My_R@ndom-P@ssw0rd",
"password2": "My_R@ndom-P@ssw0rd",
},
)
# below FAILS when UserAdmin includes inlines = [LoginInline]
assert User.objects.filter(username="test").exists()
assert response.status_code == 302
строка assert User.objects.filter(username="test").exists()
будет FAIL до тех пор, пока у меня есть inlines = [LoginInline]
, включенный в UserAdmin
. Если я закомментирую inline
, то тест пройдет.
Я действительно хочу понять, что я упускаю, и почему этот тест не работает, учитывая, что он прекрасно работает в интерфейсе администратора.
Репо, воспроизводящее эту проблему: https://github.com/oizik/django_admin_inline_test_problem
Спасибо.