сортировка диктанта в поле дата-время

#python #odoo-12

Вопрос:

здравствуйте, у меня есть код, который дает мне диктант, вот диктант:

 {2516: {'order_date': datetime.datetime(2021, 7, 26, 16, 10, 10, 461000), 'product_id': 2516, 
'product_name': 'TRENTO GRIS 30*60 NEW TILE SPAIN 514', 'quantity': -1.0, 'product_cost': 4.0,
'price_unit': 5.5, 'remaining_qty': -23.0, 'seller_name': 'السيد ابو فهد', 'jour': 'Cash,'},

2412: {'order_date': datetime.datetime(2021, 7, 26, 13, 59, 33, 351000), 'product_id': 2412, 
'product_name': 'ORION HEXA SILVER 19.8*22. SPAIN 355', 'quantity': -4.0, 'product_cost': 0.58, 
'price_unit': 1.25, 'remaining_qty': 129.0, 'seller_name': 'السيد برغش المطيري المحترم ', 'jour': 'Cash,'},

2897: {'order_date': datetime.datetime(2021, 7, 23, 20, 4, 2, 939000), 'product_id': 2897, 'product_name': 'BLANCO BR RECT LA 30*60 SPAIN 456', 
'quantity': -6.0, 'product_cost': 3.5, 'price_unit': 4.0, 'remaining_qty': 6.0, 'seller_name': 'السيد احمد منصور العازمي', 
'jour': 'Cash,'},

 2828: {'order_date': datetime.datetime(2021, 7, 23, 20, 8, 38, 380000), 
'product_id': 2828, 'product_name': 'كاونتر مدور رمادي فاتح 1277 (36*12 CM', 'quantity': -1.0, 'product_cost': 0.0, 
'price_unit': 27.5, 'remaining_qty': -1.0, 'seller_name': 'السيد علي المطيري المحترم', 'jour': 'Cash,'}, 

3041: {'order_date': datetime.datetime(2021, 7, 23, 20, 7, 11, 189000), 'product_id': 3041, 'product_name': 'PRIS TINENZA 30*60 SPAIN', 
'quantity': -2.0, 'product_cost': 5.0, 'price_unit': 6.5, 'remaining_qty': -13.0, 'seller_name': 'السيد محمد حسن الكندري المحترم', 'jour': 'Cash,'}}
 

