【问题标题】:How to set up Django models with two types of users with very different attributes如何设置具有两种不同属性的用户类型的 Django 模型
【发布时间】:2012-10-07 06:35:10
【问题描述】:

注意:自 asked this question again 以来,我已经从 1.5 版开始更新了 Django 的用户模型。

我正在重建和改进现有的 Django 站点,并将其从 Webfaction 转移到 Heroku,从 Amazon 的 SimpleDB 转移到 Heroku Postgres(尽管在开发时在 Sqllite3 上进行本地测试)。我正在做的很多事情都是转而使用内置的 Django 功能,例如 Django 管理员、用户身份验证等。

从概念上讲,该网站有两种用户:学生和企业。这两种类型的用户具有完全不同的权限和存储的有关他们的信息。如此多的情况,在网站的原始结构中,我们设置数据模型如下:

Users
    ID (primary_key)
    Business_or_Student ('B' if business, 'S' if student)
    email (unique)
    password (hashed, obviously)
    ...

Students
    ID (Foreignkey on Users)
    <more information>
    ...

Businesses
    ID (Foreignkey on Users)
    <more information>
    ...

这对我们来说非常有效,我们在“用户”表中拥有基本的用户信息,然后在“学生”和“企业”表中拥有更详细的信息。获取用户的完整个人资料需要以下伪代码:

def get_user_profile(id):
    if Users(id=id).Business_or_Student = 'B':
        return Businesses(id=id)
    else:
        return Students(id=id)

在移动过程中,我发现 Django 的内置 User 对象的功能非常有限,我不得不使用我创建的 UserProfile 类对其进行扩展,然后添加了额外的 @987654326 @ 和 Business 表。鉴于我在 Django 管理员中对此进行的所有修补,并且对 Django 模型相对不熟悉,因为我总是以不同的方式进行操作,我不确定这是否是最好的方法,或者我是否应该只需将企业和学生的所有信息粘贴在 UserProfile 表中,然后将两者与不同的组区分开来,或者如果在内置的 User 中甚至有某种方法可以做到这一点对象。

由于企业和学生也有不同的界面,我正在认真考虑在我的 Django 项目中将两者设置为不同的应用程序,从而完全分离它们的视图、模型等。这看起来像:

MyProject/
    MyProject/ (project folder, Django 1.4)
    mainsite/
    students/
    businesses/

我最大的担忧之一是 Django Admin。在扩展User 时,我已经必须添加以下代码:

class UserProfileInline(admin.StackedInline):
    model = UserProfile
    can_delete = False
    verbose_name_plural = 'profile'

class UserAdmin(UserAdmin):
    inlines = (UserProfileInline, )

但是,当User 被拉起时,我希望用户的商业或学生方面的信息显示在 Django 管理员中,但模型的 ForeignKey 部分在 Student 中和Business 模型,因为每个Student/Business 都有一个User,但每个User 只有一个Student 一个Business 与之连接的对象。我不确定如何为管理员添加条件内联。

问题:鉴于这种结构和这些问题,建立此站点的最佳方式是什么,尤其是数据模型?

【问题讨论】:

    标签: python database-design heroku django-models django-1.4


    【解决方案1】:

    这不是一个完整的解决方案,但它会让您知道从哪里开始。

    • mainsite 中创建UserProfile 模型。这将包含两种类型用户的任何共同属性。使用 OneToOne(...) 字段将其与 User 模型相关联。
    • 在每个应用程序中再创建两个模型,(学生/企业)BusinessStudent,它们具有 OneToOne 关系,每个模型都与 UserProfile(或从 UserProfile 继承)。这将包含特定于该类型用户的属性。文档:Multitable inheritance / OneToOne Relationships
    • 可以UserProfile 中添加一个字段来区分它是企业还是学生的个人资料。

    然后,对于内容管理:

    • 定义 save() 函数以自动检查冲突(例如,BusinessStudent 都有一个与 UserProfile 关联的条目,或者没有条目)。
    • 在必要时定义__unicode__() 表示。

    【讨论】:

    • 我一开始是这样做的,但后来我将StudentUserProfile 之间的OneToOne 关系切换为StudentUser,因为Django 管理员无法识别用户名UserProfile 对象的 /email,因为它们存储在 User 而不是 UserProfile。添加新企业时,OneToOne 关系下拉列表会一遍又一遍地列出UserProfile Object,直到我将其更改为User,然后它才开始列出用户名。我担心其他地区会发生类似的事情。你知道怎么处理吗?
    • 是的,UserProfile 链接到User,django 用它来代表用户。要掩盖您的下拉问题,请在UserProfile 中添加__unicode__() 方法以返回self.user.username。这是在下拉列表中显示用户名,但仍将链接到 UserProfile
    • 谢谢,最后一点是天才。我将把这个问题搁置几天,看看我得到了哪些其他回复,但你的帮助非常大。
    【解决方案2】:

    我希望我理解你的问题......也许这可以工作?您创建一个抽象的 CommonInfo 类,该类被继承到不同的子类(学生和企业)中

    class CommonUser(models.Model):      
        user = models.OneToOne(User)
        <any other common fields>
    
        class Meta:
            abstract = True
    
    
    class Student(CommonUser):
        <whatever>
    
    class Business(CommonUser):
        <whatever>
    

    在这种情况下,模型将在数据库中创建,每个表中都有基类字段。因此,当您与学生一起工作时,您会运行一个

    students = Students.objects.get.all() 
    

    获取所有学生,包括公共信息。

    那么对于你所做的每个学生:

    for student in students:
        print student.user.username
    

    业务对象也是如此。

    让学生使用用户:

    student = Student.objects.get(user=id)
    

    用户名将是唯一的,因此在创建新的学生或企业时,如果正在保存现有用户名,则会引发异常。

    忘记添加link

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-01-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-28
      • 2012-09-12
      • 2014-12-09
      • 1970-01-01
      相关资源
      最近更新 更多