django 我应该继承用户模型吗

bvpmtnay  于 2023-11-20  发布在  Go
关注(0)|答案(1)|浏览(138)

我还有另外两个模型,它们应该拥有User模型的所有功能。这就是为什么在这两个模型中,我继承了User模型。

default_role = "admin"

class User(AbstractBaseUser):
   ...
   image = models.ImageField(upload_to=user_directory_path, blank=True, null=True)
   role = models.CharField(max_length=20, choices=ROLE_CHOICE, default=default_role)
   ....

class Student(User):
   ...
   some_fields_related_to_student
   ...
   def save():
      self.role = "student"

class Teacher(User):
   ...
   some_fields_related_to_teacher
   ...
   def save():
       self.role = "teacher"

个字符
当我试图把教师和学生模型的图像图片,我想把他们:

".../teachers/{teacher.id}.{extension}" 
".../students/{student.id}.{extension}" these folders.


如何将角色字段传递给user_directory_path函数,或者在这种情况下最好的做法是什么?将图像放在与其模型相关的文件夹中是否正确?
另外,我的另一个问题是,我应该从User继承吗?每当我创建Student或Teacher时,它也会在User中创建该模型,但对我来说,它看起来不是最佳的,因为我们有点重复信息

ryhaxcpt

ryhaxcpt1#

这种方法可能会给您的项目带来一些问题,例如:
1.身份验证复杂性
1.形式和视图的复杂性
1.角色转变
1.添加不必要和不需要的连接到所有SQL示例
为了解决这些问题,让我们探索一些最佳实践:
如果你要开始一个新项目,强烈建议你设置一个自定义的用户模型,即使默认的用户模型已经足够了。这个模型的行为和默认的用户模型是一样的,但是如果将来有需要,你可以自定义它。Django doc
2.2配置文件型号:
要处理不同的用户角色,请考虑使用配置文件模型。您可以为每个角色创建单独的配置文件类,并使用OneToOneField将它们链接到用户模型。这种方法减少了代码重复,并通过select_related更好地控制数据库连接。下面是一个示例实现:

from django.contrib.auth.models import AbstractUser
from django.db import models

class User(AbstractUser):
    # Common fields and methods here

class Teacher(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    # Teacher-specific fields here

class Student(models.Model):
    user = models.OneToOneField User, on_delete=models.CASCADE)
    # Student-specific fields here

class Employee(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    # Employee-specific fields here

字符串
此外,如果您担心教师和学生模型的单独图片文件夹,则可以使用upload_to属性并自定义存储。

def user_directory_path(instance, filename):
    # Determine the user's role
    role = "other"
    if hasattr(instance, 'teacher'):
        role = 'teacher'
    elif hasattr(instance, 'student'):
        role = 'student'
    elif hasattr(instance, 'employee'):
        role = 'employee'

    # Create a directory structure based on the user's role
    return f"user_{instance.user.id}/{role}/{filename}"

class User(AbstractUser):
    # Common fields and methods here
    upload = models.FileField(upload_to=user_directory_path)


另一种选择是使用FileSystemStorage进行更多的自定义。

from django.core.files.storage import FileSystemStorage

class UserRoleStorage(FileSystemStorage):
    def get_user_role(self, instance):
       # Determine the user's role here

    def _save(self, name, content):
        # Get the user's role
        user_role = self.get_user_role(self.instance)

        # Construct the dynamic upload path
        path = f"user_{self.instance.user.id}/{user_role}/{name}"

        # Call the parent class to save the file
        return super()._save(path, content)

class User(models.Model):
    upload = models.FileField(storage=UserRoleStorage())


2.3使用JSONField:
另一种方法是使用JSONField来处理配置文件数据。在模型方面很简单,但在处理视图、权限和验证时可能会有挑战性。下面是一个例子:

class RoleType(models.IntegerChoices):
    Student = 1

def get_default_dynamic_field_definitions():
    return {}

class User(models.Model):
    data = models.JSONField(default=get_default_dynamic_field_definitions)
    role = models.IntegerField(choices=RoleType.choices)

    def save(self, *args, **kwargs):
        # Update self.data here
        return super().save(*args, **kwargs)


2.4动态配置文件字段生成器模式:
对于更复杂但更灵活的解决方案,请考虑使用动态配置文件字段构建器模式。这种方法允许您在视图中定义字段。下面是一个基本示例:

class User(AbstractUser):
    ...
class DynamicField(models.Model):
    STANDARD_FIELD_TYPES = (
        (models.CharField, 'Text'),
        (models.EmailField, 'Email'),
        (models.IntegerField, 'Integer'),
        (models.DateField, 'Date'),
        # Add more standard field types as needed
    )

    f_name = models.CharField(max_length=255, help_text="Field Name")
    f_type = models.CharField(max_length=20, choices=STANDARD_FIELD_TYPES, help_text="Field Type")
    f_validator = models.CharField(max_length=255, blank=True, help_text="Field Validator (optional)")
    f_default = models.CharField(max_length=255, blank=True, help_text="Field Default Value (optional)")
    user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='dynamic_fields')

dynamic_fields = DynamicField.objects.filter(user=user_instance)


2.5模型代理:您还可以探索模型代理功能,以扩展现有的模型方法,而无需更改它们的行为。

from django.db import models

class User(AbstractUser):
        # Your common fields and methods here

class Teacher(User):
    class Meta:
        proxy = True

    def do_something(self):
        # ...
        pass

class Student(User):
    class Meta:
        proxy = True

    def do_something(self):
        # ...
        pass

相关问题