Django ManyToManyField заказ с использованием через
Вот фрагмент настройки моих моделей:
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
Ответы
Ответ 1
Я только что прошел через это.
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 году, но это, безусловно, сейчас.
Ответ 2
Диспетчер 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
Ответ 3
Там есть опечатка в профиле (это "accout", когда я думаю, что вы имеете в виду "учетную запись" ), но что более важно, у вас есть смешанные формы с единым числом/множественным числом в модели.
В 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'):
должен работать. Предполагая, что нет других проблем.
Ответ 4
Добавьте связанное имя в ProfileAccounts, а затем измените порядок в Учетных записях с этим 'related_name__number'. Обратите внимание на два подчеркивания между родственным именем и номером. См. Ниже:
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',)
Ответ 5
Это сработало для меня:
Profile.objects.account.order_by('profileaccounts')
Ответ 6
Самое простое решение для этой конкретной проблемы -
for acct in self.profile.accounts.order_by('profileaccounts'):
pass
Ответ 7
У меня это на нескольких моих моделях, но, на мой взгляд (и в отличие от всех других ответов), вам не нужно будет снова указывать order_by
, потому что, ну, он уже указан в модели through
, Задание его снова нарушает принцип DRY (не повторяйте сам).
Я бы использовал:
qs = profile.profileaccounts_set.all()
Это дает набор профилей ProfileAccounts, связанных с профилем, с использованием настроенного упорядочения. Тогда:
for pa in qs:
print(pa.account.name)
Для бонусных очков вы также можете ускорить общий процесс, используя select_related
в запросе.