Этажное деление и модуль по списку - PullRequest
0 голосов
/ 16 мая 2018

С помощью Django Listview можно ли отображать новые столбцы, которые содержат значения деления по полу и по модулю?

У меня есть следующие две модели:

models.py

class Model_Item(models.Model):
    item_name = models.CharField(max_length = 100, null = False, blank = False, unique = True)
    item_bottleperpack = models.FloatField(null = True, blank = False) # e.g. 100 bottles per pack

    def __unicode__(self):
        return self.item_name

class Model_ItemTransaction(models.Model):
    item = models.ForeignKey(Model_Item, to_field = "item_name")
    item_sold = models.FloatField(null = True, blank = True) # in terms of bottle

    def __unicode__(self):
        return self.item 

С этим списком просмотра:

views.py

class View_Item(ListView):
    def get_queryset(self):
        queryset = Model_Item.objects.all()
        queryset = queryset.annotate(
            sum_ = Sum("model_itemtransaction__item_sold")
            )
        queryset = queryset.annotate(
            floor_division_ = F("sum_") // F("item_bottleperpack"),
            module_ = F("sum_") %% F("item_bottleperpack")
            )
        return queryset

В принципе, если я продал, скажем, 650 бутылок, а в упаковке 100 бутылок, я бы хотелпросмотр списка для отображения:

  • 6 упаковок в столбце "разделение по этажам" и
  • 50 бутылок в модуле "по модулю"column.

В настоящее время я получаю следующие ошибки с моим текущим кодом

unsupported operand type(s) for //: 'F' and 'F'
and
unsupported operand type(s) for %%: 'F' and 'F'

и надеюсь, что кто-то может помочь мне найти какое-либо решение этой проблемы (и это не обязательно должно бытьс условным выражением ).

Ответы [ 3 ]

0 голосов
/ 16 мая 2018

Согласно https://docs.djangoproject.com/en/2.0/_modules/django/db/models/expressions/:

Ни класс F, ни его родительский Combinable не реализуют __floordiv__, поэтому // не реализован. Combinable реализует __truediv__, то есть оператор /.

Я не слышал об операторе %% в Python, но % будет работать, потому что __mod__ реализован в Combinable.

Попробуйте использовать models.IntegerField или models.PositiveIntegerField для item_bottleperpack и item_sold и обновите эту строку в views.py:

queryset = queryset.annotate(
        floor_division_ = F("sum_") / F("item_bottleperpack"),
        module_ = F("sum_") % F("item_bottleperpack")
        )

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

0 голосов
/ 16 мая 2018

Итак, я нашел способ решить эту проблему, благодаря этому сообщению .

Сначала я очистил код в views.py,

views.py

class View_Item(ListView):
    def get_queryset(self):
        queryset = Model_Item.objects.all()
        queryset = queryset.annotate(
            sum_ = Sum("model_itemtransaction__item_sold")
            )
        return queryset

затем добавил этот файл кода в папку templatetags

app_filters.py

from django import template

register = template.Library()

@register.filter(name = "func_floor_division")
def func_floor_division(num, val):
    if num:
        floor_division = num // val
        return floor_division
    else:
        return None

@register.filter(name = "func_modulo")
def func_modulo(num, val):
    if num:
        modulo = num % val
        return modulo
    else:
        return None

и, наконец, изменил теги в html-файле.

html

{% load app_filters %}
<table>
    <tr>
        <th>Floor Division</th>
        <th>Modulo</th>
    </tr>

    {% for obj_ in object_list %}
        <tr>
            <td>{{ obj_.sum_|func_floor_division:obj_.item_bottleperpack }}</td>
            <td>{{ obj_.sum_|func_modulo:obj_.item_bottleperpack }}</td>
        </tr>
    {% endfor %}
</table>

Надеюсь, это поможет любому, кто столкнулся с той же проблемой.

0 голосов
/ 16 мая 2018

вы можете создать новые поля floor_division и module_ в вашем Model_Item, затем использовать получатель сохранения записи для обновления полей floor_division и module_

from django.db.models.signals import pre_save
class Model_Item(models.Model):
  item_name = models.CharField(max_length = 100, null = False, blank = False, unique = True)
  item_bottleperpack = models.FloatField(null = True, blank = False) # e.g. 100 bottles per pack
  floor_division = models.IntegerField(null=True, blank=True)
  module_ = models.IntegerField(null=True, blank=True)
  def __unicode__(self):
    return self.item_name

def model_item_pre_save(sender, instance, created):
   item = Model_Item.objects.get(id=instance.id)
   item_transaction = Model_Transaction.objects.get(item_id=instance.id)
   item.floor_division = item_transaction.item_sold // item.item_bottleperpack
   item.module_ = item_transaction.item_sold %% item.item_bottleperpack


pre_save.connect(model_item_pre_save, sender=Model_Item)
...