Giter Site home page Giter Site logo

django-username-email's Introduction

CUser, make email the USERNAME_FIELD

CUser makes it easy to use email address as your identification token instead of a username.

CUser is a custom Django user model (extends AbstractBaseUser) so it takes a tiny amount of effort to use.

The only difference between CUser and the vanilla Django User is email address is the USERNAME_FIELD (and username does not exist).

CUser supports Django 3.2 - 5.1. If you need to use CUser with Django 1.8 - 3.1, you must install an older, unmaintained version of CUser, as noted in the "Install & Set up" section.

Why use CUser?

Because you want everything in django.contrib.auth except for the username field and you also want users to log in with email addresses. And you don't want to create your own custom user model or authentication backend.

Install & Set up

Important: To keep things simple, the steps below will guide you through the process of using CUser's CUser model for your Django project's user model. However, it is strongly recommended that you set up a custom user model that extends CUser's AbstractCUser class, even if CUser's CUser model is sufficient for you (this way, you can customize the user model if the need arises). If you would not like to follow this recommendation and just want to use CUser's CUser model, simply follow the steps below (you can skip the rest of this paragraph). If you would like to follow this recommendation, you should still follow the steps below, but with the following adjustments: After step 3, follow these instructions, but instead of using from django.contrib.auth.models import AbstractUser use from cuser.models import AbstractCUser and instead of using from django.contrib.auth.admin import UserAdmin use from cuser.admin import UserAdmin. Then for step 4 of the steps below, you should set AUTH_USER_MODEL to your custom user model instead of CUser's CUser model. You should then run python manage.py makemigrations. After that, you may follow the remaining steps below just the way they are.

  1. If your Django project previously used Django's default user model, django.contrib.auth.models.User, or if you are unfamiliar with using custom user models, jump to Notes first (then come back). Otherwise, continue onward!

  2. Install with pip:

    # Django 3.2 - 5.1
    pip install django-username-email
    
    # Django 3.1 (unmaintained)
    pip install django-username-email==2.4.2
    
    # Django 2.2 or 3.0 (unmaintained)
    pip install django-username-email==2.3.1
    
    # Django 2.0 or 2.1 (unmaintained)
    pip install django-username-email==2.2.4
    
    # Django 1.11 (unmaintained)
    pip install django-username-email==2.1.6
    
    # Django 1.8 - 1.10 (unmaintained)
    pip install django-username-email==2.1.2
  3. Add cuser to your INSTALLED_APPS setting:

    INSTALLED_APPS = [
        ...
        'cuser',
    ]
  4. Specify the custom model as the default user model for your project using the AUTH_USER_MODEL setting in your settings.py:

    AUTH_USER_MODEL = 'cuser.CUser'
  5. If you use Django's default AuthenticationForm class, it is strongly recommended that you replace it with the one included with CUser. This will make the <input> have its type attribute set to email and browsers' autocomplete feature will suggest email addresses instead of usernames. For example, if your project is using Django's default LoginView view (or login view in Django < 1.11), this is what you would put in your urls.py in order to make use of CUser's AuthenticationForm class:

    from cuser.forms import AuthenticationForm
    from django.conf.urls import include, url
    from django.contrib.auth.views import LoginView
    
    urlpatterns = [
        url(r'^accounts/login/$', LoginView.as_view(authentication_form=AuthenticationForm), name='login'),
        url(r'^accounts/', include('django.contrib.auth.urls')),
        ...
    ]

    Or if you're using Django < 1.11:

    from cuser.forms import AuthenticationForm
    from django.conf.urls import include, url
    from django.contrib.auth.views import login
    
    urlpatterns = [
        url(r'^accounts/login/$', login, {'authentication_form': AuthenticationForm}, name='login'),
        url(r'^accounts/', include('django.contrib.auth.urls')),
        ...
    ]
  6. Run migrations.

    python manage.py migrate
  7. There is a good chance that you want [email protected] and [email protected] to be treated as the same email address. There is a variety of ways to go about doing this. How you handle it will depend on the needs of your project and personal preference, so CUser does not provide a solution for this out of the box. You will need to address this yourself if this applies to you. If you're using CUser's AuthenticationForm class (see step 5), you may want to subclass it and override error_messages['invalid_login'].

Configuration

To override any of the default settings, create a dictionary named CUSER in your settings.py with each setting you want to override. For example:

CUSER = {
    'app_verbose_name': 'Authentication and Authorization',
    'register_proxy_auth_group_model': True,
}

These are the settings:

app_verbose_name (default: _("Custom User"))

This controls the value that CUser will use for its AppConfig class' verbose_name.

register_proxy_auth_group_model (default: False)

When set to True, CUser's admin.py will unregister Django's default Group model and register its own proxy model of Django's default Group model (also named Group). This is useful if you want Django's default Group model to appear in the same part of the admin as CUser's CUser model.

Notes

If you have tables referencing Django's User model, you will have to delete those table and migrations, then re-migrate. This will ensure everything is set up correctly from the beginning.

