Почему в Django Rest Framework объект удаления все еще отображается в списке?

#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. Я обновил сообщение, добавив завершающую косую черту, выводящую тот же результат.