я попробовал составить список, как:

                 if products_sold.get(line.product_id.id):
                products_sold[line.product_id.id] = sorted([{
                    'order_date': order.date_order,
                    'product_id': products_sold[line.product_id.id].get('product_id'),
                    'product_name': products_sold[line.product_id.id].get('product_name'),
                    'quantity': products_sold[line.product_id.id].get('quantity', 0)   line.qty,
                    'product_cost': products_sold[line.product_id.id].get('product_cost'),
                    'price_unit': products_sold[line.product_id.id].get('price_unit'),
                    'remaining_qty': line.product_id.qty_available,
                    'seller_name': seller_name,
                    'jour': jour
                } for (product, seller_name, order, line, jour), qty in products_sold.get(line.product_id.id)],key=lambda l: l['order_date']
 

но каждый раз, когда я пытаюсь это сделать, я получаю ошибку "ValueError: too many values to unpack (expected 2)"

Я даже пытался, как:

 dict = {k: v for k, v in sorted(products_sold[line.product_id.id].items(), key= lambda v : v[0])}
 

и передал его взамен, но все равно я получаю ошибку

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

     def get_sale_details_product_wise(self, date_start=False, date_stop=False, configs=False):
    if not configs:
        configs = self.env['pos.config'].search([])

    orders = self.env['pos.order'].search([
        ('date_order', '>=', date_start),
        ('date_order', '<=', date_stop),
        ('state', 'in', ['paid', 'invoiced', 'done']),
        ('config_id', 'in', configs.ids)])

    products_sold = {}
    for order in orders:
        jour = ''
        jour_list = []
        for statement in order.statement_ids:
            if statement.journal_id.name not in jour_list:
                jour_list.append(statement.journal_id.name)
                jour  = statement.journal_id.name   ','
        for line in order.lines:
            seller_name = self.env["res.partner"].search(
                [('id', '=', line.order_id.partner_id.id)]).name

            if products_sold.get(line.product_id.id):
                # print('1111111', line.product.id)
                products_sold[line.product_id.id] = sorted([{
                    'order_date': order.date_order,
                    'product_id': products_sold[line.product_id.id].get('product_id'),
                    'product_name': products_sold[line.product_id.id].get('product_name'),
                    'quantity': products_sold[line.product_id.id].get('quantity', 0)   line.qty,
                    'product_cost': products_sold[line.product_id.id].get('product_cost'),
                    'price_unit': products_sold[line.product_id.id].get('price_unit'),
                    'remaining_qty': line.product_id.qty_available,
                    'seller_name': seller_name,
                    'jour': jour
                } for (product, seller_name, order, line, jour), qty in products_sold.get(line.product_id.id)],key=lambda l: l['order_date'])
            else:
                products_sold[line.product_id.id] = {
                    'order_date': order.date_order,
                    'product_id': line.product_id.id,
                    'product_name': line.product_id.name,
                    'quantity': line.qty,
                    'product_cost': line.product_id.standard_price,
                    'price_unit': line.price_unit,
                    'remaining_qty': line.product_id.qty_available,
                    'seller_name': seller_name,
                    'jour': jour
                }
    return {'products': products_sold}
 

Комментарии:

1. Исправлена опечатка в названии: словарь вместо диктанта

2. Здравствуйте, пожалуйста, добавьте пример того, чего вы пытаетесь достичь. Вы пытаетесь разобраться в диктанте? по какому полю? как вы хотите, чтобы диктант выглядел в конце?

3. @ExtraFishness, братан, я там упоминал… да, братан, ты прав, я хочу разобраться в диктанте… имя поля «дата заказа»

Ответ №1:

Это утверждение неверно:

 for (product, seller_name, order, line, jour), qty in products_sold.get(line.product_id.id)
 

Вы повторяете значение products_sold.get(line.product_id.id) и ожидаете, что каждый элемент содержит последовательность из 5 переменных. Значение products_sold.get(line.product_id.id) — это диктат:

 whole_dict = products_sold.get(line.product_id.id)  # Let's say id=2412
print(type(whole_dict), whole_dict)
 

Выход:

 <class 'dict'> {'order_date': datetime.datetime(2021, 7, 26, 13, 59, 33, 351000), 'product_id': 2412, 'product_name': 'ORION HEXA SILVER 19.8*22. SPAIN 355', 'quantity': -4.0, 'product_cost': 0.58, 'price_unit': 1.25, 'remaining_qty': 129.0, 'seller_name': 'السيد برغش المطيري المحترم ', 'jour': 'Cash,'}
 

Это означает, что повторение products_sold.get(line.product_id.id) эквивалентно повторению ключей products_sold.get(line.product_id.id).keys() , которые являются просто строками:

 for key in products_sold.get(line.product_id.id):  # Equivalent to products_sold.get(line.product_id.id).keys()
    print(type(key), key)
 

Выход:

 <class 'str'> order_date
<class 'str'> product_id
<class 'str'> product_name
<class 'str'> quantity
<class 'str'> product_cost
<class 'str'> price_unit
<class 'str'> remaining_qty
<class 'str'> seller_name
<class 'str'> jour
 

Итак, что вы пытались сделать, это назначить каждую строку этим 5 переменным:

 (product, seller_name, order, line, jour), qty = "order_date"
(product, seller_name, order, line, jour), qty = "product_id"
(product, seller_name, order, line, jour), qty = "product_name"
# and so on ...
 

Очевидно, что они не подойдут, и именно поэтому вы испытываете ошибку ValueError: too many values to unpack (expected 2) .

Решение

Вот как вы бы отсортировали все на products_sold основе их order_date атрибута.

 import datetime

products_sold = {
    2516: {
        'order_date': datetime.datetime(2021, 7, 26, 16, 10, 10, 461000),
        'product_id': 2516,
        'product_name': 'TRENTO GRIS 30*60 NEW TILE SPAIN 514',
        'quantity': -1.0,
        'product_cost': 4.0,
        'price_unit': 5.5,
        'remaining_qty': -23.0,
        'seller_name': 'السيد ابو فهد',
        'jour': 'Cash,'
    },
    2412: {
        'order_date': datetime.datetime(2021, 7, 26, 13, 59, 33, 351000),
        'product_id': 2412,
        'product_name': 'ORION HEXA SILVER 19.8*22. SPAIN 355',
        'quantity': -4.0,
        'product_cost': 0.58,
        'price_unit': 1.25,
        'remaining_qty': 129.0,
        'seller_name': 'السيد برغش المطيري المحترم ',
        'jour': 'Cash,'
    },
    2897: {
        'order_date': datetime.datetime(2021, 7, 23, 20, 4, 2, 939000),
        'product_id': 2897,
        'product_name': 'BLANCO BR RECT LA 30*60 SPAIN 456',
        'quantity': -6.0,
        'product_cost': 3.5,
        'price_unit': 4.0,
        'remaining_qty': 6.0,
        'seller_name': 'السيد احمد منصور العازمي',
        'jour': 'Cash,'
    },
    2828: {
        'order_date': datetime.datetime(2021, 7, 23, 20, 8, 38, 380000),
        'product_id': 2828,
        'product_name': 'كاونتر مدور رمادي فاتح 1277 (36*12 CM',
        'quantity': -1.0,
        'product_cost': 0.0,
        'price_unit': 27.5,
        'remaining_qty': -1.0,
        'seller_name': 'السيد علي المطيري المحترم',
        'jour': 'Cash,'
    },
    3041: {
        'order_date': datetime.datetime(2021, 7, 23, 20, 7, 11, 189000),
        'product_id': 3041,
        'product_name': 'PRIS TINENZA 30*60 SPAIN',
        'quantity': -2.0,
        'product_cost': 5.0,
        'price_unit': 6.5,
        'remaining_qty': -13.0,
        'seller_name': 'السيد محمد حسن الكندري المحترم',
        'jour': 'Cash,'
    },
}

# .items() is a tuple of (key, value), where key (accessed via [0]) is an int e.g. 2897 and value (accessed via [1]) is a dict e.g. {'order_date': datetime.datetime(2021, 7, 23, 20, 4, 2, 939000), 'product_id': 2897, 'product_name': 'BLANCO BR RECT...}
products_sold = dict(
    sorted(
        products_sold.items(), key=lambda item: item[1]['order_date']
    )
)

print("Whole dict")
print(products_sold)

print("n==========n")

print("Dict items")
for key, value in products_sold.items():
    print(key, value)
 

Выход:

 Whole dict
{2897: {'order_date': datetime.datetime(2021, 7, 23, 20, 4, 2, 939000), 'product_id': 2897, 'product_name': 'BLANCO BR RECT LA 30*60 SPAIN 456', 'quantity': -6.0, 'product_cost': 3.5, 'price_unit': 4.0, 'remaining_qty': 6.0, 'seller_name': 'السيد احمد منصور العازمي', 'jour': 'Cash,'}, 3041: {'order_date': datetime.datetime(2021, 7, 23, 20, 7, 11, 189000), 'product_id': 3041, 'product_name': 'PRIS TINENZA 30*60 SPAIN', 'quantity': -2.0, 'product_cost': 5.0, 'price_unit': 6.5, 'remaining_qty': -13.0, 'seller_name': 'السيد محمد حسن الكندري المحترم', 'jour': 'Cash,'}, 2828: {'order_date': datetime.datetime(2021, 7, 23, 20, 8, 38, 380000), 'product_id': 2828, 'product_name': 'كاونتر مدور رمادي فاتح 1277 (36*12 CM', 'quantity': -1.0, 'product_cost': 0.0, 'price_unit': 27.5, 'remaining_qty': -1.0, 'seller_name': 'السيد علي المطيري المحترم', 'jour': 'Cash,'}, 2412: {'order_date': datetime.datetime(2021, 7, 26, 13, 59, 33, 351000), 'product_id': 2412, 'product_name': 'ORION HEXA SILVER 19.8*22. SPAIN 355', 'quantity': -4.0, 'product_cost': 0.58, 'price_unit': 1.25, 'remaining_qty': 129.0, 'seller_name': 'السيد برغش المطيري المحترم ', 'jour': 'Cash,'}, 2516: {'order_date': datetime.datetime(2021, 7, 26, 16, 10, 10, 461000), 'product_id': 2516, 'product_name': 'TRENTO GRIS 30*60 NEW TILE SPAIN 514', 'quantity': -1.0, 'product_cost': 4.0, 'price_unit': 5.5, 'remaining_qty': -23.0, 'seller_name': 'السيد ابو فهد', 'jour': 'Cash,'}}

==========

Dict items
2897 {'order_date': datetime.datetime(2021, 7, 23, 20, 4, 2, 939000), 'product_id': 2897, 'product_name': 'BLANCO BR RECT LA 30*60 SPAIN 456', 'quantity': -6.0, 'product_cost': 3.5, 'price_unit': 4.0, 'remaining_qty': 6.0, 'seller_name': 'السيد احمد منصور العازمي', 'jour': 'Cash,'}
3041 {'order_date': datetime.datetime(2021, 7, 23, 20, 7, 11, 189000), 'product_id': 3041, 'product_name': 'PRIS TINENZA 30*60 SPAIN', 'quantity': -2.0, 'product_cost': 5.0, 'price_unit': 6.5, 'remaining_qty': -13.0, 'seller_name': 'السيد محمد حسن الكندري المحترم', 'jour': 'Cash,'}
2828 {'order_date': datetime.datetime(2021, 7, 23, 20, 8, 38, 380000), 'product_id': 2828, 'product_name': 'كاونتر مدور رمادي فاتح 1277 (36*12 CM', 'quantity': -1.0, 'product_cost': 0.0, 'price_unit': 27.5, 'remaining_qty': -1.0, 'seller_name': 'السيد علي المطيري المحترم', 'jour': 'Cash,'}
2412 {'order_date': datetime.datetime(2021, 7, 26, 13, 59, 33, 351000), 'product_id': 2412, 'product_name': 'ORION HEXA SILVER 19.8*22. SPAIN 355', 'quantity': -4.0, 'product_cost': 0.58, 'price_unit': 1.25, 'remaining_qty': 129.0, 'seller_name': 'السيد برغش المطيري المحترم ', 'jour': 'Cash,'}
2516 {'order_date': datetime.datetime(2021, 7, 26, 16, 10, 10, 461000), 'product_id': 2516, 'product_name': 'TRENTO GRIS 30*60 NEW TILE SPAIN 514', 'quantity': -1.0, 'product_cost': 4.0, 'price_unit': 5.5, 'remaining_qty': -23.0, 'seller_name': 'السيد ابو فهد', 'jour': 'Cash,'}
 

Пробный прогон:

Это предполагает, что вы используете Python 3.7 или более поздней версии, как описано в документации, поскольку только из этой версии упорядочиваются словари. В противном случае используйте список (или коллекции.OrderedDict), поэтому измените выше на list(sorted(... .

Изменено в версии 3.7: Порядок словаря гарантированно будет порядком вставки. Такое поведение было детализацией реализации CPython начиная с версии 3.6.

Комментарии:

1. «братан, это дает ошибку в заявлении if:» если products_sold.get(line.product_id.id): Ошибка атрибута: объект «список» не имеет атрибута «получить»

2. Вы products_sold правильно диктуете, как в моем примере? Вы можете просмотреть пример запуска здесь: paiza.io/projects/e/S4DaFd3efAcbx3SesvMTsA?theme=twilight

3. «а также, если я изменю:» products_sold = сортировка( products_sold[line.product_id.id], ключ=лямбда-элемент: элемент[1][‘order_date’] ) он выдает ошибку: ошибка типа: объект ‘datetime.datetime’ не подлежит подписке, я изменил его как, потому что dict был на products_sold[line.product_id.id]

4. Не могли бы вы обновить вопрос и добавить точный формат products_sold ? Так ли это, как сейчас products_sold = {2516: {'order_date': datetime.datetime(), product_id': 2516}, 2412: {'order_date': datetime.datetime(), product_id': 2412}} , или это products_sold = [{2516: {'order_date': datetime.datetime(), product_id': 2516}, 2412: {'order_date': datetime.datetime(), product_id': 2412}}] или что-то другое?

5. нет, нет, все в порядке, братан, ты прав.. я просто ранее преобразовал дикт в список и забыл изменить его обратно, поэтому он выдавал ошибку