@9550668

Django. Models. Как избавиться от нерадактируемых полей?

Всем доброго времени суток.

У меня есть UserModel, основаная на AbstractBaseUser.

В данной модели требуется для регистрации пользователя ввод только мобильного телефона; основные поля, включая username, генерируются автоматически(по плану их потом можно отредактировать - так быстрее пройти регистрацию).

В итоге, все работает, однако обнаружил в админ панели, что, к примеру, username не обновляет значение, если я хочу изменить username впоследствии. Т.е. - readonly. Как побороть?

П.С. Есть вопрос в догонку.
username генерируется автоматически: username = "username"+id.
Как путь реализации вношу в Модель запись(username - blank) по номеру телефона, потом забираю из записи созданный id, присоединяю "username"+полученный id и обновляю запись.
Может есть более изящный способ?

models.py:
from django.conf import settings
from django.contrib.auth.models import (
    BaseUserManager, AbstractBaseUser
)

from django.core.validators import RegexValidator
from django.db import models
from django.db.models.signals import post_save
from django.dispatch import receiver
from rest_framework.authtoken.models import Token

import phonenumbers


class UsersManager(BaseUserManager):
    def create_user(self, mobile, password=None):
        """
        Creates and saves a User with the given username and password.
        """
        country_code = phonenumbers.parse(mobile, None)
        user = self.model(
            mobile=mobile,
        )
        user.country_code = country_code.country_code
        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_superuser(self, mobile, password):
        """
        Creates and saves a superuser with the given username, mobile and password
        """
        country_code = phonenumbers.parse(mobile, None)
        user = self.create_user(
            mobile=mobile,
            password=password,
        )
        user.country_code = country_code.country_code
        user.is_admin = True
        user.is_worker = True
        user.save(using=self._db)
        user.username="username"+str(user.id)
        user.email = user.username+"@users.com"
        user.save(using=self.db)
        return user

USERNAME_REGEX = '^[a-zA-Z0-9.@+-]*$'
MOBILE_REGEX = '^\+\d*$'

class Users(AbstractBaseUser):
    username                    = models.CharField(
                                                max_length=50,
                                                unique=True,
                                                validators=[
                                                            RegexValidator(
                                                            regex= USERNAME_REGEX,
                                                            message='Username field can only be Alphanameric or contain additional ., @, +, -',
                                                            code='invalid_username')]
                                                )
    email                       = models.EmailField(
                                                verbose_name='email address',
                                                max_length=155,
                                                unique=True,
                                                blank=True
                                                )
    mobile                      = models.CharField(
                                                unique=True,
                                                max_length=50,
                                                verbose_name="Mobile phone number",
                                                validators=[
                                                            RegexValidator(
                                                            regex=MOBILE_REGEX,
                                                            message='Wrong mobile number sequence',
                                                            code='Invalide mobile number')]
                                                )
    country_code                = models.IntegerField(verbose_name="Country", default=1)
    date_of_birth               = models.DateField(blank=True, default="2000-01-01")
    registered_date             = models.DateTimeField(auto_now_add=True)
    is_active                   = models.BooleanField(default=True)
    is_worker                   = models.BooleanField(default=False)
    is_admin                    = models.BooleanField(default=False)

    objects = UsersManager()

    USERNAME_FIELD = 'mobile'
    #REQUIRED_FIELDS = ['mobile']

    def save(self, *args, **kwargs):
        '''
        Rewritten Save function for Model Users
        '''
        super().save(*args, **kwargs)
        Users.objects.filter(id=self.id).update(email="username"+str(self.id)+"@users.com")
        Users.objects.filter(id=self.id).update(username="username"+str(self.id))
        Users.objects.filter(id=self.id).update(country_code = phonenumbers.parse(self.mobile, None).country_code)
        print(self.username, self.email)

    def __str__(self):
        return self.username


    class Meta:
        verbose_name = "User"
        verbose_name_plural = "Users"


admin.py:
from django import forms
from django.contrib import admin
from django.contrib.auth.models import Group
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from django.contrib.auth.forms import ReadOnlyPasswordHashField

from .models import Users
from .forms import UserChangeForm, UserCreationForm


class UserAdmin(BaseUserAdmin):
    # The forms to add and change user instances
    form = UserChangeForm
    add_form = UserCreationForm

    # The fields to be used in displaying the User model.
    # These override the definitions on the base UserAdmin
    # that reference specific fields on auth.User.
    list_display = ('username', 'email', 'mobile', 'country_code', 'date_of_birth', 'registered_date', 'is_admin', 'is_worker')
    list_filter = ('is_admin',)
    fieldsets = (
        (None, {'fields': ('username', 'email', 'mobile', 'password')}),
        ('Personal info', {'fields': ('date_of_birth', 'country_code')}),
        ('Permissions', {'fields': ('is_admin', 'is_worker')}),
    )

    add_fieldsets = (
        (None, {
            'classes': ('wide',),
            'fields': ('mobile', 'is_worker', 'is_admin'),
        }),
    )
    search_fields = ('username', 'email',)
    ordering = ('username', 'email',)
    filter_horizontal = ()


# Now register the new UserAdmin...
admin.site.register(Users, UserAdmin)
# ... and, since we're not using Django's built-in permissions,
# unregister the Group model from admin.
admin.site.unregister(Group)
  • Вопрос задан
  • 72 просмотра
Пригласить эксперта
Ответы на вопрос 1
@bacon
1. Все остальные поля можно просто делать null=True, blank=True и не заполнять их
2. Если username генерируется автоматически, то сделать его свойством
@property
def username(self):
    return f'username{self.id}'
потом когда потребуется, сделаете поле в базе, может до этого и не дойдет

И не нужно будет так извращаться с save.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы
05 авг. 2020, в 21:55
20000 руб./за проект
05 авг. 2020, в 20:58
10000 руб./за проект
05 авг. 2020, в 20:21
10000 руб./за проект