You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Django-Rest-Framework中仅展示当前用户的视频?

问题描述

我正在使用Django和React开发一个YouTube克隆项目,拥有一个可让用户删除、编辑视频的管理面板。但目前面板会同时显示自身及其他用户的视频,请问如何实现仅展示当前用户视频的功能?


Django 后端代码(views.py)

class AdminVideoDetail(generics.RetrieveAPIView):
    permission_classes = [IsAuthenticated]
    queryset = Video.objects.all()
    serializer_class = VideoSerializer

React 前端组件(videos.js)

import React from 'react';
import { makeStyles } from '@material-ui/core/styles';
import Container from '@material-ui/core/Container';
import Link from '@material-ui/core/Link';
import Paper from '@material-ui/core/Paper';
import Table from '@material-ui/core/Table';
import TableBody from '@material-ui/core/TableBody';
import TableCell from '@material-ui/core/TableCell';
import TableContainer from '@material-ui/core/TableContainer';
import TableHead from '@material-ui/core/TableHead';
import TableRow from '@material-ui/core/TableRow';
import DeleteForeverIcon from '@material-ui/icons/DeleteForever';
import EditIcon from '@material-ui/icons/Edit';
import Button from '@material-ui/core/Button';

const useStyles = makeStyles((theme) => ({
    cardMedia: {
        paddingTop: '56.25%', // 16:9
    },
    link: {
        margin: theme.spacing(1, 1.5),
    },
    cardHeader: {
        backgroundColor:
            theme.palette.type === 'light'
                ? theme.palette.grey[200]
                : theme.palette.grey[700],
    },
    videoTitle: {
        fontSize: '16px',
        textAlign: 'left',
    },
    videoText: {
        display: 'flex',
        justifyContent: 'left',
        alignItems: 'baseline',
        fontSize: '12px',
        textAlign: 'left',
        marginBottom: theme.spacing(2),
    },
}));

const Videos = (props) => {
    const { videos } = props;
    const classes = useStyles();
    if (!videos || videos.length === 0) return <Button href={'/admin/create'} variant="contained" color="primary">New Video</Button>;
    return (
        <React.Fragment>
            <Container maxWidth="md" component="main">
                <Paper className={classes.root}>
                    <TableContainer className={classes.container}>
                        <Table stickyHeader aria-label="sticky table">
                            <TableHead>
                                <TableRow>
                                    <TableCell>Id</TableCell>
                                    <TableCell align="left">Title</TableCell>
                                    <TableCell align="left">Action</TableCell>
                                </TableRow>
                            </TableHead>
                            <TableBody>
                                {videos.map((video) => {
                                    return (
                                        <TableRow>
                                            <TableCell component="th" scope="row">
                                                {video.id}
                                            </TableCell>
                                            <TableCell align="left">
                                                <Link
                                                    color="textPrimary"
                                                    href={'/video/' + video.id}
                                                    className={classes.link}
                                                >
                                                    {video.title}
                                                </Link>
                                            </TableCell>

                                            <TableCell align="left">
                                                <Link
                                                    color="textPrimary"
                                                    href={'/admin/edit/' + video.id}
                                                    className={classes.link}
                                                >
                                                    <EditIcon></EditIcon>
                                                </Link>
                                                <Link
                                                    color="textPrimary"
                                                    href={'/admin/delete/' + video.id}
                                                    className={classes.link}
                                                >
                                                    <DeleteForeverIcon></DeleteForeverIcon>
                                                </Link>
                                            </TableCell>
                                        </TableRow>
                                    );
                                })}
                                <TableRow>
                                    <TableCell colSpan={4} align="right">
                                        <Button
                                            href={'/admin/create'}
                                            variant="contained"
                                            color="primary"
                                        >
                                            New Video
                                        </Button>
                                    </TableCell>
                                </TableRow>
                            </TableBody>
                        </Table>
                    </TableContainer>
                </Paper>
            </Container>
        </React.Fragment>
    );
};
export default Videos;

解决方案

1. 确保Video模型关联用户

首先你的Video模型需要添加关联User的字段,用于记录视频所属用户:

from django.contrib.auth.models import User
from django.db import models

class Video(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="videos")
    title = models.CharField(max_length=255)
    # 其他视频字段(如视频文件、描述等)

2. 修改Django视图,过滤当前用户的视频

列表视图(管理面板获取视频列表用)

如果存在获取视频列表的视图(比如AdminVideoList),重写get_queryset方法只返回当前用户的视频:

from rest_framework import generics
from .models import Video
from .serializers import VideoSerializer
from rest_framework.permissions import IsAuthenticated

class AdminVideoList(generics.ListAPIView):
    permission_classes = [IsAuthenticated]
    serializer_class = VideoSerializer

    def get_queryset(self):
        # 仅返回当前登录用户的视频
        return Video.objects.filter(user=self.request.user)

详情视图(AdminVideoDetail)

修改现有AdminVideoDetail,确保用户只能访问自己的视频,防止通过URL参数直接访问他人视频:

class AdminVideoDetail(generics.RetrieveAPIView):
    permission_classes = [IsAuthenticated]
    serializer_class = VideoSerializer

    def get_object(self):
        # 根据视频ID和当前用户过滤,找不到则返回404
        obj = generics.get_object_or_404(Video, id=self.kwargs['pk'], user=self.request.user)
        self.check_object_permissions(self.request, obj)
        return obj

创建视频时自动关联用户

如果有创建视频的视图,保存时自动绑定当前登录用户:

class AdminVideoCreate(generics.CreateAPIView):
    permission_classes = [IsAuthenticated]
    serializer_class = VideoSerializer

    def perform_create(self, serializer):
        # 保存视频时设置所属用户为当前登录用户
        serializer.save(user=self.request.user)

3. 前端无需额外修改

只要后端API返回的是当前用户的视频列表,你现有的videos.js组件可以直接使用,props.videos已经是过滤后的结果,只会渲染当前用户的视频。


内容的提问来源于stack exchange,提问作者PHILLIPP APETENOK

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 03:10:39