【问题标题】:Why in Django Rest Framework remove object still appears on a list?为什么在 Django Rest Framework 中删除对象仍然出现在列表中?
【发布时间】:2023-03-15 22:25:01
【问题描述】:

删除对象后,它仍然在响应数据中。

/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,重新启动后它正在更新列表并且不显示已删除的项目。当我直接检查数据库表时,数据是正确的,这意味着项目被正确删除。我在想它是从哪里来的,为什么会以某种方式被缓存?

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 &&
                   python manage.py check_connection &&
                   python manage.py migrate &&
                   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)

序列化器.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',)

【问题讨论】:

  • 显示返回此响应的视图...

标签: django docker django-rest-framework docker-compose


【解决方案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。由于查询集实际上是在类上定义的,因此它已经在一些 previous 请求中进行了评估。如果您看到get_queryset 的默认实现有以下几行:

if isinstance(queryset, QuerySet):
    # Ensure queryset is re-evaluated on each request.
    queryset = queryset.all()

queryset = queryset.all() 这行是我们关心的问题。这样做是(正如评论已经表明的那样)它确保 QuerySet 在每个请求上都被重新评估。因此,您应该将实现更改为:

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()

【讨论】:

  • 工作得很好,因为我一直在使用return super(ViewSet, self).get_queryset() 我不知道它是这样工作的。谢谢。
【解决方案2】:

如果您使用浏览器查看/api/premises/premises/,那么您可能正在查看该页面的缓存版本。尝试Ctrl-R 重新加载页面的新版本。

【讨论】:

    【解决方案3】:

    也许问题出在端点/api/premises/premises/4 的视图中。您能否提供有关视图及其序列化程序的更多详细信息?

    另外,我注意到端点 /api/premises/premises/4 与端点 /api/premises/premises/ 相比缺少尾部斜杠 (/)。如果在 urls.py 中定义了尾部斜杠,这可能会触发重定向 http 调用。

    【讨论】:

    • 我已经更新了帖子,添加了斜杠输出相同的结果。
    猜你喜欢
    • 2011-12-29
    • 2013-05-23
    • 2017-03-12
    • 2015-03-15
    • 1970-01-01
    • 2014-12-14
    • 1970-01-01
    • 1970-01-01
    • 2016-07-03
    相关资源
    最近更新 更多