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

Определите заказ для ManyToManyField с django

Есть ли способ определить порядок содержимого элементов списка?

Пример:

  • ArticleContainer1 содержит в следующем порядке:
     статья1, статья2, статья3, статья6

  • ArticleContainer2 содержит в следующем порядке:
     статья 3, статья2, статья1, статья4

  • ArticleContainer3 содержит в следующем порядке:
     article5

Вот мои классы:

class Article(models.Model):    
    title = models.CharField(max_length=200)

class ArticleContainer(models.Model):
   contents = models.ManyToManyField(Article, blank=True, null=True)
4b9b3361

Ответ 1

Итак, это пример, который у меня есть, сайт, который организует людей в отделах по заказу отдела. Это та же концепция, что и ваша проблема, но с разными моделями. В этом примере используется таблица "многие-ко-многим".

class Department(models.Model):
    slug = models.SlugField(
        verbose_name    = _(u'Slug'),
        help_text           = _(u'Uri identifier for this department.'),
        max_length=255
    )
    name = models.CharField(
        verbose_name    = _(u'Department Name'),
        help_text           = _(u'The department\ name.'),
        max_length      = 255
    )
    description = models.TextField(
        verbose_name    = _(u'Description'),
        help_text           = _(u'Department\ description')
    )
    people = models.ManyToManyField(
        Person,
        through             = 'DepartmentPeople',
        related_name    = 'people',
        verbose_name    = _(u'People'),
        help_text           = _(u'People in this Department')
    )
    order_by = models.IntegerField(
        verbose_name    = _(u'Ordering Weight'), 
        help_text           = _(u'This item\ weight within a list.'),
        max_length      = 255
    )

    class Meta:
        verbose_name = _(u"Department")
        verbose_name_plural = _(u"Departments")
        ordering = ['order_by',]

    def people_list(self):
        return [dp.person for dp in DepartmentPeople.objects.filter(department=self).order_by('order')]

    def __unicode__(self):
        return self.name        

И сквозная модель:

class DepartmentPeople(models.Model):
    person = models.ForeignKey(
        Person,
        verbose_name    = _(u'Person'),
        help_text           = _(u'Person is a member of this deparment.'),
    )
    department = models.ForeignKey(
        Department,
        verbose_name    = _(u'Department'),
        help_text           = _(u'Pseron is a member of this department.'),
    )       
    order = models.IntegerField(
        verbose_name    = _(u'Order'),
        help_text           = _(u'What order to display this person within the department.'),
        max_length      = 255
    )

    class Meta:
        verbose_name = _(u"Department Person")
        verbose_name_plural = _(u"Department People")
        ordering = ['order',]

    def __unicode__(self):
        return self.person.first_name + " " + self.person.last_name + " is a member of " + self.department.name + (" in position %d" % self.order)

И администратор:

class DepartmentPeopleInline(admin.TabularInline):
    model = DepartmentPeople
    extra = 1

class DepartmentAdmin(admin.ModelAdmin):
    inlines = (DepartmentPeopleInline,)

admin.site.register(Person, PersonAdmin)
admin.site.register(Department, DepartmentAdmin)

ЗАПРОС В КОММЕНТАРИИ:

Примечание. Следующим является мой PersonAdmin, но для этого примера он бесполезен. вы можете пройти простым

class PersonAdmin(admin.ModelAdmin) :
    pass

НО это то, что я использую в своем приложении:

class PersonForm(forms.ModelForm):
    abstract = forms.CharField(
        widget=TinyMCE(attrs={'cols': 80, 'rows': 30})
    )

    class Meta:
        model = Person

class PersonAdmin(reversion.VersionAdmin):
    form = PersonForm
    # The Form Fieldsets
    fieldsets = [
        (
            None,
            {
                'fields'    : [('first_name', 'last_name', 'post_nominal', ), 'slug', 'title', 'headshot', 'large_photo', ('email', 'phone', ), 'abstract']
            },
        )
    ]

    # Prepopulated fields
    prepopulated_fields = {'slug': ('first_name', 'last_name', 'post_nominal', )}

    # Fields that are readonly
    #readonly_fields = ('slug', )

    def formfield_for_dbfield(self, db_field, **kwargs):
        if db_field.name == 'headshot':
            request = kwargs.pop("request", None)
            kwargs['widget'] = AdminImageWidget
            return db_field.formfield(**kwargs)
        return super(PersonAdmin, self).formfield_for_dbfield(db_field, **kwargs)

Ответ 2

Смотрите документы через.

Ответ 3

Если вы используете явно определенную модель through для отношения m2m, вы можете добавить свой собственный атрибут order-id. Затем вы можете расширить ManyToManyField, чтобы заполнить идентификатор заказа по вашей логике при создании/обновлении и менеджере модели m2m, который будет сортировать результаты, когда вы извлекаете их атрибутом идентификатора заказа.

Ответ 4

В Django 2.0 принятый ответ фрэнсиса Яконьелло хорошо работает, за исключением предупреждения, вызванного аргументом max_length для поля order класса DepartmentPeople.

Django игнорирует max_length для целочисленных полей и предупредит вас в Django 1. 8+.

Я бы добавил запись unique_together в подкласс Meta

class Meta:
    #...
    unique_together = ['person', 'department', 'order']

чтобы предотвратить ошибки ввода данных.