Объекты отсутствуют в БД (проблема транзакции)

У меня есть представление DRF, которое импортирует Product объекты в базе данных. Проблема в том, что пока транзакция жива, все выглядит правильно. Созданные объекты имеют свои ids (значит они были сохранены в БД).

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

  1. get file (binary from request)
  2. store it in /tmp/product_imports/
  3. call ImportService.import_csv(new_filepath)
  4. the method returns a number of products imported
  5. return a response from the view

Все выглядит хорошо, view возвращает число (2 в моем случае, так как 3 из 5 продуктов не действительны). Но когда я проверяю БД, его там нет

@action(methods=['post'], detail=False)
def import_csv(self, request, pk=None) -> Response:
    csv_file = request.FILES['file']
    csv_import_files_dir = os.path.join('/tmp/project_imports/')
    csv_file_path = os.path.join(csv_import_files_dir, str(uuid.uuid4()))
    os.makedirs(csv_import_files_dir, exist_ok=True)
    with open(csv_file_path, 'wb') as f:
        f.write(csv_file.read())
    count = product_services.imports.ImportService.import_csv(csv_file_path, request.user)
    return Response({'imported': count})

Основные методы из ImportService

@classmethod
def import_csv(cls, filepath: str, created_by: User, delete_file=True) -> int:
    """imports products
    supplier_sku already exists ? skip product : add product """
    cls.validate_csv(filepath)
    products_count = 0

    with open(filepath) as f:
        reader = csv.DictReader(f)

        for row in reader:
            if not all([row.get(field, None) is not None for field in ['title', 'sku']]):
                continue
            row['title'] = row['title'][:99]

            try:
                cls.create_from_dict(row, created_by)
            except IntegrityError:
                raise  # todo what?
            except cls.InvalidCSVRowException:
                continue
            except:
                continue
            else:
                products_count += 1
        if delete_file:
            os.remove(filepath)
    return products_count

class InvalidCSVRowException(Exception):
    pass

@classmethod
def validate_row(cls, row: dict):
    if not all([row.get(field, None) for field in cls.REQUIRED_COLUMNS]):
        raise cls.InvalidCSVRowException(f"These columns can't be empty: {cls.REQUIRED_COLUMNS} | {row}")

@classmethod
def create_from_dict(cls, row: dict, created_by):
    # ['supplier', 'sku', 'url', 'title', 'price']
    from products.models import Product
    from products.models import ProductInfo
    cls.validate_row(row)
    product = Product(created_by=created_by, product_title=row['title'])
    product.save()
    product_id = product.id
    from suppliers.models import Supplier
    supplier = \
        Supplier.objects.get_or_create(name__iexact=row['supplier'], defaults={'name': row['supplier']})[
            0]
    product_info = ProductInfo(product_id=product_id, supplier=supplier, supplier_sku=row['sku'],
                               supplier_url=row['url'], supplier_title=row['title'], current_price=row['price'])

    product_info.save()

PS: Я заметил, что когда я останавливаю выполнение (в отладчике) до того, как представление вернет ответ, я не могу запросить продукты из базы данных, так как это вызывает:

You can't execute queries until the end of 'atomic' block. Да, есть ATOMIC_REQUESTS=True.

Вернуться на верх