Django - отображать список вычисляемых полей в шаблоне - PullRequest
0 голосов
/ 06 сентября 2018

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

pending_action.html

    <h1>Pending Action</h1> 
            {% for req_header in req_header_list %}         
                <div class="accordion" id="accordionExample">
                    <div class="card">
                        <div class="card-header" id="headingOne">
                        <h5 class="mb-0">
                            <button class="btn btn-link" type="button" data-toggle="collapse" data-target="#req{{ req_header.id }}" aria-expanded="false" aria-controls="collapseOne">                       
                                {{ req_header }} 
                            </button>
                        </h5>
                        </div>

                        <div id="req{{ req_header.id }}" class="collapse" aria-labelledby="headingOne" data-parent="#accordionExample">
                        <div class="card-body">
                            <table class="table">
                                <tr>
                                    <th>Line</th>
                                    <th>Description</th>
                                    <th>Quantity</th>
                                    <th>Total Price</th>
                                    <th>Status</th>
                                </tr>    
                                {% for line in req_header.par_req_line.all %}
                                    <tr>
                                        <td>{{line}}</td>
                                        <td>{{line.description}}</td>
                                        <td>{{line.quantity}}</td>
                                        <td>{{line.total_price}}<td>
                                        <td>{{line.status}}</td>                     
                                    </tr>
                                {% endfor %}
                                <tr>
                                    <td>
                                        <form action="#" method="POST">       
                                                <input type="submit" value="Submit">
                                        </form>
                                    </td>
                                    <td></td>
                                    <td></td>
                                    <td>
                                         <!--WANT TO DISPLAY THE TOTAL PRICE PER REQUISITION HERE                                         
                                          {{price_list.0}}
                                    </td>

                                </tr>
                            </table>   
                        </div>
                        </div>
                    </div>                
                </div>

        {% endfor %}
    </div>

views.py

def pending_action(request):
    user = CustomUser.objects.get(username=request.user)
    user_req_headers = Requisition.objects.filter(username=user)
    complete_status = RequisitionStatus.objects.get(status='Completed')
    req_header_list = []
    total_price = 0
    price_list = []

    for req_header in user_req_headers:
        req_lines = RequisitionLine.objects.filter(Q(parent_req = req_header) & ~Q(status=complete_status))
        for line in req_lines:
            if line.parent_req not in req_header_list:
                req_header_list.append(line.parent_req)

            total_price = total_price + line.total_price
        price_list.append(total_price)
        total_price = 0

    return render(request, 'req/pending_action.html', {'req_header_list':req_header_list, 'price_list':price_list})

models.py

class Requisition(models.Model):
    username = models.ForeignKey(
        'users.CustomUser', on_delete=models.CASCADE, related_name='req_user')
    signature = models.CharField(max_length=10, blank=True, null=True)



class RequisitionLine(models.Model):

    parent_req = models.ForeignKey('Requisition', on_delete=models.CASCADE, related_name='par_req_line' )
    sequence = models.PositiveIntegerField()
    item_code = models.ForeignKey(
        'items.ItemMaster', on_delete=models.CASCADE, related_name='req_item', blank=True, null=True)
    description = models.CharField(max_length=50, blank=True)
    extra_information = models.TextField(blank=True)
    quantity = models.PositiveIntegerField(blank=True, default=0,null=True)
    price = models.DecimalField(max_digits=19, decimal_places=2, blank=True, default=0.00,null=True)
    total_price = models.DecimalField(max_digits=19, decimal_places=2, blank=True, default=0.00,null=True)
    purchase_order = models.CharField(max_length=9, blank=True,null=True)
    po_line = models.PositiveSmallIntegerField(blank=True,null=True)
    req_delivery_date = models.DateField(blank=True,null=True)
    act_delivar_date = models.DateField(blank=True, null=True)
    status = models.ForeignKey('RequisitionStatus', related_name='req_status', on_delete=models.CASCADE, blank=True, null=True)
    assistance = models.ForeignKey('users.UserRoles', related_name='req_assist', blank=True, null=True, on_delete=models.CASCADE, limit_choices_to= ~Q(role='Requestor'))
    catagory = models.ForeignKey('items.ItemCatagory', on_delete=models.CASCADE, related_name='line_cat',  blank=True, null=True)
    notes = models.TextField(blank=True)

    class Meta:
        unique_together = ('parent_req','sequence')

