Как переопределить внутренний запрос на чтение класса или метода в django
Я хочу переопределить внутренний запрос на чтение, присутствующий в моем классе или методе. Я хочу написать обобщенное решение, чтобы оно работало на классе или методе, где я хочу изменить запросы на чтение.
Я пытаюсь использовать декораторы, промежуточное ПО и метаклассы, но мне не удается получить доступ к внутреннему запросу на чтение функции.
Я просто хочу изменить его, чтобы он брал его из реплики чтения. но я не могу сделать это для всех запросов чтения. Я могу модифицировать запрос на чтение так, чтобы он брался из реплики чтения только для нескольких классов или методов.
master_models.CarTransmission.objects.filter( # pylint: disable=E1101 variant_id__in=self.variant_ids ).values_list(*self.specifications, named=True)
изменить это на-
master_models.CarTransmission.objects.using('replica').filter( # pylint: disable=E1101 variant_id__in=self.variant_ids ).values_list(*self.specifications, named=True)
оригинальный.
model = get_object_or_404(master_models.Model,slug=slug)
измените это на -
model = get_object_or_404(master_models.Model.objects.using('replica'),slug=slug)
Логика, которую я ожидаю, должна быть специфична для класса и метода. Если я применю это к классу, то все присутствующие методы должны изменить все внутренние запросы на чтение. Возможно ли это, или я должен перейти ко всем запросам и написать .using('replica')
pleaser не предоставляйте решения, которые работают для какого-то конкретного приложения, например, использование маршрутизации для перемещения его на перенаправление в реплику, так как они будут работать на всем проекте или на каком-то приложении, а не на конкретном методе или классе.
Для этого можно использовать маршрутизатор базы данных [Django-doc]:
# app_name/router.py
class ReplicateRouter:
def db_for_read(self, model, **hints):
return 'replicate'
для запросов, которые таким образом читаются из базы данных, вместо нее будет использоваться база данных replicate
.
и установите маршрутизатор в настройках:
# settings.py
DATABASE_ROUTERS = ['app_name.router.ReplicateRouter']
Вы также можете добавить к этому больше контроля, например, только для определенных моделей с помощью:
# app_name/router.py
class ReplicateRouter:
def db_for_read(self, model, **hints):
if hasattr(model, 'use_replicate_for_read', False):
return 'replicate'
и затем прикрепите атрибут user_replicate_for_read
к модели, для которой вы хотите это сделать:
# app_name/models.py
class CarTransmission(models.Model):
use_replicate_for_read = True
# …