Instead of referring to User directly, you should reference the user model using django.contrib.auth.get_user_model()

When you define a foreign key or many-to-many relations to the User model, you should specify the custom model using the AUTH_USER_MODEL setting.

For example:

from django.conf import settings
from django.db import models

class Profile(models.Model):
    user = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
)

License

Released under the MIT license. See LICENSE for details.

Original author

Tom Meagher

Questions, comments, or anything else?

  • Open an issue

django-username-email's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

django-username-email's Issues

Faulty `invalid_login` error message

The error message in cuser/templates/forms.py

'invalid_login': _(
            "Please enter a correct %(username)s and password. Note that both "
            "fields may be case-sensitive."
        ),

translates to :

Please enter a correct email address and password. Note that both fields may be case-sensitive.

This is incorrect because email addresses are not case-sensitive. Only the password field may be case-sensitive.

Missing migration

Hi, migrate command says that I have missing migration:

Your models have changes that are not yet reflected in a migration, and so won't be applied.
  Run 'manage.py makemigrations' to make new migrations, and then re-run 'manage.py migrate' to apply them.

When I ran the command ./manage.py makemigrations cuser it generated the new migration file for me with

migrations.AlterField(
            model_name='cuser',
            name='email',
            field=models.EmailField(error_messages={'unique': 'A user with that email address already exists.'}, max_length=254, unique=True, verbose_name='email address'),
        ),

This looks odd because we have the same email field parameters in initial migration. Maybe it is due to that I use SQLite database for my small project. Anyway, I gonna to make PR with this odd missing migration.

Does anybody observe the same issue?

Help with CUser: Reverse accessor clashing

I am using cuser as follows (having imported AbstractCUser):
class Utilisateur(AbstractCUser):
telephone = models.CharField(max_length=10)
doit_changer_mot_de_passe = models.BooleanField(default=True)
a_accepte_CGU = models.BooleanField(default=False)
est_administrateur = models.BooleanField(default=False)

Django returns the following errors:
core.Utilisateur.groups: (fields.E304) Reverse accessor for 'Utilisateur.groups' clashes with reverse accessor for 'CUser.groups'.
HINT: Add or change a related_name argument to the definition for 'Utilisateur.groups' or 'CUser.groups'.
core.Utilisateur.user_permissions: (fields.E304) Reverse accessor for 'Utilisateur.user_permissions' clashes with reverse accessor for 'CUser.user_permissions'.
HINT: Add or change a related_name argument to the definition for 'Utilisateur.user_permissions' or 'CUser.user_permissions'.
cuser.CUser.groups: (fields.E304) Reverse accessor for 'CUser.groups' clashes with reverse accessor for 'Utilisateur.groups'.
HINT: Add or change a related_name argument to the definition for 'CUser.groups' or 'Utilisateur.groups'.
cuser.CUser.user_permissions: (fields.E304) Reverse accessor for 'CUser.user_permissions' clashes with reverse accessor for 'Utilisateur.user_permissions'.
HINT: Add or change a related_name argument to the definition for 'CUser.user_permissions' or 'Utilisateur.user_permissions'.

What would you advise?

Referring to wrong step before under Install & Set up

In the text it says

but with the following adjustments: After step 2, follow these instructions, but instead of using [...]. Then for step 3 of the steps below, you should set AUTH_USER_MODEL to your custom user model instead of CUser’s CUser model

Since the "Step 3" part seems to be referring to Step 4 and step 3 really is to add the app to the installed apps, it seems as if you meant to say "step 4" here.

no such table: 'cuser_user'

Anytime I try to login a user, create a super user, or even entering admin I get this error, I tried running python manage.py migrate --run-syncdb with no changes.

Full Traceback:

Environment:


Request Method: POST
Request URL: http://localhost:8000/admin/login/

Django Version: 2.1.1
Python Version: 3.7.0
Installed Applications:
['django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'info',
 'login',
 'main',
 'widget_tweaks',
 'cuser']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware']



Traceback:

File "C:\Users\Duarte Dias\Desktop\iterate\env\lib\site-packages\django\db\backends\utils.py" in _execute
  85.                 return self.cursor.execute(sql, params)

File "C:\Users\Duarte Dias\Desktop\iterate\env\lib\site-packages\django\db\backends\sqlite3\base.py" in execute
  296.         return Database.Cursor.execute(self, query, params)

The above exception (no such table: cuser_cuser) was the direct cause of the following exception:

File "C:\Users\Duarte Dias\Desktop\iterate\env\lib\site-packages\django\core\handlers\exception.py" in inner
  34.             response = get_response(request)

File "C:\Users\Duarte Dias\Desktop\iterate\env\lib\site-packages\django\core\handlers\base.py" in _get_response
  126.                 response = self.process_exception_by_middleware(e, request)

