0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

[Django]動画入力フォームでis_valid()がFalseになる現象について

Last updated at Posted at 2024-06-21

はじめに

Djangoを用いてユーザーがアップロードした動画を受け取るシステムを作成していた際にis_valid()Trueにならない論理エラーが発生しました。本記事ではis_valid()に関するエラーとその解決法について記述します。なお、使用しているDjangoのバージョンは5.0.6で、pythonのバージョンは3.11.1です。

is_valid()とは

django公式ドキュメントによると、データが入力されてformのインスタンスに対してis_valid()はデータが正しいかどうかをブール値で返します。form.is_valid()とすることでformに対して検証を行うことができます。

関連コード

vies.py
def file_upload(request):
    print("GGG")
    if request.method == 'POST':
        print("FFF")
        form = UploadFileForm(request.POST, request.FILES)
        print(form.is_valid())
        if form.is_valid():
            print("AAA")
            file_obj = request.FILES['file']
            if file_obj:
                print("BBB")
                handle_uploaded_file(file_obj)
                return render(request, 'file_upload/frontpage.html', {
                    'form': form, 'show_success_message': True
                })
            else:
                return render(request, 'file_upload/frontpage.html', {
                    'form': form, 'error_message': 'ファイルを選択していません。'
                })
    else:
        form = UploadFileForm()
    return render(request, 'file_upload/frontpage.html', {'form': form})
forms.py
from django import forms

class UploadFileForm(forms.Form):
    title = forms.CharField(max_length=50)
    file = forms.FileField()
urls.py
from django.urls import path,include
from . import views

app_name = 'file_upload'

urlpatterns = [
    path('', views.file_upload, name='file_upload'),
    path('process/', views.processing, name='processing'),
    path('feedback/', include('feedback.urls')),
]
frontpage.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>ファイルアップロード</title>
    <style>
        body {
            font-family: Arial, sans-serif;
        }
        .header {
            text-align: left;
            font-size: 2em;
            margin: 20px;
        }
        .container {
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            height: 80vh;
        }
        .file-title {
            font-size: 1.5em;
            margin-bottom: 20px;
        }
        .file-upload {
            margin-bottom: 20px;
        }
        .file-upload input {
            margin-bottom: 10px;
        }
        .process-btn {
            margin-top: 20px;
        }
        .error-message {
            color: red;
            margin-top: 10px;
        }
    </style>
    <script>
        function showSuccessMessage() {
            alert('ファイルが正常にアップロードされました!');
        }

        function showErrorMessage() {
            alert('ファイルを選択していません。');
        }
    </script>
</head>
<body>
    <div class="header">
        preai
    </div>
    <div class="container">
        <div class="file-title">
            ファイルを選択してください
        </div>
        <form id="uploadForm" method="POST" enctype="multipart/form-data">
            {% csrf_token %}
            <div class="file-upload">
                {{ form.file }}
                <button type="submit">アップロード</button>
            </div>
            {% if error_message %}
                <div class="error-message">{{ error_message }}</div>
            {% endif %}
        </form>
        <div class="process-btn">
            <form action="{% url 'file_upload:processing' %}" method="get">
                <button type="submit">処理</button>
            </form>
        </div>
    </div>
    {% if show_success_message %}
        <script>
            showSuccessMessage();
        </script>
    {% endif %}
</body>
</html>

原因と解決策

タイトルを受け取っていないのが原因

タイトルを動画の名前だと勘違いしておりタイトルを受け取るフォームを作っていませんでした。タイトルやファイルを受け取れている場合は出力にちゃんとその文字列が含まれるので勘違いしないように気を付けてください。print(request.POST),print(request.FILESとして表示した結果を以下に示します。

タイトルを受け取っていない場合の出力

フォームのデータ: <QueryDict: {'csrfmiddlewaretoken': ['bEDtPv2b7fUsZ1miO25yHG3rmqiFZqmdZo9MBgJZnYFoV8x9QiRXgiGPK4sj8QPo']}>
アップロードされたファイル: <MultiValueDict: {'file': [<TemporaryUploadedFile: demo.mp4 (video/mp4)>]}>

タイトルを受け取っている場合の出力

フォームのデータ: <QueryDict: {'csrfmiddlewaretoken': ['QvsPSGH9hL0TnTsPOozaaBoqdYneY3EdEfY8EroXxuLPj0DGQElzJd1OBCxS7t7o'], 'title': ['demo']}>
アップロードされたファイル: <MultiValueDict: {'file': [<TemporaryUploadedFile: demo.mp4 (video/mp4)>]}>

フォームのデータの最後にtitleタグが追加されていることが分かります。

解決策

タイトルを受け取っていないためmodels.pyforms.pyを変更して完了。無事に動画を受け取れるようになりました。また、models.pyで形式を指定してforms.pyではforms.ModelFormとして参照するように設定しました。

forms.py
from django import forms
from file_upload.models import Post

class UploadFileForm(forms.ModelForm):
    class Meta:
        model = Post
        fields = ('file', )

models.py
from django.db import models

class Post(models.Model):
    file = models.FileField()

解決後のコード

いかにgithubのリンクを貼っておきます。今回のエラーはfile_uploadファイル内で起こっています。

参照したサイト

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?