🐍
【Python】Djangoでデーベースの内容をビューに表示する
開発環境:
項目 | バージョン |
---|---|
windows | 11 |
Vscode | 1.87.2 |
Docker | 26.1.1 |
Docker-compose | 2.27.0 |
python | 3.11.10 |
Django | 5.0.1 |
Psql | 16.5 |
達成目標
- データベース上に登録されている動画ファイルの内容をビューで一覧表示させることができる。
前提
- Djangoのマニュアルの
Writing your first Django app, part 1
を応用した内容となっている。 - アプリケーションのトップページが表示されている状態かつデータベースの設定が完了している状態から解説をしていく。
開発環境の構築がまだの方はこちらから↓
データベースの設定がまたの方はこちらから↓
基礎編
1.アプリケーションフォルダを作成する
アプリケーションフォルダ作成コマンドの実行
アプリケーションフォルダの作成コマンドを実行
docker-compose exec web python manage.py startapp videos
videosアプリケーションフォルダが作成される
settings.py
への追加
プロジェクトフォルダ内の# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'users',
'videos', # 追加
]
2.モデルの作成
動画に関わる情報をmodels.pyファイルに追加
from django.db import models
from django.contrib.auth.models import User
class Video(models.Model):
title = models.CharField(max_length=200) # 動画のタイトル
description = models.TextField(blank=True, null=True) # 動画の説明
video_file = models.FileField(upload_to='videos/', blank=True, null=True) # 動画ファイルを保存
created_at = models.DateTimeField(auto_now_add=True) # 登録日
category = models.CharField(max_length=100, blank=True, null=True) # 動画のカテゴリー
thumbnail = models.ImageField(upload_to='thumbnails/', blank=True, null=True) # サムネイル画像
duration = models.PositiveIntegerField(blank=True, null=True) # 動画の長さ(秒単位)
is_published = models.BooleanField(default=True) # 公開状態
uploaded_by = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True) # アップロードしたユーザー
view_count = models.PositiveIntegerField(default=0) # 視聴回数
rating = models.PositiveIntegerField(default=0) # 動画の評価
updated_at = models.DateTimeField(auto_now=True) # 最終更新日
published_at = models.DateTimeField(null=True, blank=True) # 公開日
def __str__(self):
return self.title
3.マイグレーションの実行
マイグレーションの実行
docker-compose exec web python manage.py makemigrations videos
docker-compose exec web python manage.py migrate videos
出力結果
$ docker-compose exec web python manage.py makemigrations videos
time="2024-11-20T22:42:21+09:00" level=warning msg="C:\\Users\\shimo\\Desktop\\test\\reha_navi\\docker-compose.yml: `version` is obsolete"
Migrations for 'videos':
videos/migrations/0001_initial.py
- Create model Video
$ docker-compose exec web python manage.py migrate videos
Operations to perform:
Apply all migrations: videos
Running migrations:
Applying videos.0001_initial... OK
python admin
)への追加
4.管理画面(admin.pyへ以下を全て追加
from .models import Video
class VideoAdmin(admin.ModelAdmin):
list_display = ('title', 'category', 'created_at', 'is_published', 'uploaded_by', 'view_count', 'rating', 'published_at')
list_filter = ('is_published', 'category', 'created_at')
search_fields = ('title', 'description', 'category')
ordering = ('-created_at',)
date_hierarchy = 'created_at'
admin.site.register(Video, VideoAdmin)
5.ビューの作成
urls.py
ファイルの作成
urls.pyファイルの作成
New-Item videos/urls.py
urls.py
ファイルの編集
urls.pyへ以下を全て追加
from django.urls import path
from . import views
urlpatterns = [
path('', views.video_list, name='video_list'),
path('video/<int:id>/', views.video_detail, name='video_detail'),
]
views.py
ファイルの編集
views.pyへ以下を全て追加
from django.shortcuts import render, get_object_or_404
from .models import Video
def video_list(request):
videos = Video.objects.filter(is_published=True).order_by('-created_at') # 公開されている動画を降順で取得
return render(request, 'videos/video_list.html', {'videos': videos})
def video_detail(request, id):
video = get_object_or_404(Video, id=id)
return render(request, 'videos/video_detail.html', {'video': video})
6.テンプレートの作成
フォルダの作成
テンプレートフォルダの作成
mkdir videos/templates/videos
ファイルの作成
テンプレートファイルの作成
New-Item videos/templates/videos/video_list.html
New-Item videos/templates/videos/video_detail.html
ファイルの編集
video_list.htmlへ以下を全て追加
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>動画一覧</title>
<style>
/* コンテナの設定 */
.video-list {
display: flex;
flex-wrap: wrap; /* 複数行に対応 */
gap: 20px; /* カード間の間隔 */
justify-content: center; /* 中央揃え */
padding: 20px;
list-style-type: none; /* リストスタイルを削除 */
}
/* 各動画カードの設定 */
.video-card {
width: 320px; /* カードの幅 */
border: 1px solid #ddd; /* ボーダー */
border-radius: 8px; /* 角丸 */
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1); /* シャドウ */
overflow: hidden; /* 内容がはみ出ないようにする */
text-align: center;
background-color: #fff;
}
/* カード内のサムネイル画像 */
.video-card img {
width: 100%; /* カード幅に合わせる */
height: auto;
max-height: 200px; /* 画像の最大高さ */
object-fit: cover; /* 画像の縦横比を維持しつつ、領域に収める */
}
/* カード内のタイトル */
.video-card h3 {
font-size: 18px;
margin: 10px 0;
}
/* カード内の説明文 */
.video-card p {
font-size: 14px;
color: #666;
padding: 0 10px 10px;
margin: 0;
}
/* カード内の動画再生エリア */
.video-card video {
width: 100%; /* カード幅に合わせる */
margin-top: 10px; /* 動画の上にスペースを追加 */
}
</style>
</head>
<body>
<h1 style="text-align: center;">動画一覧</h1>
<ul class="video-list">
{% for video in videos %}
<li class="video-card">
{% if video.thumbnail %}
<img src="{{ video.thumbnail.url }}" alt="{{ video.title }}">
{% endif %}
<!-- 動画ファイルを再生 -->
{% if video.video_file %}
<video controls>
<source src="{{ video.video_file.url }}" type="video/mp4">
お使いのブラウザは動画再生に対応していません。
</video>
{% endif %}
<h3>{{ video.title }}</h3>
<p>{{ video.description }}</p>
</li>
{% endfor %}
</ul>
</body>
</html>
video_detail.htmlへ以下を全て追加
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>{{ video.title }}</title>
</head>
<body>
<h1>{{ video.title }}</h1>
<p>{{ video.description }}</p>
<p>カテゴリ: {{ video.category }}</p>
<p>視聴回数: {{ video.view_count }} 回</p>
<p>評価: {{ video.rating }} 点</p>
<p>公開日: {{ video.published_at }}</p>
<p>アップロード者: {{ video.uploaded_by.username }}</p>
<a href="{% url 'video_list' %}">戻る</a>
</body>
</html>
urls.py
にインクルード
7.プロジェクトのurls.pyにインクルードとif settings~を追加
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('videos/', include('videos.urls')), # 追加
]
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
Discussion