File "C:\Users\Duarte Dias\Desktop\iterate\env\lib\site-packages\django\core\handlers\base.py" in _get_response
  124.                 response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "C:\Users\Duarte Dias\Desktop\iterate\env\lib\site-packages\django\views\decorators\cache.py" in _wrapped_view_func
  44.         response = view_func(request, *args, **kwargs)

File "C:\Users\Duarte Dias\Desktop\iterate\env\lib\site-packages\django\contrib\admin\sites.py" in login
  398.         return LoginView.as_view(**defaults)(request)

File "C:\Users\Duarte Dias\Desktop\iterate\env\lib\site-packages\django\views\generic\base.py" in view
  68.             return self.dispatch(request, *args, **kwargs)

File "C:\Users\Duarte Dias\Desktop\iterate\env\lib\site-packages\django\utils\decorators.py" in _wrapper
  45.         return bound_method(*args, **kwargs)

File "C:\Users\Duarte Dias\Desktop\iterate\env\lib\site-packages\django\views\decorators\debug.py" in sensitive_post_parameters_wrapper
  76.             return view(request, *args, **kwargs)

File "C:\Users\Duarte Dias\Desktop\iterate\env\lib\site-packages\django\utils\decorators.py" in _wrapper
  45.         return bound_method(*args, **kwargs)

File "C:\Users\Duarte Dias\Desktop\iterate\env\lib\site-packages\django\utils\decorators.py" in _wrapped_view
  142.                     response = view_func(request, *args, **kwargs)

File "C:\Users\Duarte Dias\Desktop\iterate\env\lib\site-packages\django\utils\decorators.py" in _wrapper
  45.         return bound_method(*args, **kwargs)

File "C:\Users\Duarte Dias\Desktop\iterate\env\lib\site-packages\django\views\decorators\cache.py" in _wrapped_view_func
  44.         response = view_func(request, *args, **kwargs)

File "C:\Users\Duarte Dias\Desktop\iterate\env\lib\site-packages\django\contrib\auth\views.py" in dispatch
  61.         return super().dispatch(request, *args, **kwargs)

File "C:\Users\Duarte Dias\Desktop\iterate\env\lib\site-packages\django\views\generic\base.py" in dispatch
  88.         return handler(request, *args, **kwargs)

File "C:\Users\Duarte Dias\Desktop\iterate\env\lib\site-packages\django\views\generic\edit.py" in post
  141.         if form.is_valid():

File "C:\Users\Duarte Dias\Desktop\iterate\env\lib\site-packages\django\forms\forms.py" in is_valid
  185.         return self.is_bound and not self.errors

File "C:\Users\Duarte Dias\Desktop\iterate\env\lib\site-packages\django\forms\forms.py" in errors
  180.             self.full_clean()

File "C:\Users\Duarte Dias\Desktop\iterate\env\lib\site-packages\django\forms\forms.py" in full_clean
  382.         self._clean_form()

File "C:\Users\Duarte Dias\Desktop\iterate\env\lib\site-packages\django\forms\forms.py" in _clean_form
  409.             cleaned_data = self.clean()

File "C:\Users\Duarte Dias\Desktop\iterate\env\lib\site-packages\django\contrib\auth\forms.py" in clean
  195.             self.user_cache = authenticate(self.request, username=username, password=password)

File "C:\Users\Duarte Dias\Desktop\iterate\env\lib\site-packages\django\contrib\auth\__init__.py" in authenticate
  73.             user = backend.authenticate(request, **credentials)

File "C:\Users\Duarte Dias\Desktop\iterate\env\lib\site-packages\django\contrib\auth\backends.py" in authenticate
  16.             user = UserModel._default_manager.get_by_natural_key(username)

File "C:\Users\Duarte Dias\Desktop\iterate\env\lib\site-packages\django\contrib\auth\base_user.py" in get_by_natural_key
  44.         return self.get(**{self.model.USERNAME_FIELD: username})

File "C:\Users\Duarte Dias\Desktop\iterate\env\lib\site-packages\django\db\models\manager.py" in manager_method
  82.                 return getattr(self.get_queryset(), name)(*args, **kwargs)

File "C:\Users\Duarte Dias\Desktop\iterate\env\lib\site-packages\django\db\models\query.py" in get
  393.         num = len(clone)

File "C:\Users\Duarte Dias\Desktop\iterate\env\lib\site-packages\django\db\models\query.py" in __len__
  250.         self._fetch_all()

File "C:\Users\Duarte Dias\Desktop\iterate\env\lib\site-packages\django\db\models\query.py" in _fetch_all
  1186.             self._result_cache = list(self._iterable_class(self))

File "C:\Users\Duarte Dias\Desktop\iterate\env\lib\site-packages\django\db\models\query.py" in __iter__
  54.         results = compiler.execute_sql(chunked_fetch=self.chunked_fetch, chunk_size=self.chunk_size)

File "C:\Users\Duarte Dias\Desktop\iterate\env\lib\site-packages\django\db\models\sql\compiler.py" in execute_sql
  1065.             cursor.execute(sql, params)

