【问题标题】:Django intermediate table with a many-to-many field instead foreign key?具有多对多字段而不是外键的Django中间表?
【发布时间】:2019-08-19 09:51:03
【问题描述】:

我的应用中有 2 个模型:

  • 用户

我的目标是使用中间表将许多塔与用户相关联,因为我需要添加一段时间。

所以我的模型中有这样的东西:

class Tower(models.Model):
    name = models.CharField(max_length=128)

class User(models.Model):
    name = models.CharField(max_length=128)
    members = models.ManyToManyField('Tower', through='Dates')

class Dates(models.Model):
    user = models.ForeignKey('User', on_delete=models.CASCADE)
    tower = models.ForeignKey('Tower', on_delete=models.CASCADE)
    begin_date = models.DateTimeField()
    end_date = models.DateTimeField()

但我的目标是在类 Dates 中将字段塔设置为这样的多对多:

tower = models.ManyToManyField('Tower', blank=True)

这样我就可以在某个时间段内将许多塔与用户相关联。但不幸的是,django 说我需要对 Tower 和 User 类使用 forgeignkey。

对此有什么解决办法吗?直接应用中间表中的多对多字段?或者我必须创建一个新类,类似于 GroupTower,它与 Tower 类具有多对多字段?像这样的:

class Tower(models.Model):
    name = models.CharField(max_length=128)

class GroupTower(models.Model):
    tower = models.ManyToManyField('Tower', blank=True)

class User(models.Model):
    name = models.CharField(max_length=128)
    members = models.ManyToManyField('Tower', through='Dates')

class Dates(models.Model):
    user = models.ForeignKey('User', on_delete=models.CASCADE)
    tower = models.ForeignKey('GroupTower', on_delete=models.CASCADE)
    begin_date = models.DateTimeField()
    end_date = models.DateTimeField()

提前致谢。

【问题讨论】:

    标签: django many-to-many django-database django-intermediate-table


    【解决方案1】:

    有很多方法可以设计数据库。

    一个例子:

    class Tower(models.Model):
        name = models.CharField(max_length=128)
    
    class User(models.Model):
        name = models.CharField(max_length=128)
        members = models.ManyToManyField('UserTower')
    
    class UserTower(models.Model):
        user = models.ForeignKey('User', on_delete=models.CASCADE)
        tower = models.ManyToManyField('Tower')
        begin_date = models.DateTimeField()
        end_date = models.DateTimeField()
    

    在此设计中,您可以向用户添加多个 UserTower 实例,并且每个 UserTower 实例可以有许多塔。

    现在,如果您为用户查询成员:

    User.objects.get(pk=1).members.all()
    

    如果您以这种方式保存成员,您将拥有按时间段分组的成员,但这需要您编写一些代码以避免 begin_datebegin_dateuser 重复。

    现在如果你需要塔:

    user_members = User.objects.get(pk=1).members.all().values_list('tower', flat=True)
    towers = Tower.objects.filter(pk__in=user_members).distinct()
    

    只有当你真的不希望有相同的 begin_datebegin_date 重复时,这种设计才可以,我找不到原因。

    如果您添加多个具有相同begin_datebegin_dateuser 但不同tower 的实例,您仍然可以拥有所有功能。

    【讨论】:

    • 这正是我所期待的。非常感谢您的帮助。
    猜你喜欢
    • 1970-01-01
    • 2016-09-07
    • 2023-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-17
    • 1970-01-01
    相关资源
    最近更新 更多