megalus / django-google-sso

Easily add Google Authentication to Django Admin
https://megalus.github.io/django-google-sso/
MIT License
35 stars 20 forks source link

Conflict registering admin model #41

Closed paulschreiber closed 1 month ago

paulschreiber commented 2 months ago

Description

When I run migrate, I get this error:

  File "/app/terraso_backend/apps/core/admin.py", line 60, in <module>
    @admin.register(User)
     ^^^^^^^^^^^^^^^^^^^^
  File "/home/terraso/.local/lib/python3.12/site-packages/django/contrib/admin/decorators.py", line 107, in _model_admin_wrapper
    admin_site.register(models, admin_class=admin_class)
  File "/home/terraso/.local/lib/python3.12/site-packages/django/contrib/admin/sites.py", line 125, in register
    raise AlreadyRegistered(msg)
django.contrib.admin.exceptions.AlreadyRegistered: The model User is already registered with 'core.GoogleSSOUserAdmin'.

We already have a User model for our app: https://github.com/techmatters/terraso-backend/blob/main/terraso_backend/apps/core/admin.py

The workaround was to make sure "django_google_sso", was at the end of INSTALLED_APPS.

chrismaille commented 2 months ago

Hi @paulschreiber , thanks for the message. I'll look into it.

chrismaille commented 2 months ago

Looking at the code, can you try this?

# terraso_backend/apps/core/admin.py
from django_google_sso.admin import (
    GoogleSSOInlineAdmin, get_current_user_and_admin
)

CurrentUserModel, last_admin, LastUserAdmin = get_current_user_and_admin()

if admin.site.is_registered(CurrentUserModel):
    admin.site.unregister(CurrentUserModel)

@admin.register(CurrentUserModel)  # <-- Change here
class UserAdmin(LastUserAdmin):  # <-- Change here
    ordering = ("email",)
    list_display = ("email", "first_name", "last_name", "created_at", "is_staff")
    search_fields = ("email", "first_name", "last_name")
    inlines = (UserPreferenceInline, GoogleSSOInlineAdmin)  # <-- Add GoogleSSOInlineAdmin here
    ...

The get_current_user_and_admin helper retrieve the last Admin and User model registered in Django. I think thats why when you put the package at the end of INSTALLED_APPS, it works, because this helper (which we use too) finds the UserAdmin you registered before.

hbruno commented 1 month ago

I confirm that importing the library at the end of the installed apps solve this problem. In my project I used

INSTALLED_APPS = DJANGO_APPS + THIRD_PARTY_APPS + LOCAL_APPS + ['django_google_sso']
chrismaille commented 1 month ago

Both solutions work, but my advice is to unregister and register again the custom User Admin class, which is in pair with this document. You can do this manually, use the get_current_user_and_admin helper as stated in the docs, or add the package at the end of your INSTALLED_APPS. I'll include this on the documentation.