File "C:\Users\Duarte Dias\Desktop\iterate\env\lib\site-packages\django\db\backends\utils.py" in execute
  100.             return super().execute(sql, params)

File "C:\Users\Duarte Dias\Desktop\iterate\env\lib\site-packages\django\db\backends\utils.py" in execute
  68.         return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)

File "C:\Users\Duarte Dias\Desktop\iterate\env\lib\site-packages\django\db\backends\utils.py" in _execute_with_wrappers
  77.         return executor(sql, params, many, context)

File "C:\Users\Duarte Dias\Desktop\iterate\env\lib\site-packages\django\db\backends\utils.py" in _execute
  85.                 return self.cursor.execute(sql, params)

File "C:\Users\Duarte Dias\Desktop\iterate\env\lib\site-packages\django\db\utils.py" in __exit__
  89.                 raise dj_exc_value.with_traceback(traceback) from exc_value

File "C:\Users\Duarte Dias\Desktop\iterate\env\lib\site-packages\django\db\backends\utils.py" in _execute
  85.                 return self.cursor.execute(sql, params)

File "C:\Users\Duarte Dias\Desktop\iterate\env\lib\site-packages\django\db\backends\sqlite3\base.py" in execute
  296.         return Database.Cursor.execute(self, query, params)

Exception Type: OperationalError at /admin/login/
Exception Value: no such table: cuser_cuser

django v4 complains about a missing "cuser" migration

  • django v4 complains about a missing "cuser" migration
  • manage.py makemigrations creates the following "" migration.
  • I suspect that this migration must be added to cuser source code for django v4 compatibility

root@7a55490bd5f3:/app# ./manage.py makemigrations
Migrations for 'cuser':
  /usr/local/lib/python3.9/site-packages/cuser/migrations/0004_alter_cuser_id.py
    - Alter field id on cuser

root@7a55490bd5f3:/app# cat /usr/local/lib/python3.9/site-packages/cuser/migrations/0004_alter_cuser_id.py
# Generated by Django 4.0 on 2021-12-17 09:39

from django.db import migrations, models


class Migration(migrations.Migration):

    dependencies = [
        ('cuser', '0003_alter_user_first_name_max_length'),
    ]

    operations = [
        migrations.AlterField(
            model_name='cuser',
            name='id',
            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
        ),
    ]


Migrations for Django 2.2 fail

Hi,

I just tried upgrading my development environment (using django-username-email 2.2.2) to Django 2.2, and when I ran migrate, I got this:

Traceback (most recent call last):
  File "manage.py", line 15, in <module>
    execute_from_command_line(sys.argv)
  File "/home/dom/.virtualenvs/churchsimple/lib/python3.6/site-packages/django/core/management/__init__.py", line 381, in execute_from_command_line
    utility.execute()
  File "/home/dom/.virtualenvs/churchsimple/lib/python3.6/site-packages/django/core/management/__init__.py", line 375, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/home/dom/.virtualenvs/churchsimple/lib/python3.6/site-packages/django/core/management/base.py", line 323, in run_from_argv
    self.execute(*args, **cmd_options)
  File "/home/dom/.virtualenvs/churchsimple/lib/python3.6/site-packages/django/core/management/base.py", line 364, in execute
    output = self.handle(*args, **options)
  File "/home/dom/.virtualenvs/churchsimple/lib/python3.6/site-packages/django/core/management/base.py", line 83, in wrapped
    res = handle_func(*args, **kwargs)
  File "/home/dom/.virtualenvs/churchsimple/lib/python3.6/site-packages/django/core/management/commands/migrate.py", line 234, in handle
    fake_initial=fake_initial,
  File "/home/dom/.virtualenvs/churchsimple/lib/python3.6/site-packages/django/db/migrations/executor.py", line 117, in migrate
    state = self._migrate_all_forwards(state, plan, full_plan, fake=fake, fake_initial=fake_initial)
  File "/home/dom/.virtualenvs/churchsimple/lib/python3.6/site-packages/django/db/migrations/executor.py", line 147, in _migrate_all_forwards
    state = self.apply_migration(state, migration, fake=fake, fake_initial=fake_initial)
  File "/home/dom/.virtualenvs/churchsimple/lib/python3.6/site-packages/django/db/migrations/executor.py", line 245, in apply_migration
    state = migration.apply(state, schema_editor)
  File "/home/dom/.virtualenvs/churchsimple/lib/python3.6/site-packages/django/db/migrations/migration.py", line 124, in apply
    operation.database_forwards(self.app_label, schema_editor, old_state, project_state)
  File "/home/dom/.virtualenvs/churchsimple/lib/python3.6/site-packages/django/db/migrations/operations/special.py", line 190, in database_forwards
    self.code(from_state.apps, schema_editor)
  File "/home/dom/.virtualenvs/churchsimple/lib/python3.6/site-packages/django/contrib/auth/migrations/0011_update_proxy_permissions.py", line 35, in update_proxy_model_permissions
    ).update(content_type=new_content_type)
  File "/home/dom/.virtualenvs/churchsimple/lib/python3.6/site-packages/django/db/models/query.py", line 741, in update
    rows = query.get_compiler(self.db).execute_sql(CURSOR)
  File "/home/dom/.virtualenvs/churchsimple/lib/python3.6/site-packages/django/db/models/sql/compiler.py", line 1426, in execute_sql
    cursor = super().execute_sql(result_type)
  File "/home/dom/.virtualenvs/churchsimple/lib/python3.6/site-packages/django/db/models/sql/compiler.py", line 1097, in execute_sql
    cursor.execute(sql, params)
  File "/home/dom/.virtualenvs/churchsimple/lib/python3.6/site-packages/django/db/backends/utils.py", line 99, in execute
    return super().execute(sql, params)
  File "/home/dom/.virtualenvs/churchsimple/lib/python3.6/site-packages/django/db/backends/utils.py", line 67, in execute
    return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
  File "/home/dom/.virtualenvs/churchsimple/lib/python3.6/site-packages/django/db/backends/utils.py", line 76, in _execute_with_wrappers
    return executor(sql, params, many, context)
  File "/home/dom/.virtualenvs/churchsimple/lib/python3.6/site-packages/django/db/backends/utils.py", line 84, in _execute
    return self.cursor.execute(sql, params)
  File "/home/dom/.virtualenvs/churchsimple/lib/python3.6/site-packages/django/db/utils.py", line 89, in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
  File "/home/dom/.virtualenvs/churchsimple/lib/python3.6/site-packages/django/db/backends/utils.py", line 84, in _execute
    return self.cursor.execute(sql, params)
