Подтвердить что ты не робот

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
4b9b3361

Ответ 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 в запросе.