#django #django-models #django-rest-framework
Вопрос:
Я создаю API с помощью платформы django rest. Но у меня возникает проблема каждый раз, когда я хочу изменить модель, когда я уже создал связанный набор представлений моделей.
Например, у меня есть такая модель:
class Machine(models.Model):
name = models.CharField(_('Name'), max_length=150, unique=True)
provider = models.CharField(_("provider"),max_length=150)
build_date = models.DateField(_('build date'))
category = models.ForeignKey("machine.CategoryMachine",
related_name="machine_category",
verbose_name=_('category'),
on_delete=models.CASCADE
)
site = models.ForeignKey(
"client.Site",
verbose_name=_("site"),
related_name="machine_site",
on_delete=models.CASCADE
)
class Meta:
verbose_name = _("Machine")
verbose_name_plural = _("Machines")
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse("Fridge_detail", kwargs={"pk": self.pk})
И этот набор представлений:
class MachineViewSet(viewsets.ModelViewSet):
"""
A simple ViewSet for listing or retrieving machine.
"""
permission_classes = [permissions.IsAuthenticated]
serializer_class = MachineSerializer
queryset = cache.get_or_set(
'machine_machines_list',
Machine.objects.all(),
60*60*24*7
)
@swagger_auto_schema(responses={200: MachineSerializer})
def list(self, request):
serializer_context = {
'request': request,
}
queryset = cache.get_or_set(
'machine_machines_list',
Machine.objects.all(),
60*60*24*7
)
serializer = MachineSerializer(queryset, many=True, context=serializer_context)
return Response(serializer.data)
@swagger_auto_schema(responses={404: 'data not found', 200: MachineSerializer})
def retrieve(self, request, pk=None):
serializer_context = {
'request': request,
}
queryset = Machine.objects.all()
machine = get_object_or_404(queryset, pk=pk)
serializer = MachineSerializer(machine, context=serializer_context)
return Response(serializer.data)
Если я хочу добавить поле в свою модель, например, описание. Когда я выполняю команду python manage.py makemigrations
Я получаю ошибку :
django.db.utils.ProgrammingError: column machine_machine.description does not exist
Я должен прокомментировать свой набор представлений, чтобы иметь возможность запускать makemigrations
и migrate
. Как я могу избежать необходимости каждый раз комментировать наборы представлений, когда я хочу изменить модель?
Комментарии:
1. Можете ли вы поделиться обратной связью?
2. Вы будете кэшировать результаты набора запросов в течение недели?? Ты действительно в этом уверен? Таким образом, вы можете отображать устаревшие данные для пользователей.
3. Я удаляю данные из кэша при изменении результата (например, после добавления объекта…)
Ответ №1:
На ваш взгляд, в вашем классе есть следующая строка:
queryset = cache.get_or_set(
'machine_machines_list',
Machine.objects.all(),
60*60*24*7
)
Поскольку эта строка присутствует в объявлении класса, а не в методе класса, она выполняется при создании / интерпретации класса. Это приводит к тому, что он запускает запрос, так как для его кэширования потребуется выполнить оценку набора запросов (обработка наборов запросов приведет к принудительной оценке). Проблема здесь в том, что ваши модели еще не были перенесены, и ваши запросы не выполняются. Вы можете написать этот код в get_queryset
методе, переопределив его, если хотите:
class MachineViewSet(viewsets.ModelViewSet):
"""
A simple ViewSet for listing or retrieving machine.
"""
permission_classes = [permissions.IsAuthenticated]
serializer_class = MachineSerializer
# Remove below lines
# queryset = cache.get_or_set(
# 'machine_machines_list',
# Machine.objects.all(),
# 60*60*24*7
# )
def get_queryset(self):
return cache.get_or_set(
'machine_machines_list',
Machine.objects.all(),
60*60*24*7
)
...
Но эта реализация имеет серьезные недостатки! Вы кэшируете набор запросов в течение недели. В течение этого периода времени может поступить много новых данных, и вы, по сути, будете предоставлять своим пользователям устаревшие данные. Я бы посоветовал вам отказаться от такого рода кэширования. Кроме того, вы, похоже, возвращаете все данные из своего представления, подумайте о какой-то фильтрации, чтобы для таких вещей требовалось меньше памяти.
Комментарии:
1. Спасибо вам за ваш ответ. Это работает очень хорошо. Для недельного кэша я удаляю ключи по мере необходимости, например, после добавления новой машины. Зная, что в месяц будет добавляться/изменяться не более 1 или 2 машин, недельный кэш не кажется слишком плохим.