Django ManyToManyField 使用 through 排序

29 投票
7 回答
27597 浏览
提问于 2025-04-16 05:13

这是我模型设置的一部分:

class Profile(models.Model):     
    name = models.CharField(max_length=32)

    accout = models.ManyToManyField(
        'project.Account',
        through='project.ProfileAccount'
    )

    def __unicode__(self)
        return self.name

class Accounts(models.Model):
    name = models.CharField(max_length=32)
    type = models.CharField(max_length=32)

    class Meta:
        ordering = ('name',)

    def __unicode__(self)
        return self.name

class ProfileAccounts(models.Model):
    profile = models.ForeignKey('project.Profile')
    account = models.ForeignKey('project.Accounts')

    number = models.PositiveIntegerField()

    class Meta:
        ordering = ('number',)

然后当我访问账户时,怎样才能按照中间的 ProfileAccounts 模型里的 'number' 来排序,而不是默认的 Accounts 模型里的 'name' 呢?

for acct_number in self.profile.accounts.all():
    pass

这个方法不行,但大致上是我想要用来访问这些数据的方式:

for scanline_field in self.scanline_profile.fields.all().order_by('number'):
    pass

7 个回答

5

一个ManyToManyField管理器让你可以直接从相关模型中选择或过滤数据,而不需要在Django层面使用任何通过模型的连接...

同样,

如果你尝试:

pr = Profile.objects.get(pk=1)
pr.account.all()

这会返回与该个人资料相关的所有账户。正如你所看到的,ProfileAccount这个通过模型并没有直接的关系,所以在这个时候你不能使用M2M关系...你必须使用反向关系来连接通过模型,并过滤结果...

pr = Profile.objects.get(pk=1)
pr.profileaccount_set.order_by('number')

这会给你一个有序的查询集,但在这种情况下,你得到的查询集是profileaccount对象,而不是账户对象...所以你需要使用另一个Django层面的关系来访问每个相关的账户,使用:

pr = Profile.objects.get(pk=1)
for pacc in pr.profileaccount_set.order_by('number'):
    pacc.account
6

这个对我有效:

Profile.objects.account.order_by('profileaccounts')
31

我刚遇到这个问题。

class Profile(models.Model):     
    accounts = models.ManyToManyField('project.Account',
                                      through='project.ProfileAccount')

    def get_accounts(self):
        return self.accounts.order_by('link_to_profile')


class Account(models.Model):
    name = models.CharField(max_length=32)


class ProfileAccount(models.Model):
    profile = models.ForeignKey('project.Profile')
    account = models.ForeignKey('project.Account', related_name='link_to_profile')
    number = models.PositiveIntegerField()

    class Meta:
        ordering = ('number',)

我把那些不相关的字段都去掉了,只留下了 Account.name。这是我找到的最简单的解决办法,不知道在2010年是否可行,但现在肯定可以。

撰写回答