django扩展AbstractUser创建两张用户表,用于维护两种对象,比如一方是卖家,一方是买家。报错,已解决

首先,老样子对于django的AbstractUser的基础上进行扩展,扩展出了两张表。一张是AUser表,一张是BUser表。

但是这个时候发现在创建的时候,看到了满屏的错误,如下:

NO1002.AUser.groups: (fields.E304) Reverse accessor for 'AUser.groups' clashes with reverse accessor for 'BUser.groups'.
    HINT: Add or change a related_name argument to the definition for 'AUser.groups' or 'BUser.groups'.
NO1002.AUser.groups: (fields.E304) Reverse accessor for 'AUser.groups' clashes with reverse accessor for 'User.groups'.
    HINT: Add or change a related_name argument to the definition for 'AUser.groups' or 'User.groups'.
NO1002.AUser.user_permissions: (fields.E304) Reverse accessor for 'AUser.user_permissions' clashes with reverse accessor for 'BUser.user_permissions'.
    HINT: Add or change a related_name argument to the definition for 'AUser.user_permissions' or 'BUser.user_permissions'.
NO1002.AUser.user_permissions: (fields.E304) Reverse accessor for 'AUser.user_permissions' clashes with reverse accessor for 'User.user_permissions'.
    HINT: Add or change a related_name argument to the definition for 'AUser.user_permissions' or 'User.user_permissions'.
NO1002.BUser.groups: (fields.E304) Reverse accessor for 'BUser.groups' clashes with reverse accessor for 'AUser.groups'.
    HINT: Add or change a related_name argument to the definition for 'BUser.groups' or 'AUser.groups'.
NO1002.BUser.groups: (fields.E304) Reverse accessor for 'BUser.groups' clashes with reverse accessor for 'User.groups'.
    HINT: Add or change a related_name argument to the definition for 'BUser.groups' or 'User.groups'.
NO1002.BUser.user_permissions: (fields.E304) Reverse accessor for 'BUser.user_permissions' clashes with reverse accessor for 'AUser.user_permissions'.
    HINT: Add or change a related_name argument to the definition for 'BUser.user_permissions' or 'AUser.user_permissions'.
NO1002.BUser.user_permissions: (fields.E304) Reverse accessor for 'BUser.user_permissions' clashes with reverse accessor for 'User.user_permissions'.
    HINT: Add or change a related_name argument to the definition for 'BUser.user_permissions' or 'User.user_permissions'.
auth.User.groups: (fields.E304) Reverse accessor for 'User.groups' clashes with reverse accessor for 'AUser.groups'.
    HINT: Add or change a related_name argument to the definition for 'User.groups' or 'AUser.groups'.
auth.User.groups: (fields.E304) Reverse accessor for 'User.groups' clashes with reverse accessor for 'BUser.groups'.
    HINT: Add or change a related_name argument to the definition for 'User.groups' or 'BUser.groups'.
auth.User.user_permissions: (fields.E304) Reverse accessor for 'User.user_permissions' clashes with reverse accessor for 'AUser.user_permissions'.
    HINT: Add or change a related_name argument to the definition for 'User.user_permissions' or 'AUser.user_permissions'.
auth.User.user_permissions: (fields.E304) Reverse accessor for 'User.user_permissions' clashes with reverse accessor for 'BUser.user_permissions'.
    HINT: Add or change a related_name argument to the definition for 'User.user_permissions' or 'BUser.user_permissions'.

很惊人是不是。于是在查阅之后发现是不能共用一个外键,因为比如permission这类的表都是靠着用户表的id来维护的,这样创建的话就会导致两张user表,关联的都是同一个permission啊,group表。

另外就是如何扩展的这个表,这里直接上代码:

