sqlite Django extend AbstractUser no such table error

xxhby3vn  于 2023-05-23  发布在  SQLite
关注(0)|答案(4)|浏览(162)

我试图在python 3.8.0上扩展django 3.0.1(drf==3.10.3)AbstractUser。我得到no such table <appName>_user错误时,试图登录管理页面和JWT。
我的项目目录结构:

root
-|app
--|<projectName>
---|<appName>
---|statics
---|__init__.py
---|settings.py
---|urls.py
---|wsgi.py
---|asgi.py
--|manage.py
--|.env
--|db.sql

我的app/projectName/appName/migrationsapp/projectName/appName/tests上有__init__.py
以下是settings.py文件的相关部分:

BASE_DIR = os.path.join(os.path.dirname(os.path.dirname(
    os.path.abspath(__file__))), '<projectName>/')

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework',
    'drf_yasg',  # openapi

    # local
    '<projectName>.<appName>',
]

if DEBUG:
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.sqlite3',
            'NAME': env.str('DATABASE_NAME', 'db.sqlite3'),
            'HOST': env.str('DATABASE_HOST', os.path.join(BASE_DIR, 'db.sqlite3')),
            'PORT': env.int('DATABASE_PORT', '5000')
        },
        'test': {
            'ENGINE': 'django.db.backends.sqlite3',
            'NAME': env.str('DATABASE_NAME', 'testing.sqlite3'),
            'HOST': env.str('DATABASE_HOST', os.path.join(BASE_DIR, 'testing.sqlite3')),
            'PORT': env.int('DATABASE_PORT', '5000')
        }
    }
else:
    DATABASES = {
        'default': env.db(),
    }

AUTH_USER_MODEL = '<appName>.User'

我的appName/models.py的相关部分:

class User(AbstractUser):

    role = models.CharField(
        max_length=15,
        choices=[(tag, tag.value)
                 for tag in UserRolesChoise]  # Choices is a list of Tuple
    )
    is_vendor = models.BooleanField(
        _('vendor status'),
        default=False,
        help_text=_(
            'Designates whether the user is a vendor.'),
    )
    is_customer = models.BooleanField(
        _('customer status'),
        default=True,
        help_text=_(
            'Designates whether the user is a customer.'),
    )

    def __str__(self):
        return self.username

我的appName/serializers.py的相关部分:

from rest_framework import serializers
from django.contrib.auth import get_user_model

User = get_user_model()

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ('username', 'email', 'last_login', 'first_name', 'last_name',
                  'get_full_name', 'is_staff', 'is_active', 'date_joined', 'is_vendor', 'is_customer')

我的appName/urls.py的相关部分:

from django.urls import path, re_path, include
from django.contrib import admin
from rest_framework import routers
from .<appName> import views

router = routers.DefaultRouter()
router.register(r'users', views.UserViewSet)

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/v1/', include(router.urls))
]

我的appName/views.py的相关部分:

from rest_framework import viewsets
from .serializers import UserSerializer
from .premissions import IsOwnerOrAdmin

from django.contrib.auth import get_user_model
User = get_user_model()

class UserViewSet(viewsets.ModelViewSet):
    """
    API endpoint that allows users to be viewed or edited.
    """
    queryset = User.objects.all().order_by('-date_joined')
    serializer_class = UserSerializer
    permission_classes = [IsOwnerOrAdmin,]

我的appName/apps.py的相关部分:

from django.apps import AppConfig

class <AppName>Config(AppConfig):
    name = '<appName>'

这是一个正在开发的系统,所以我尝试通过在我的应用程序文件夹上运行以下命令来删除所有迁移和数据库:

find . -path "*/migrations/*.py" -not -name "__init__.py" -delete
find . -path "*/migrations/*.pyc"  -delete
rm db.sqlite3
python manage.py makemigrations
python manage.py migrate
python manage.py createsuperuser

奇怪的事情:当我运行python manage.py dbshell并输入.tables时,显示的是我的<appname>_user
我的一些位于<appName>/tests/test_*.py的测试通过得很好:

from rest_framework import status
from rest_framework.test import APITestCase

from django.contrib.auth import get_user_model
User = get_user_model()

class UserModelTestCase(APITestCase):
    """ Test module for User model """

    def setUp(self):
        super(UserModelTestCase, self).setUp()
        self.given_user_exists(first_name='Test', last_name='Customer', email="customer@gmail.com",  password="7789",
            username="Test Customer", role='Customer')
        self.given_user_exists(
            first_name='Test', last_name='Vendor', email="vendor@gmail.com", password="7789",
            username="Test Vendor",
            role='Vendor', is_vendor=True, is_customer=False)
        self.given_user_exists(
            first_name='Test', last_name='Staff', email="stff@gmail.com", password="7789",
            username="Test Staff",
            role='Admin', is_customer=False, is_staff=True)

        self.user_customer=User.objects.get(username='Test Customer')
        self.user_vendor=User.objects.get(username='Test Vendor')
        self.user_staff=User.objects.get(username='Test Staff')

    def tearDown(self):
        super(UserModelTestCase, self).tearDown()

    def test_all_users_hidden_for_anonymous_users(self):
        all_users = self.client.get('/api/v1/users/')
        self.assertEqual(all_users.status_code,status.HTTP_401_UNAUTHORIZED)

我的代码中所有的和都没有使用<>。
这让我觉得这是一个DB问题,但我不明白这个问题。

f3temu5u

f3temu5u1#

meta类中有abstract = True,请检查Usermodel。如果存在,请删除此行。
如果它具有abstract = True属性,则该模型将不会用于创建任何数据库表。就像你的情况一样。

ylamdve6

ylamdve62#

您还需要实现自己的BaseUserManager。在您的models.py上添加以下代码

from django.contrib.auth.base_user import BaseUserManager

class UserManager(BaseUserManager):
    use_in_migrations = True

    def _create_user(self, email, password, **extra_fields):
        if not email:
            raise ValueError('The given email must be set')
        email = self.normalize_email(email)
        user = self.model(email=email, **extra_fields)
        user.set_password(password)
        user.save(using=self._db)
        return user

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

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

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

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

希望这有帮助!

t8e9dugd

t8e9dugd3#

我不得不继续这个项目,所以我做了我能想到的不太聪明的事情--逃避这个问题,我现在确信这是一个设置问题。
如果这能帮到谁,我这么做:
1.我为项目创建了一个新的根目录。
1.在这个文件夹中,我运行了python manage.py start app <appName>来创建我的应用程序。以下是我目前的档案:

root
-|<projectName>
--|<projectName>
---|__init__.py
---|settings.py
---|urls.py
---|wsgi.py
---|asgi.py
--|<appName>
---|apps.py
---|views.py
---|_init__.py
---|serializers.py
---|etc...
--|statics
--|manage.py
--|.env
--|db.sql

1.删除了db.sql文件、迁移和__pycache__文件夹。
1.已从原始文件夹复制相关代码段。
1.根据新项目更改了设置和导入。

TL;DR一旦我创建了新的项目结构,删除了迁移,__pycache__文件夹和DB文件,一切都正常。

kiayqfof

kiayqfof4#

一个可行的解决方案可能是删除db.sql文件并运行命令进行迁移和迁移。

相关问题