django.db.utils.IntegrityError: duplicate key value violates unique constraint "auth_permission_content_type_id_codename_01ab375a_uniq"
DETAIL:  Key (content_type_id, codename)=(6, add_group) already exists.

In this case, the old content type being moved from was auth, and the new one was cuser. Looking in my database, I appear to have the following:

>>> from django.contrib.auth.models import Permission
>>> foo = list(Permission.objects.all())
>>> foo = [obj for obj in foo if obj.codename == 'add_group']
>>> foo
[<Permission: auth | group | Can add group>, <Permission: cuser | group | Can add group>]

Any ideas of how to fix this? I think I could probably fix by removing all the Permission objects with content type cuser right before the upgrade, but curious if you have better ideas, of if there's a way to fix this in django-username-email itself.

Form validation error on email field

When validating the email address I kept running into errors when a new user wants to sign up.

I see this errors, because I use this print statement:
print(form.errors.as_json())

When I leave email empty I get this error (which is expected):
{"email": [{"message": "This field is required.", "code": "required"}]}

When I enter a invalid email address I get this error (which is expected):
{"email": [{"message": "Enter a valid email address.", "code": "invalid"}]}

When I enter a valid email address I get this error (which is NOT expected):
{"email": [{"message": "This field cannot be blank.", "code": "blank"}]}

To fix this issue I edited the AbstractCUser class in cuser.models.py
I added blank=True, like this:

email = models.EmailField(
    _('email address'),
    blank=True,
    unique=True,
    error_messages={
        'unique': _("A user with that email address already exists."),
    },
)

Maybe I made a mistake somewhere else, not sure.
But this was my solution.

Avoid creating cuser_cuser_* tables when extend AbstractCUser.

I created a custom User model based on your django-username-email AbstractCUser class. A side effect is the creation of cuser_cuser_* tables even though they are never populated. I’m wondering how to avoid creating these tables.

Here is the contents of my users/model.py:
from django.db import models
from django.contrib.auth.models import Group as BaseGroup
from cuser.models import AbstractCUser, CUserManager

class User(AbstractCUser):
    """
    Password and email are required. Other fields are optional.
    """
    class Meta(AbstractCUser.Meta):
        swappable = 'AUTH_USER_MODEL'

class UserManager(CUserManager):
    pass

class Group(BaseGroup):
    class Meta:
        proxy = True

Using cuser with an started project

When a project has data, the migration process raises a:
django.db.migrations.exceptions.InconsistentMigrationHistory: Migration wagtaildocs.0001_initial is applied before its dependency cuser.0001_initial on database 'default'.
I'm reading that django docs don't recommend to change the user model once started the project. Should it be possible with django-username-email?

django.utils.translation.ugettext_lazy() is deprecated

Currently I'm getting a lot of warnings. The log is below. Simply changing all occurances of ugettext_lazy to gettext_lazy should do the trick.


../../../.cache/pypoetry/virtualenvs/foobar-core-6qdzD22P-py3.9/lib/python3.9/site-packages/cuser/settings.py:5
  /home/alex/.cache/pypoetry/virtualenvs/foobar-core-6qdzD22P-py3.9/lib/python3.9/site-packages/cuser/settings.py:5: RemovedInDjango40Warning: django.utils.translation.ugettext_lazy() is deprecated in favor of django.utils.translation.gettext_lazy().
    'app_verbose_name': _("Custom User"),

