首页 > 解决方案 > 根据 Django 数据库中的当前项目数生成默认值 - 循环导入问题

问题描述

我正在处理一个 Django 项目,但我真的不知道如何避免 Django 模型和自定义 python 文件之间的循环导入generators.py

帐户/模型.py

from django.db import models
from django.utils.translation import gettext_lazy as _
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin, BaseUserManager
from django.utils import timezone

from core.generators import make_id_number
class UserManager(BaseUserManager):

    def create_user(self, email, username, fname, lname, password, **others):
        
        if not email:
            raise ValueError(_('Please Provide Email Address!'))
        if not username:
            raise ValueError(_('Please Provide User Name!'))
        if not fname:
            raise ValueError(_('Please Provide First Name!'))
        if not lname:
            raise ValueError(_('Please Provide Last Name!'))
        
        email = self.normalize_email(email)
        user = self.model(
            email=email,
            username=username,
            fname=fname,
            lname=lname,
            password=password,
            **others
        )
        user.set_password(password)
        user.save()
        return user

    def create_superuser(self, email, username, fname, lname, password, **others):

        others.setdefault('is_staff', True)
        others.setdefault('is_superuser', True)
        others.setdefault('is_active', True)

        if others.get('is_staff') is False:
            raise ValueError(_('Superuser must have \'staff\' permissions!'))
        if others.get('is_active') is False:
            raise ValueError(_('Superuser must be active!'))
        if others.get('is_superuser') is False:
            raise ValueError(_('Superuser must have \'superuser\' permissions!'))

        return self.create_user(email, username, fname, lname, password, **others)

class User(AbstractBaseUser, PermissionsMixin):

    email = models.EmailField(_('Email'),max_length=150,unique=True)
    username = models.CharField(_('Username'),max_length=150,unique=True)
    fname = models.CharField(_('First Name'),max_length=150)
    mname = models.CharField(_('Middle Name'),max_length=150,null=True,blank=True)
    lname = models.CharField(_('Last Name'),max_length=150)
    date_joined = models.DateTimeField(_('Date Joined'),default=timezone.now)
    last_login = models.DateTimeField(_('Last Login'),auto_now=True)
    is_staff = models.BooleanField(_('Staff'),default=False)
    is_active = models.BooleanField(_('Active'),default=False)
    is_superuser = models.BooleanField(_('Superuser'),default=False)

    objects = UserManager()
    
    EMAIL_FIELD = 'email'
    USERNAME_FIELD = 'username'
    REQUIRED_FIELDS = ['email', 'fname' , 'lname']

    def __str__(self):
        return self.username

    def get_full_name(self):
        full_name = (f'{self.fname} {self.lname}')
        return full_name.strip()

    def get_short_name(self):
        return self.fname

class UserIdentification(models.Model):

    user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True)
    id_number = models.BigIntegerField(_('ID Number'), default=make_id_number, unique=True)
    reg_code = models.CharField(_('Registration Code'), max_length=150, unique=True)

    def __str__(self):
        return (f'{self.user.username}-{self.id_number:09d}')

核心/发电机.py

import pytz

from django.utils.crypto import get_random_string
from django.utils import timezone
from django.conf import settings

from accounts.models import UserIdentification

# Generate a random password with the given length and given allowed_chars.
# The default value of allowed_chars does not have "I" or "O" or letters and digits that look similar to avoid confusion.
def make_random_password(length=12, allowed_chars='!@#$%^&*()_+-=abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789'):
    return get_random_string(length, allowed_chars)


def make_id_number(local_tz=settings.TIME_ZONE):

    local_tz = pytz.timezone(local_tz)
    local_date = local_tz.normalize(timezone.now()).date()

    mm=int(local_date.month)
    dd=int(local_date.day)
    yy=int(local_date.year-2000)
    ccc=int(UserIdentification.objects.all().count())
    # ccc=0

    id_number=int(f'{mm:02d}{dd:02d}{yy:02d}{ccc+1:03d}')
    return id_number

如您所见,这肯定会导致循环导入问题,因为我make_id_number从中导入core/generators.py会查询数据库中使用模型UserIdentificationfrom的当前用户数accounts/models.py,这反过来会要求core\generators.py生成一个 id 号。

我将非常感谢任何能给我解决方案、提示或教程的人,我该如何避免这种情况。

标签: pythondjangocircular-dependency

解决方案


在python中有一个避免循环导入的技巧

只导入模块,不从模块导入

在模型.py 中: import core.generators

在 generators.py 中:import accounts.models


推荐阅读