doramochi blog

doramochi blog

趣味で学んだプログラミングの知識を綴っていきます

DjangoとReactを使ったアプリケーションを作ってみる③(動画一覧を表示)

間が空いてしまったが、練習として色々作ってみる。
今回は動画の一覧を表示してみる。

準備編:
DjangoとReactを使ったアプリケーションを作ってみる①(Django側の準備) - doramochi blog
DjangoとReactを使ったアプリケーションを作ってみる②(React側の準備) - doramochi blog

素材の準備

まずは練習に使用する動画と画像をダウンロード。
今回はNHKクリエイティブ・ライブラリーの素材を使用させていただく。
publicフォルダの配下に「video」「img」フォルダを作成。

適当に画像と動画をダウンロードして各フォルダに配置する。


モデル修正とDBの準備

前回適当に値を入れてしまったので素材に合わせてデータを追加する。
また、前回作成したモデルにはサムネイル画像のパスを登録する項目がなかったので追加する。

モデルの修正

models.pyを下記のように修正する。
「path」としていた部分を「video_path」に修正。
さらに「img_path」も追加する。
修正が完了したら「makemigrations」「migrate」コマンドを実行してDBへ反映。

from django.conf import settings
from django.db import models
from django.utils import timezone

class Video(models.Model):
    title = models.CharField(max_length=30)
    description = models.TextField(max_length=300)
    video_path = models.CharField(max_length=60)
    img_path = models.CharField(max_length=60)
    datetime = models.DateTimeField(blank=False, null=False)
    number_of_views = models.IntegerField(blank=True, default=0)

合わせてserialize.pyも修正しておく。

from rest_framework import serializers
from .models import Video

class VideoSerializer(serializers.ModelSerializer):
    class Meta:
        model = Video
        fields = ('id',
                  'title',
                  'description',
                  'video_path',
                  'img_path',
                  'datetime',
                  'number_of_views')

DBの準備

下記のようにデータを登録する。

フロントエンド側の修正

Material UIのインストール

今回はMaterial UIのCardを使用してみる。
mui.com
そのため、まずはMaterial UIのインストール。

npm install @mui/material @emotion/react @emotion/styled

Component作成

上記カードを1つのComponentとして作成する。
下記のように「src」の配下に「\components」フォルダ。「\components」フォルダの配下に「VideoCard」フォルダを作成。
「VideoCard」フォルダ配下に「VideoCard.js」ファイルを作成する。

Material UIのサンプルに記載されているコードをとりあえずコピペ。

必要な部分を変更していく。
修正点は以下の通り。
・画像のパスを変更
・DBから取得した動画タイトルを表示
・DBから取得したdescriptionを表示
・不要な記述削除
DBからの値はpropsで受け取るようにする。
また、画像ファイルは

{`${process.env.PUBLIC_URL}/img/${props.img_path}`}

と指定することでpublic配下のファイルを参照することが出来る。
今回はpublicの下にimgフォルダを作成しているので上記の様にしている。

動画や画像はpublic以外に配置することもできるが、ビルドの対象となってしまうので注意が必要。
数が多くなったり、サイズが大きい場合は「npm start」や「npm run build」などを実行したときにメモリ不足でエラーとなる場合がある。

修正したコードは以下の通り。

import * as React from 'react';
import Card from '@mui/material/Card';
import CardActions from '@mui/material/CardActions';
import CardContent from '@mui/material/CardContent';
import CardMedia from '@mui/material/CardMedia';
import Button from '@mui/material/Button';
import Typography from '@mui/material/Typography';

const VideoCard = (props) => {
  return (
    <Card sx={{ maxWidth: 345 }}>
      <CardMedia
        component="img"
        height="140"
        image={`${process.env.PUBLIC_URL}/img/${props.img_path}`}
        alt="test"
      />
      <CardContent>
        <Typography gutterBottom variant="h5" component="div">
        {props.title}
        </Typography>
        <Typography variant="body2" color="text.secondary">
        {props.description}
        </Typography>
      </CardContent>
    </Card>
  );
};

export default VideoCard;

App.jsの修正

作成したVideoCard Componentを呼び出す。
Componentの呼び出しはImportしてdivなどと同じように呼び出すだけ。

import VideoCard from './components/VideoCard/VideoCard';

function App() {
  return (
    <div>
      <VideoCard />
    </div>
  );
}

今回は引数で動画の情報を渡すので以下のように修正する。

import './App.css';
import axios from 'axios';
import React, { useState, useEffect } from 'react';
import VideoCard from './components/VideoCard/VideoCard';

function App() {
  const [posts, setPosts] = useState([])

  useEffect(() => {
    axios
    .get('http://localhost:8000/api/home/')
    .then(res=>{setPosts(res.data);})
    .catch(err=>{console.log(err);});
  }, []);

  return (
    <div className="App">
      <h1>動画サイト</h1>
      {posts.map(post => (
        <div>
        <VideoCard title={post.title} img_path={post.img_path} video_path={post.video_path} description={post.description}/>
        </div>
      ))}
    </div>
  );
}

export default App;

コード修正後、DjangoとReactを起動してhttp://localhost:3000/へアクセスすると下記のように表示される。