../../../.cache/pypoetry/virtualenvs/foobar-core-6qdzD22P-py3.9/lib/python3.9/site-packages/cuser/models.py:91
  /home/alex/.cache/pypoetry/virtualenvs/foobar-core-6qdzD22P-py3.9/lib/python3.9/site-packages/cuser/models.py:91: RemovedInDjango40Warning: django.utils.translation.ugettext_lazy() is deprecated in favor of django.utils.translation.gettext_lazy().
    _('email address'),

../../../.cache/pypoetry/virtualenvs/foobar-core-6qdzD22P-py3.9/lib/python3.9/site-packages/cuser/models.py:94
  /home/alex/.cache/pypoetry/virtualenvs/foobar-core-6qdzD22P-py3.9/lib/python3.9/site-packages/cuser/models.py:94: RemovedInDjango40Warning: django.utils.translation.ugettext_lazy() is deprecated in favor of django.utils.translation.gettext_lazy().
    'unique': _("A user with that email address already exists."),

../../../.cache/pypoetry/virtualenvs/foobar-core-6qdzD22P-py3.9/lib/python3.9/site-packages/cuser/models.py:97
  /home/alex/.cache/pypoetry/virtualenvs/foobar-core-6qdzD22P-py3.9/lib/python3.9/site-packages/cuser/models.py:97: RemovedInDjango40Warning: django.utils.translation.ugettext_lazy() is deprecated in favor of django.utils.translation.gettext_lazy().
    first_name = models.CharField(_('first name'), max_length=150, blank=True)

../../../.cache/pypoetry/virtualenvs/foobar-core-6qdzD22P-py3.9/lib/python3.9/site-packages/cuser/models.py:98
  /home/alex/.cache/pypoetry/virtualenvs/foobar-core-6qdzD22P-py3.9/lib/python3.9/site-packages/cuser/models.py:98: RemovedInDjango40Warning: django.utils.translation.ugettext_lazy() is deprecated in favor of django.utils.translation.gettext_lazy().
    last_name = models.CharField(_('last name'), max_length=150, blank=True)

../../../.cache/pypoetry/virtualenvs/foobar-core-6qdzD22P-py3.9/lib/python3.9/site-packages/cuser/models.py:100
  /home/alex/.cache/pypoetry/virtualenvs/foobar-core-6qdzD22P-py3.9/lib/python3.9/site-packages/cuser/models.py:100: RemovedInDjango40Warning: django.utils.translation.ugettext_lazy() is deprecated in favor of django.utils.translation.gettext_lazy().
    _('staff status'),

../../../.cache/pypoetry/virtualenvs/foobar-core-6qdzD22P-py3.9/lib/python3.9/site-packages/cuser/models.py:102
  /home/alex/.cache/pypoetry/virtualenvs/foobar-core-6qdzD22P-py3.9/lib/python3.9/site-packages/cuser/models.py:102: RemovedInDjango40Warning: django.utils.translation.ugettext_lazy() is deprecated in favor of django.utils.translation.gettext_lazy().
    help_text=_('Designates whether the user can log into this admin site.'),

../../../.cache/pypoetry/virtualenvs/foobar-core-6qdzD22P-py3.9/lib/python3.9/site-packages/cuser/models.py:105
  /home/alex/.cache/pypoetry/virtualenvs/foobar-core-6qdzD22P-py3.9/lib/python3.9/site-packages/cuser/models.py:105: RemovedInDjango40Warning: django.utils.translation.ugettext_lazy() is deprecated in favor of django.utils.translation.gettext_lazy().
    _('active'),