class AUser(AbstractUser):
    phoneNumber = models.CharField(_('phoneNumber'), max_length=11, blank=False)
    signinposition = models.CharField(_('sign up position'), max_length=90, default='')
    picture = models.ImageField(_('head_ico'), upload_to='Content_img', default=None)

    class Meta(AbstractUser.Meta):
        swappable = 'AUTH_USER_MODEL'

另外要在settings.py中添加一条语句:

AUTH_USER_MODEL = ‘appname.classname’ (比如在我上方的就可以写成: mysite.AUser)

然后我又创建了BUser表,直接参考把A改成B即可。

弄好了之后,就看到了一开始看到的错误。

再我搜了一番之后,发现找到。有的人说干嘛需要维护两张呢?直接加一个列用于区分不就好了吗?其实我刚开始也是这样想的。但是考虑到未来当用户量多的时候,这样可能会很麻烦,于是我还是坚持建两张表。

怎么扩呢,在下不才,只能选择将配套的子类就行定制了,针对于B表,我为它独立copy出了一套,这样再执行./manager makemigrations OK

./manager migrate 

done!

上代码:

import re

from django.db import models
from django.contrib import auth
from django.contrib.contenttypes.models import ContentType
from django.contrib.auth.models import User, AbstractUser, BaseUserManager, Group, Permission, AbstractBaseUser, UserManager
from django.core.mail import send_mail
from django.utils import timezone
from django.utils.translation import gettext,gettext_lazy as _

from django.contrib.auth.validators import UnicodeUsernameValidator

phonenumber_regex = r'^[0-9]{11}$'
phonenumber_regex_compiled = re.compile(phonenumber_regex)

def B_update_last_login(sender, user, **kwargs):
    """
    A signal receiver which updates the last_login date for
    the user logging in.
    """
    user.last_login = timezone.now()
    user.save(update_fields=['last_login'])

class B_UserManager(BaseUserManager):
    use_in_migrations = True

    def _create_user(self, username, phonenumber, email, password, **extra_fields):
        """
        Create and save a user with the given username, email, and password.
        """
        if not username:
            raise ValueError('The given username must be set')
        email = self.normalize_email(email)
        phonenumber = self.normalize_phonenumber(phonenumber)
        username = self.model.normalize_username(username)
        user = self.model(username=username, email=email, phonenumber=phonenumber, **extra_fields)
        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_user(self, username, phonenumber, email=None, password=None, **extra_fields):
        extra_fields.setdefault('is_staff', False)
        extra_fields.setdefault('is_superuser', False)
        return self._create_user(username, phonenumber, email, password, **extra_fields)

    def create_superuser(self, username, email, password, **extra_fields):
        extra_fields.setdefault('is_staff', True)
        extra_fields.setdefault('is_superuser', True)

        if extra_fields.get('is_staff') is not True:
            raise ValueError('Superuser must have is_staff=True.')
        if extra_fields.get('is_superuser') is not True:
            raise ValueError('Superuser must have is_superuser=True.')

        return self._create_user(username, email, password, **extra_fields)

    def normalize_phonenumber(cls, phonenumber):
        if phonenumber_regex_compiled.match(phonenumber_regex) != None:
            return phonenumber
        raise ValueError('Enter a valid Chinese phone number. This value may contain only 11 numbers.')

class B_PermissionManager(models.Manager):
    pass


class B_Permission(models.Model):
    pass

class B_PermissionManager(models.Manager):
    pass

class B_GroupManager(models.Manager):
    pass


class B_Group(models.Model):
    pass

def _user_get_all_permissions(user, obj):
    permissions = set()
    for backend in auth.get_backends():
        if hasattr(backend, "get_all_permissions"):
            permissions.update(backend.get_all_permissions(user, obj))
    return permissions