StackTrace

Environment:


Request Method: GET
Request URL: http://127.0.0.1:8000/req/pending/

Django Version: 2.1
Python Version: 3.7.0
Installed Applications:
['django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'req',
 'users.apps.UsersConfig',
 'items']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware']



Traceback:

File "C:\Users\###\Documents\Python\venv\env\lib\site-packages\django\core\handlers\exception.py" in inner
  34.             response = get_response(request)

File "C:\Users\###\Documents\Python\venv\env\lib\site-packages\django\core\handlers\base.py" in _get_response
  126.                 response = self.process_exception_by_middleware(e, request)

File "C:\Users\###\Documents\Python\venv\env\lib\site-packages\django\core\handlers\base.py" in _get_response
  124.                 response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "C:\Users\###\Documents\Python\venv\env\lib\site-packages\django\contrib\auth\decorators.py" in _wrapped_view
  21.                 return view_func(request, *args, **kwargs)

File "C:\Users\###\Documents\Python\django\lambda\req\views.py" in pending_action
  273.     user_reqs = Requisition.objects.filter(par_req_line__in=user_req_lines_incomplete).annotate(aggregated_price=sum('par_req_line__total_price'))

Exception Type: TypeError at /req/pending/
Exception Value: unsupported operand type(s) for +: 'int' and 'str'

1 Ответ

0 голосов
/ 07 сентября 2018

Вам следует провести рефакторинг файла views.py, чтобы он возвращал один набор запросов объектов реквизиции, соответствующих вашим условиям, с добавлением агрегированных ценовых данных, которые вы хотите предоставить. Затем вам нужно провести рефакторинг вашего HTML-шаблона, чтобы выполнить итерацию по одному набору запросов. Максимальное использование Django ORM сделает ваш код намного короче и будет работать намного быстрее.

В views.py

from django.db.models import Sum

def pending_action(request):
    user_req_lines_incomplete = RequisitionLine.objects.filter(parent_req__username=request.user).exclude(status__status='Completed'))
    user_reqs = Requisition.objects.filter(par_req_line__in=user_requisition_lines_incomplete).annotate(aggregated_price=Sum('par_req_line__total_price'))
    return render(request, 'req/pending_action.html', {'user_reqs':user_reqs})        

Обратите внимание, что в Django ORM под капотом происходит небольшая хитрость, когда вы делаете фильтр для связанной модели, прежде чем аннотировать эту модель. Когда вы filter(par_req_line__in, это также означает, что примечание, которое происходит позже в строке, будет рассчитываться только на par_req_line с, которые соответствуют условию фильтра. Таким образом, ваша агрегация будет суммировать только те строки, которые находятся в user_req_lines_incomplete. Я на 95% уверен, что это то, что вы хотите, но не стесняйтесь уточнить, если вы ищете другое состояние. Я изо всех сил пытался следовать всему вашему коду со многими циклами for и именами. (Без суждения.)

In pending_action.html

<!-- I took out most of your HTML to simplify -->
<h1>Pending Action</h1> 

{% for req in user_reqs %}
    <h5>{{req}}</h5> <!-- You can show whatever you want for your req here -->
    {% for line in req.par_req_line.all %x} 
        <tr>
            <td>{{line}}</td>
            <td>{{line.description}}</td>
            <td>{{line.quantity}}</td>
            <td>{{line.total_price}}<td>
            <td>{{line.status}}</td>                     
        </tr>
    {% endfor %}
    Total price: {{req.aggregated_price}} <!-- Use the annotated data here -->
{% endfor %}

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

...