../../../.cache/pypoetry/virtualenvs/foobar-core-6qdzD22P-py3.9/lib/python3.9/site-packages/cuser/models.py:107
  /home/alex/.cache/pypoetry/virtualenvs/foobar-core-6qdzD22P-py3.9/lib/python3.9/site-packages/cuser/models.py:107: RemovedInDjango40Warning: django.utils.translation.ugettext_lazy() is deprecated in favor of django.utils.translation.gettext_lazy().
    help_text=_(

../../../.cache/pypoetry/virtualenvs/foobar-core-6qdzD22P-py3.9/lib/python3.9/site-packages/cuser/models.py:112
  /home/alex/.cache/pypoetry/virtualenvs/foobar-core-6qdzD22P-py3.9/lib/python3.9/site-packages/cuser/models.py:112: RemovedInDjango40Warning: django.utils.translation.ugettext_lazy() is deprecated in favor of django.utils.translation.gettext_lazy().
    date_joined = models.DateTimeField(_('date joined'), default=timezone.now)

../../../.cache/pypoetry/virtualenvs/foobar-core-6qdzD22P-py3.9/lib/python3.9/site-packages/cuser/models.py:120
  /home/alex/.cache/pypoetry/virtualenvs/foobar-core-6qdzD22P-py3.9/lib/python3.9/site-packages/cuser/models.py:120: RemovedInDjango40Warning: django.utils.translation.ugettext_lazy() is deprecated in favor of django.utils.translation.gettext_lazy().
    verbose_name = _('user')

../../../.cache/pypoetry/virtualenvs/foobar-core-6qdzD22P-py3.9/lib/python3.9/site-packages/cuser/models.py:121
  /home/alex/.cache/pypoetry/virtualenvs/foobar-core-6qdzD22P-py3.9/lib/python3.9/site-packages/cuser/models.py:121: RemovedInDjango40Warning: django.utils.translation.ugettext_lazy() is deprecated in favor of django.utils.translation.gettext_lazy().
    verbose_name_plural = _('users')

../../../.cache/pypoetry/virtualenvs/foobar-core-6qdzD22P-py3.9/lib/python3.9/site-packages/cuser/models.py:157
  /home/alex/.cache/pypoetry/virtualenvs/foobar-core-6qdzD22P-py3.9/lib/python3.9/site-packages/cuser/models.py:157: RemovedInDjango40Warning: django.utils.translation.ugettext_lazy() is deprecated in favor of django.utils.translation.gettext_lazy().
    verbose_name = _('group')

../../../.cache/pypoetry/virtualenvs/foobar-core-6qdzD22P-py3.9/lib/python3.9/site-packages/cuser/models.py:158
  /home/alex/.cache/pypoetry/virtualenvs/foobar-core-6qdzD22P-py3.9/lib/python3.9/site-packages/cuser/models.py:158: RemovedInDjango40Warning: django.utils.translation.ugettext_lazy() is deprecated in favor of django.utils.translation.gettext_lazy().
    verbose_name_plural = _('groups')

../../../.cache/pypoetry/virtualenvs/foobar-core-6qdzD22P-py3.9/lib/python3.9/site-packages/cuser/forms.py:19
  /home/alex/.cache/pypoetry/virtualenvs/foobar-core-6qdzD22P-py3.9/lib/python3.9/site-packages/cuser/forms.py:19: RemovedInDjango40Warning: django.utils.translation.ugettext_lazy() is deprecated in favor of django.utils.translation.gettext_lazy().
    label=_("Email address"),

../../../.cache/pypoetry/virtualenvs/foobar-core-6qdzD22P-py3.9/lib/python3.9/site-packages/cuser/forms.py:26
  /home/alex/.cache/pypoetry/virtualenvs/foobar-core-6qdzD22P-py3.9/lib/python3.9/site-packages/cuser/forms.py:26: RemovedInDjango40Warning: django.utils.translation.ugettext_lazy() is deprecated in favor of django.utils.translation.gettext_lazy().
    label=_("Password"),

../../../.cache/pypoetry/virtualenvs/foobar-core-6qdzD22P-py3.9/lib/python3.9/site-packages/cuser/forms.py:38
  /home/alex/.cache/pypoetry/virtualenvs/foobar-core-6qdzD22P-py3.9/lib/python3.9/site-packages/cuser/forms.py:38: RemovedInDjango40Warning: django.utils.translation.ugettext_lazy() is deprecated in favor of django.utils.translation.gettext_lazy().
    'invalid_login': _(

../../../.cache/pypoetry/virtualenvs/foobar-core-6qdzD22P-py3.9/lib/python3.9/site-packages/cuser/forms.py:42
  /home/alex/.cache/pypoetry/virtualenvs/foobar-core-6qdzD22P-py3.9/lib/python3.9/site-packages/cuser/forms.py:42: RemovedInDjango40Warning: django.utils.translation.ugettext_lazy() is deprecated in favor of django.utils.translation.gettext_lazy().
    'inactive': _("This account is inactive."),

../../../.cache/pypoetry/virtualenvs/foobar-core-6qdzD22P-py3.9/lib/python3.9/site-packages/cuser/forms.py:104
  /home/alex/.cache/pypoetry/virtualenvs/foobar-core-6qdzD22P-py3.9/lib/python3.9/site-packages/cuser/forms.py:104: RemovedInDjango40Warning: django.utils.translation.ugettext_lazy() is deprecated in favor of django.utils.translation.gettext_lazy().
    'password_mismatch': _('The two password fields didn’t match.'),

../../../.cache/pypoetry/virtualenvs/foobar-core-6qdzD22P-py3.9/lib/python3.9/site-packages/cuser/forms.py:112
  /home/alex/.cache/pypoetry/virtualenvs/foobar-core-6qdzD22P-py3.9/lib/python3.9/site-packages/cuser/forms.py:112: RemovedInDjango40Warning: django.utils.translation.ugettext_lazy() is deprecated in favor of django.utils.translation.gettext_lazy().
    label=_("Email address"),

../../../.cache/pypoetry/virtualenvs/foobar-core-6qdzD22P-py3.9/lib/python3.9/site-packages/cuser/forms.py:119
  /home/alex/.cache/pypoetry/virtualenvs/foobar-core-6qdzD22P-py3.9/lib/python3.9/site-packages/cuser/forms.py:119: RemovedInDjango40Warning: django.utils.translation.ugettext_lazy() is deprecated in favor of django.utils.translation.gettext_lazy().
    label=_("Password"),

../../../.cache/pypoetry/virtualenvs/foobar-core-6qdzD22P-py3.9/lib/python3.9/site-packages/cuser/forms.py:125
  /home/alex/.cache/pypoetry/virtualenvs/foobar-core-6qdzD22P-py3.9/lib/python3.9/site-packages/cuser/forms.py:125: RemovedInDjango40Warning: django.utils.translation.ugettext_lazy() is deprecated in favor of django.utils.translation.gettext_lazy().
    label=_("Password confirmation"),

../../../.cache/pypoetry/virtualenvs/foobar-core-6qdzD22P-py3.9/lib/python3.9/site-packages/cuser/forms.py:128
  /home/alex/.cache/pypoetry/virtualenvs/foobar-core-6qdzD22P-py3.9/lib/python3.9/site-packages/cuser/forms.py:128: RemovedInDjango40Warning: django.utils.translation.ugettext_lazy() is deprecated in favor of django.utils.translation.gettext_lazy().
    help_text=_("Enter the same password as before, for verification."),

../../../.cache/pypoetry/virtualenvs/foobar-core-6qdzD22P-py3.9/lib/python3.9/site-packages/cuser/forms.py:179
  /home/alex/.cache/pypoetry/virtualenvs/foobar-core-6qdzD22P-py3.9/lib/python3.9/site-packages/cuser/forms.py:179: RemovedInDjango40Warning: django.utils.translation.ugettext_lazy() is deprecated in favor of django.utils.translation.gettext_lazy().
    label=_("Email address"),

../../../.cache/pypoetry/virtualenvs/foobar-core-6qdzD22P-py3.9/lib/python3.9/site-packages/cuser/forms.py:186
  /home/alex/.cache/pypoetry/virtualenvs/foobar-core-6qdzD22P-py3.9/lib/python3.9/site-packages/cuser/forms.py:186: RemovedInDjango40Warning: django.utils.translation.ugettext_lazy() is deprecated in favor of django.utils.translation.gettext_lazy().
    label=_("Password"),

../../../.cache/pypoetry/virtualenvs/foobar-core-6qdzD22P-py3.9/lib/python3.9/site-packages/cuser/forms.py:187
  /home/alex/.cache/pypoetry/virtualenvs/foobar-core-6qdzD22P-py3.9/lib/python3.9/site-packages/cuser/forms.py:187: RemovedInDjango40Warning: django.utils.translation.ugettext_lazy() is deprecated in favor of django.utils.translation.gettext_lazy().
    help_text=_(

../../../.cache/pypoetry/virtualenvs/foobar-core-6qdzD22P-py3.9/lib/python3.9/site-packages/cuser/admin.py:17
  /home/alex/.cache/pypoetry/virtualenvs/foobar-core-6qdzD22P-py3.9/lib/python3.9/site-packages/cuser/admin.py:17: RemovedInDjango40Warning: django.utils.translation.ugettext_lazy() is deprecated in favor of django.utils.translation.gettext_lazy().
    (_('Personal info'), {'fields': ('first_name', 'last_name')}),

../../../.cache/pypoetry/virtualenvs/foobar-core-6qdzD22P-py3.9/lib/python3.9/site-packages/cuser/admin.py:18
  /home/alex/.cache/pypoetry/virtualenvs/foobar-core-6qdzD22P-py3.9/lib/python3.9/site-packages/cuser/admin.py:18: RemovedInDjango40Warning: django.utils.translation.ugettext_lazy() is deprecated in favor of django.utils.translation.gettext_lazy().
    (_('Permissions'), {'fields': ('is_active', 'is_staff', 'is_superuser',

../../../.cache/pypoetry/virtualenvs/foobar-core-6qdzD22P-py3.9/lib/python3.9/site-packages/cuser/admin.py:20
  /home/alex/.cache/pypoetry/virtualenvs/foobar-core-6qdzD22P-py3.9/lib/python3.9/site-packages/cuser/admin.py:20: RemovedInDjango40Warning: django.utils.translation.ugettext_lazy() is deprecated in favor of django.utils.translation.gettext_lazy().
    (_('Important dates'), {'fields': ('last_login', 'date_joined')}),

AttributeError: type object 'UserAdmin' has no attribute '_meta'

I want to extend the CUser model with custom properties and still have the admin interface working. Currently, I'm getting the above error with the following code.

# models.py

from cuser.models import AbstractCUser

class User(AbstractCUser):
    pass
# admin.py

from cuser.admin import UserAdmin
from .models import *

admin.site.register([User, UserAdmin])

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.