Как упорядочить возвращаемые объекты поля по умолчанию после определения сквозной модели? - PullRequest
0 голосов
/ 05 июня 2019

Сводка

Определение get_queryset (), как показано ниже, не упорядочивает объекты с целым числом order, как ожидалось.Я ожидаю, что заказ будет item.order1 item.order2 item.order 3, но на самом деле я получаю 12,1,6.или даже 8,13,2.

return self.items.all().order_by('items','-itemOrder__order')

Деталь

У меня есть модель Item и модель Set,Наборы имеют отношение ManyToMany к Item, поэтому каждый Set является в основном набором Item с.

Проблема в том, что у этих предметов нет порядка, когда я их отображаю, и яхочу иметь возможность заказывать их произвольно.То есть.не только по дате или названию.

Я определил отношение through, в котором элементы Set определяются через новый класс SetMeta, который имеет поле order.Теперь я могу установить это значение order в моем веб-приложении, но фактическое упорядочение объектов еще не сработало.

models.py

class Item(models.Model, AdminVideoMixin):
    title = models.TextField(max_length=5000)
    ....

class Set(Item):
    items = models.ManyToManyField(Item, related_name='in_sets', through='SetMeta', max_length=5000,)

    def get_absolute_url(self):
        return reverse('curate:set_detail',kwargs={'slug':self.slug})

    def get_queryset(self):
        return self.items.all().order_by('-itemOrder__order')

    def __str__(self):
        return self.title

class SetMeta(models.Model):
    item = models.ForeignKey(Item, on_delete=models.CASCADE, related_name='itemOrder', max_length=5000)
    set = models.ForeignKey(Set, on_delete=models.CASCADE, related_name='SetOrder', max_length=5000)
    order = models.IntegerField(default=0, null=True,)

    def up(self):
        self.order += 1
        self.save()
        print(self.order)

    def down(self):
        self.order -= 1
        self.save()
        print(self.order)


views.py

def setEdit(request, slug):

    set = Set.objects.get(slug__exact=slug)
    user = request.user

   ### SOME OTHER STUFF ###

    return render(request, 'curate/set_edit.html', {'set_edit': set_edit,
                                                    'item_form': item_form,
                                                    'set' : set})

set_edit.html template

  {% for item in set.items.all %}
        <div class="col-lg-2 col-sm-2 col-xs-6 item mr-1 badge-set-holder"  aria-expanded="true">

          {% if item.type == 'video' %}
          <a href="{% url 'curate:item_detail' slug=item.slug %}"><img class='img-fluid img-preview' src="{{item.image_sized.url}}" alt="broken"> </img>
            <span id=dr{{set.pk}} class="badge badge-success badge-set-positioner">Video</span>

#####

  {% else %}
              <a href="{% url 'curate:item_detail' slug=item.slug %}"><img class='img-fluid img-preview' src="{{item.top_image}}" alt="broken"> </img>
              <span class="badge badge-success badge-set-positioner">Item</span>

            {% endif %}

            <div class="collapse show" id=dr{{set.pk}}>
              <a href="{% url 'curate:item_detail' slug=item.slug %}">
                <h5 class='header'>{{item.title}}</h5>
              </a>
              <small>The order is {{item.itemOrder.get.order}}</small>
              <p>
                <a href="{% url 'curate:remove_item_from_set' slug=set.slug pk=item.pk %}" style="color:red;">
                    <i class="material-icons" style="color:red;">
                          remove_circle
                        </i>REMOVE
                  </a>
                  </p>
                  <p>
                  <a href="{% url 'curate:moveUp' slug=set.slug item_pk=item.pk %}" style="color:red;">
                      <i class="material-icons" style="color:red;">
                            arrow_left
                          </i>
                    </a>
                    <a href="{% url 'curate:moveDown' slug=set.slug item_pk=item.pk %}" style="color:red;">
                        <i class="material-icons" style="color:red;">
                              arrow_right
                            </i>
                      </a>
                      </p>

Я добавил функцию def get_queryset (), котораяЯ думаю (?) Упорядочивает поля по itemOrder__order, но, похоже, этого не происходит.На переднем крае я получаю необъяснимый порядок.Я могу вызывать «вверх» и «вниз» на своих предметах и ​​даже отображать значение order спереди, которое меняется, но порядок меняется совершенно случайно, я не могу понять, какая логика используется для заказаих.Я пытался увидеть, действительно ли IntergerField был чем-то другим, например, CharField, но это не так.Я посмотрел в базе данных.

Например, прямо сейчас элементы отображаются в порядке 12,1,6.Я могу возиться со значениями, и порядок также может быть 8,13,2.Я даже пытался обновить страницу и посмотреть, изменяется ли случайное отображение без чисел, присутствующих в порядке, но нет, они остаются в том порядке, пока числа не меняются, но не упорядочиваются с логикой, которую я могу понять?

Ответы [ 2 ]

0 голосов
/ 05 июня 2019

Я понял это в конце концов благодаря помощи обоих авторов выше. Я только что определил модельный метод в своем наборе, который дает мне то, что мне нужно.

class Set(Item):
    front_page = models.BooleanField(max_length=300, blank=False, default=False, null=False)
    items = models.ManyToManyField(Item, related_name='in_sets', through='SetMeta', max_length=5000,)

    def get_absolute_url(self):
        return reverse('curate:set_detail',kwargs={'slug':self.slug})

    def order(self):
        return self.items.all().order_by('itemOrder__order')

    def __str__(self):
        return self.title

0 голосов
/ 05 июня 2019

Прежде всего, если вы хотите сделать промежуточный заказ Model, вы должны создать пользовательский промежуточный Model (явно). Вы уже сделали это. Кроме того, вы пытаетесь переопределить метод экземпляра get_queryset() в своем классе Model, но это не имеет значения. get_queryset() - это метод Manager/BaseManager класса, а не Model класса.

Вы можете попробовать что-то вроде этого ,,,

SetMeta.objects.filter(item_id=ITEM_ID).order_by('order')

или

SetMeta.objects.filter(set_id=SET_ID).order_by('order')

Кроме того, рекомендуется использовать метод select_related() QuerySet для доступа к связанным объектам и избежать большого количества попаданий DB. Он выполняет SQL JOINS. Ничего больше.

SetMeta.objects.select_related('item').filter(item_id=ITEM_ID).order_by('order')

или

SetMeta.objects.select_related('set').filter(set_id=SET_ID).order_by('order')

Кроме того, вы можете установить правило порядка по умолчанию для SetMeta класса.

class SetMeta(models.Model):
    item = models.ForeignKey(Item, on_delete=models.CASCADE, related_name='itemOrder', max_length=5000)
    set = models.ForeignKey(Set, on_delete=models.CASCADE, related_name='SetOrder', max_length=5000)
    order = models.IntegerField(default=0, null=True,)

    class Meta:
        ordering = ('order',)

Использование в запросах

items = Item.objects.all()

m2m_model_qs = SetMeta.objects.select_related('item', 'set').filter(item_id__in=items).order_by('order') # performs SQL SubSelect
for instance in m2m_model_qs:
    print(instance) # this is instance of m2m model
    print(instance.item) # this is instance of Item model. you can access columns also. "instance.item.title"
    print(instance.set) # this is instance of Set model. you can access columns also. "instance.set.pk" # for example.

Надеюсь, это вам поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...