class B_PermissionsMixin(models.Model):
    """
    Add the fields and methods necessary to support the Group and Permission
    models using the ModelBackend.
    """

    class Meta:
        abstract = True

    def get_group_permissions(self, obj=None):
        """
        Return a list of permission strings that this user has through their
        groups. Query all available auth backends. If an object is passed in,
        return only permissions matching this object.
        """
        return None

    def get_all_permissions(self, obj=None):
        return _user_get_all_permissions(self, obj)

    def has_perm(self, perm, obj=None):
        """
        Return True if the user has the specified permission. Query all
        available auth backends, but return immediately if any backend returns
        True. Thus, a user who has permission from a single auth backend is
        assumed to have permission in general. If an object is provided, check
        permissions for that object.
        """
        # Active superusers have all permissions.
        if self.is_active and self.is_superuser:
            return True

        # Otherwise we need to check the backends.
        return _user_has_perm(self, perm, obj)

    def has_perms(self, perm_list, obj=None):
        """
        Return True if the user has each of the specified permissions. If
        object is passed, check if the user has all required perms for it.
        """
        return all(self.has_perm(perm, obj) for perm in perm_list)

    def has_module_perms(self, app_label):
        """
        Return True if the user has any permissions in the given app label.
        Use similar logic as has_perm(), above.
        """
        # Active superusers have all permissions.
        if self.is_active and self.is_superuser:
            return True

        return _user_has_module_perms(self, app_label)

class B_AbstractUser(AbstractBaseUser, B_PermissionsMixin):
    """
    An abstract base class implementing a fully featured User model with
    admin-compliant permissions.

    Username and password are required. Other fields are optional.
    """
    username_validator = UnicodeUsernameValidator()

    username = models.CharField(
        _('username'),
        max_length=150,
        unique=True,
        help_text=_('Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.'),
        validators=[username_validator],
        error_messages={
            'unique': _("A user with that username already exists."),
        },
    )
    first_name = models.CharField(_('first name'), max_length=30, blank=True)
    last_name = models.CharField(_('last name'), max_length=150, blank=True)
    email = models.EmailField(_('email address'), blank=True)
    is_staff = models.BooleanField(
        _('staff status'),
        default=False,
        help_text=_('Designates whether the user can log into this admin site.'),
    )
    is_active = models.BooleanField(
        _('active'),
        default=True,
        help_text=_(
            'Designates whether this user should be treated as active. '
            'Unselect this instead of deleting accounts.'
        ),
    )
    date_joined = models.DateTimeField(_('date joined'), default=timezone.now)

    objects = B_UserManager()

    EMAIL_FIELD = 'email'
    USERNAME_FIELD = 'username'
    REQUIRED_FIELDS = ['email']

    class Meta:
        verbose_name = _('B_user')
        verbose_name_plural = _('B_users')
        abstract = True

    def clean(self):
        super().clean()
        self.email = self.__class__.objects.normalize_email(self.email)

    def get_full_name(self):
        """
        Return the first_name plus the last_name, with a space in between.
        """
        full_name = '%s %s' % (self.first_name, self.last_name)
        return full_name.strip()

    def get_short_name(self):
        """Return the short name for the user."""
        return self.first_name

    def email_user(self, subject, message, from_email=None, **kwargs):
        """Send an email to this user."""
        send_mail(subject, message, from_email, [self.email], **kwargs)

class AUser(AbstractUser):
    phoneNumber = models.CharField(_('phoneNumber'), max_length=11, blank=False)
    signinposition = models.CharField(_('sign up position'), max_length=90, default='')
    picture = models.ImageField(_('head_ico'), upload_to='Content_img', default=None)

    class Meta(AbstractUser.Meta):
        swappable = 'AUTH_USER_MODEL'

class BUser(B_AbstractUser):
    phoneNumber = models.CharField(_('phoneNumber'), max_length=11, blank=False)
    signinposition = models.CharField(_('sign up position'), max_length=90, default=None)
    picture = models.ImageField(_('head_ico'), upload_to='Content_img', default=None)

    class Meta(B_AbstractUser.Meta):
        verbose_name = 'B_user'



 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

loo00000op

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值