Есть ли способ сохранить запрос в 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, он стоит того, как мне кажется.