Есть ли способ сохранить запрос в django и использовать его позже?

У меня есть служба, которая печатает входящие данные в excel. Эта служба работает следующим образом. Я создаю запрос, но не запускаю его. Я сбрасываю и сохраняю запрос с помощью "pickle", загружаю и снова использую его с помощью pickle в задаче celery. До сих пор это работало на всех моих моделях. Но в модели ниже pickle выдает ошибку.

django version=3.2 Поле Money, которое я использовал в модели, находится здесь. django-money==3.0.0

class PaymentStatus:
    WAIT = 1
    SUCCESS = 2
    FAIL = 3
    CANCEL = 4

    types = (
        (WAIT, _('Waiting')),
        (SUCCESS, _('Success')),
        (FAIL, _('Fail')),
        (CANCEL, _('Cancel'))
    )



class PaymentModel(models.Model):
    class Meta:
        app_label = 'betik_app_payment'
        indexes = [
            models.Index(fields=['dt', 'user_email'])
        ]

    provider = models.PositiveIntegerField(choices=PaymentProviderTypeEnum.types)
    is_test = models.BooleanField(default=True)
    payment_status = models.PositiveIntegerField(choices=PaymentStatus.types, default=PaymentStatus.WAIT)
    price = MoneyField(max_digits=20, decimal_places=2, help_text=_('amount paid excluding tax and discount'))
    paid_price = MoneyField(max_digits=20, decimal_places=2, help_text=_('amount paid including tax and discount'))
    dt = models.DateTimeField()
    user_email = models.EmailField(null=True, blank=True)
    token = models.CharField(max_length=255, null=True, blank=True, help_text=_('This token comes from the payment system. With this token, inquiries are made in the payment system'))
    locale = models.CharField(max_length=10, default="en")

Ошибка огурца: _pickle.PicklingError: Can't pickle <function QuerySet.distinct at 0x7faf69912430>: это не тот же объект, что и django.db.models.query.QuerySet.distinct

.
qs=PaymentModel.objects.filter(dt__date__lte="2030-01-01")
pickle.dumps(qs) #raise error

успешно работает, когда есть только одна модель

qs=PaymentModel.objects.filter(dt__date__lte="2030-01-01")
pickle.dumps(qs[0]) # SUCCESS

Когда так не получилось, я решил сохранить сырой sql и запустить его в задаче celery.

qs=PaymentModel.objects.filter(dt__date__lte="2030-01-01")
sql=str(qs.query)

## raw sql ##
'SELECT "betik_app_payment_paymentmodel"."id", "betik_app_payment_paymentmodel"."provider", "betik_app_payment_paymentmodel"."is_test", "betik_app_payment_paymentmodel"."payment_status", "betik_app_payment_paymentmodel"."price_currency", "betik_app_payment_paymentmodel"."price", "betik_app_payment_paymentmodel"."paid_price_currency", "betik_app_payment_paymentmodel"."paid_price", "betik_app_payment_paymentmodel"."dt", "betik_app_payment_paymentmodel"."user_email", "betik_app_payment_paymentmodel"."token", "betik_app_payment_paymentmodel"."locale" FROM "betik_app_payment_paymentmodel" WHERE ("betik_app_payment_paymentmodel"."dt")::date <= 2030-01-01'

но когда я пытаюсь запустить его из необработанного sql запроса, он выдает ошибку вроде этой

qs=PaymentModel.objects.raw(sql)
list(qs)

Вышеуказанное исключение стало непосредственной причиной следующего исключения:

Traceback (последний последний вызов): Файл "", строка 1, в Файл "/usr/local/lib/python3.8/site-packages/django/db/models/query.py", строка 1476, in len. self._fetch_all() Файл "/usr/local/lib/python3.8/site-packages/django/db/models/query.py", строка 1471, в _fetch_all self._result_cache = list(self.iterator()) Файл "/usr/local/lib/python3.8/site-packages/django/db/models/query.py", строка 1494, в iterator query = iter(self.query) Файл "/usr/local/lib/python3.8/site-packages/django/db/models/sql/query.py", строка 100, in iter. self._execute_query() Файл "/usr/local/lib/python3.8/site-packages/django/db/models/sql/query.py", строка 140, в _execute_query self.cursor.execute(self.sql, params) Файл "/usr/local/lib/python3.8/site-packages/django/db/backends/utils.py", строка 98, в execute return super().execute(sql, params) Файл "/usr/local/lib/python3.8/site-packages/django/db/backends/utils.py", строка 66, в execute return self._execute_with_wrappers(sql, params, many=False, executor=self._execute) File "/usr/local/lib/python3.8/site-packages/django/db/backends/utils.py", строка 75, в _execute_with_wrappers return executor(sql, params, many, context) Файл "/usr/local/lib/python3.8/site-packages/django/db/backends/utils.py", строка 84, in _execute return self.cursor.execute(sql, params) Файл "/usr/local/lib/python3.8/site-packages/django/db/utils.py", строка 90, in exit raise dj_exc_value.with_traceback(traceback) from exc_value Файл "/usr/local/lib/python3.8/site-packages/django/db/backends/utils.py", строка 84, in _execute return self.cursor.execute(sql, params) django.db.utils.ProgrammingError: ERROR: operator does not exist: date <= integer LINE 1: ...FROM betik_app_payment_paymentmodel WHERE dt::date<=2030-01-... ^ СОВЕТ: Нет функции соответствующая заданному имени и типу аргументов. Вам может потребоваться добавить явные приведения типов.

Есть ли другой способ сохранить запрос и запустить его позже?

  • Кверисеты являются ленивыми, поэтому база данных не будет поражена, пока вы не оцените свой кверисет. Вы можете проверить этот doc, он стоит того, как мне кажется.
Вернуться на верх