これが私のモデルのセットアップ方法の抜粋です。
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モデルの「番号」で並べ替えるにはどうすればよいですか?:
for acct_number in self.profile.accounts.all():
pass
これは機能しませんが、このデータにアクセスする方法の要点です。
for scanline_field in self.scanline_profile.fields.all().order_by('number'):
pass
私はちょうどこれを通り抜けました。
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',)
Article.name
を除いてトピックから外れたフィールドを削除しました。これは私が見つけた最短のソリューションであり、2010年に使用できるかどうかはわかりませんが、現在は確かにそうです。
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
関連する名前をProfileAccountsに追加してから、その 'related_name__number'を持つアカウントの順序を変更します。 related_nameとnumberの間に2つのアンダースコアがあることに注意してください。下記参照:
class Accounts(models.Model):
.
.
.
class Meta:
ordering = ('profile_accounts__number',)
class ProfileAccounts(models.Model):
.
.
.
account = models.ForeignKey('project.Accounts', related_name='profile_accounts')
number = models.PositiveIntegerField()
class Meta:
ordering = ('number',)
それは私のために働いた:
Profile.objects.account.order_by('profileaccounts')
プロファイルにタイプミスがありますが(「アカウント」を意味すると思う場合は「アカウント」です)、さらに重要なのは、モデル内で単数形/複数形が混在していることです。
Djangoでは、通常、クラスに単数形の名前を付け、ManyToManyFieldに複数形の名前を付けます。
_class Profile(models.Model):
name = models.CharField(max_length=32)
accounts = models.ManyToManyField(
'Account',
through='ProfileAccount'
)
def __unicode__(self)
return self.name
class Account(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 ProfileAccount(models.Model):
profile = models.ForeignKey(Profile)
account = models.ForeignKey(Account)
number = models.PositiveIntegerField()
class Meta:
ordering = ('number',)
_
このモデルで何をしようとしているのか少し混乱していますが、これらの変更を行うと、for acct_number in self.profile.accounts.all().order_by('number'):
が機能するはずです。他の問題がないと仮定します。
私はこれを多くのモデルで使用していますが、私の意見では(他のすべての回答とは異なり)、_order_by
_を再度指定する必要はありません。これは、through
モデルですでに指定されているためです。もう一度指定すると、DRY(繰り返さないでください)の原則に違反します。
私は使うだろう:
_qs = profile.profileaccounts_set.all()
_
これにより、構成された順序を使用して、プロファイルに関連付けられたProfileAccountsのセットが提供されます。次に:
_for pa in qs:
print(pa.account.name)
_
ボーナスポイントについては、クエリで_select_related
_を使用して、プロセス全体を高速化することもできます。
この特定の問題の最も簡単な解決策は
for acct in self.profile.accounts.order_by('profileaccounts'):
pass