【问题标题】:Django - models design issueDjango - 模型设计问题
【发布时间】:2021-04-23 18:51:54
【问题描述】:

我正在努力在 Django(使用 PostgreSQL)上设计我的模型。

目标是创建一个组系统,用户可以在其中排列项目。一个项目在我的数据库中必须是唯一的。但是我不希望项目在我的数据库中分组。我想要一个属于用户并且可以分组排序的项目列表。

用户拥有对象。然后他可以将它们分组。但他不需要这样做。

我创建了一个属于用户 (User) 的用户项组 (UserItemGroup)。然后,我创建了一个项目模型 (UserItem)。该模型表示用户可以分组的项目。项目可以同时属于多个组,但必须是唯一的!我在UserItem 模型中使用了2 个ForeignKey,但看起来很奇怪……见下文:

class UserItemGroup(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)

    name = models.CharField(max_length=200, blank=False, null=False)
    slug = models.CharField(max_length=200, blank=False, null=False)

class UserItem(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    group = models.ForeignKey(UserItemGroup, on_delete=models.CASCADE)

项目可以这样排列:

user_x
------group_a
------------item_1
------------item_2
------------item_3
------group_b
------------item_1
------------item_4

希望我很清楚,在此先感谢您的帮助。

【问题讨论】:

    标签: python sql django database


    【解决方案1】:

    我认为您不需要 user 中的 UserItem 的 ForeignKey,因为项目是组的一部分,而组取决于用户。

    另外,你说一个项目可以属于多个组,所以关系必须是ManyToManyField

    class UserItem(models.Model):
        group = models.ManyToManyField(UserItemGroup, blank=True)
        name = models.CharField(max_length=200, unique=True)
    

    我添加了一个name 字段并将其设置为唯一,以确保项目的唯一性。 如果项目必须是组的一部分,您可以从 ManyToManyField 中删除 the blank=True

    如果您想从用户那里获取所有项目,您可以这样做:

    UserItem.objects.filter(group__user=user).distinct()
    

    或按组排序:

    for group in user.useritemgroup_set.all():
        print(group.name)
        print(group.useritem_set.all())
    

    【讨论】:

    • 我没有否决这个。不过,这有点不方便,因为我需要请求组和组项目来获取属于用户的所有项目,对吧?这也会返回重复的项目,因为它们可以在多个组中。
    • 您可以在查询中使用 .distinct() 来消除重复项,这是正确的数据库建模
    • 对我来说,物品应该是首要考虑的事情。然后我们考虑将项目分组,你知道我的意思吗?
    • 我不希望项目分组,我希望它们分组排序。虽然组也是包含数据的表。
    • 我已经编辑了我的答案,向您展示如何使用这种设计查询对象,这似乎最适合您的用例。
    【解决方案2】:

    所以我觉得这个设计应该更好:

    class ItemGroup(models.Model):
        # Add next line only if you want to restrict Groups to user (if they are not shared)
        # user = models.ForeignKey(User, on_delete=models.CASCADE)
        name = models.CharField(max_length=200)
        slug = models.CharField(max_length=200)
    
    class UserItem(models.Model):
        user = models.ForeignKey(User, on_delete=models.CASCADE)
        groups = models.ManyToManyField(UserItemGroup, blank=True)
        name = models.CharField(max_length=200, unique=True)
    
        def __str__(self):
            return self.name
    

    然后你可以像这样显示用户的项目:

    # Get all possible groups from the user items
    for group in ItemGroup.objects.filter(useritem__user=user).distinct():
        print(group.name)
        # Display all user items from this group
        print(user.useritem_set.filter(groups=group))
    # Print items that are not in a group
    print(user.useritem_set.filter(groups=None))
    

    【讨论】:

    猜你喜欢
    • 2010-11-23
    • 2018-02-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多