#django #docker #django-rest-framework #docker-compose
Вопрос:
После удаления объекта он все еще находится в данных ответа.
/api/premises/premises/4
ВОЗВРАТ
{
"detail": "Not found."
}
но /api/premises/premises/
ВОЗВРАТ
[
{
"id": 1,
"image": "/product/lb-gallery-main.jpg",
"owner": "owner@lebernardin.com",
"name": "Le Bernardin",
"description": "Le Bernardin to francuska restauracja z owocami morza na Manhattanie w Nowym Jorku. Gilbert Le Coze i jego siostra Maguy Le Coze otworzyli restaurację w Paryżu w 1972 roku, pod nazwą Les Moines de St. Bernardin.",
"country": "Poland",
"city": "Gdynia",
"postcode": "80-209",
"address": "Starowiejska 1",
"tags": [
1,
2
]
},
{
"id": 4,
"image": "naws.com/product/Union-Oksford.jpg",
"owner": "admin@admin.com",
"name": "dadad",
"description": "dada",
"country": "dada",
"city": "dada",
"postcode": "dad",
"address": "dadadada",
"tags": []
},
{
"id": 2,
"image": "196290008887877_5616210528952631689_n.jpg",
"owner": "admin@admin.com",
"name": "Sebastian Wrzałek",
"description": "adadada",
"country": "dadad",
"city": "adada",
"postcode": "dada",
"address": "dadadadaddd",
"tags": []
}
]
Странно, что он не отображается на Django Admin. Также я использую Docker, после перезапуска он обновляет список и не показывает удаленный элемент. Когда я проверил таблицу базы данных напрямую, данные соответствуют, что означает, что элемент удален правильно. Я думаю, откуда он берется и почему он каким-то образом кэшируется?
докер-compose.yml
version: "3"
services:
redis:
image: redis
command: redis-server
ports:
- "6379:6397"
app:
build:
context: .
ports:
- "8000:8000"
volumes:
- ./app:/app
command: >
sh -c "python manage.py wait_for_db amp;amp;
python manage.py check_connection amp;amp;
python manage.py migrate amp;amp;
python manage.py runserver 0.0.0.0:8000"
environment:
- DB_HOST=db
- DB_NAME=app
- DB_USER=postgres
- DB_PASS=sspassword
depends_on:
- db
env_file:
- .env
db:
image: postgis/postgis:9.6-2.5-alpine
environment:
- POSTGRES_DB=app
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=sspassword
Редактировать.
views.py
class PremisesViewSet(viewsets.ModelViewSet):
"""Manage premises in database"""
lookup_field = 'id'
lookup_url_kwarg = 'premises_id'
serializer_class = serializers.PremisesSerializer
queryset = Premises.objects.all()
permission_classes = (IsAuthenticated,)
def get_queryset(self):
"""Retreive the premises for auth user"""
try:
# TODO create wrapper for header
if(self.request.META['HTTP_X_SOURCE_WEB']):
return self.queryset.filter(owner=self.request.user)
except KeyError:
return self.queryset
def get_serializer_class(self):
"""Return appropriate serializer class"""
return self.serializer_class
def perform_create(self, serializer):
"""Create a new premises"""
serializer.save(owner=self.request.user)
@action(detail=True, methods=['get'])
def menu(self, request, **kwargs):
instance = self.get_object()
menu = Menu.objects.filter(premises=instance, is_default=True)
serializer = MenuProductsSerializer(menu, many=True)
return Response(serializer.data)
Serializers.py
class PremisesSerializer(serializers.ModelSerializer):
"""Serializer a premises"""
image = Base64ImageField(max_length=None)
owner = serializers.ReadOnlyField(source='owner.email')
location = serializers.HiddenField(default=Point(1,1))
class Meta:
model = Premises
fields = '__all__'
read_only_fields = ('id',)
Комментарии:
1. Покажите представление, которое возвращает этот ответ…
Ответ №1:
Проблема в вашем get_queryset
, которая заключается в следующем:
def get_queryset(self):
"""Retreive the premises for auth user"""
try:
# TODO create wrapper for header
if(self.request.META['HTTP_X_SOURCE_WEB']):
return self.queryset.filter(owner=self.request.user)
except KeyError:
return self.queryset
Проблема в том, что в except
блоке вы напрямую возвращаетесь self.queryset
. Поскольку набор запросов фактически определен в классе, он уже был оценен в каком-либо предыдущем запросе. Если вы видите, что реализация по умолчанию get_queryset
содержит следующие строки:
if isinstance(queryset, QuerySet): # Ensure queryset is re-evaluated on each request. queryset = queryset.all()
Эта линия queryset = queryset.all()
вызывает у нас здесь беспокойство. Что это делает (как уже указано в комментарии), это гарантирует, что набор запросов будет повторно оцениваться при каждом запросе. Следовательно, вам следует изменить свою реализацию на:
def get_queryset(self):
"""Retreive the premises for auth user"""
# TODO create wrapper for header
if self.request.META.get('HTTP_X_SOURCE_WEB') is not None: # Instead of try-except use .get() which will return `None` if the header is not set
return self.queryset.filter(owner=self.request.user)
return self.queryset.all()
Комментарии:
1. Работает просто отлично, потому что я всегда пользовался
return super(ViewSet, self).get_queryset()
, я не знал, что это работает таким образом. Спасибо.
Ответ №2:
Если вы используете браузер для просмотра /api/premises/premises/
, возможно, вы просматриваете кэшированную версию этой страницы. Попробуйте Ctrl-R
перезагрузить свежую версию страницы.
Ответ №3:
Возможно, проблема в представлении конечной /api/premises/premises/4
точки . Можете ли вы предоставить более подробную информацию о представлении и его сериализаторе?
Кроме того, я заметил, что завершающая косая черта ( /
) отсутствует /api/premises/premises/4
в конечной точке в отличие от конечной /api/premises/premises/
точки . Это может вызвать перенаправление http-вызова в случае, если конечная косая черта была определена в urls.py.
Комментарии:
1. Я обновил сообщение, добавив завершающую косую черту, выводящую тот же результат.