katsumasa0514
@katsumasa0514 (ASAP k)

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

djangoでDBに、pythonファイル内からアクセス

解決したいこと

WEBアプリを制作しています。
htmlにデータを表示させるためにDBにアクセスしようとしたところエラーが出てしまい、
行き詰まってしまいました。

views.py
@login_required(login_url='/movieist/accounts/login/')
def profile(request):
    profileData = Profile.objects.filter(id=request.user.id)
    reviewData = Review.objects.filter(owner=request.user.id)

#この部分
    res = reviewData.movie_id
    res = api.get_movie(res)

    params = {
        'reviewData': reviewData,
        'profileData': profileData,
        'TMDBData': res,
    }

    return render(request, 'movieist/profile.html', params)
html
           <div class="reviews">
                <div class="container">
                    <h2>レビュー></h2>
                    {% for review in reviewData %}
                    <div class="review">
                        <div class="review-image">

                        </div>
                        <div class="review-contents">
                            <div class="topBox">
                                <div class="titleAndStar">

                                </div>
                                <div class="evaluation">
                                    <h3>{{review.good}}</h3>
                                    <h3>{{review.bad}}</h3>
                                </div>
                            </div>
                            <div class="downBox">
                                <div class="comments">
                                    <h3>{{review.commentTitle}}</h3>
                                    <p>{{review.comment}}</p>
                                </div>
                            </div>
                        </div>
                    </div>
                    {% endfor %}
                </div>
            </div>
models.py
class Review(models.Model):
    owner = models.ForeignKey(User, on_delete=models.CASCADE, related_name='review_owner')
    commentTitle = models.CharField(max_length=40)
    comment = models.TextField()
    movie_id = models.IntegerField()
    good = models.IntegerField(default=0)
    bad = models.IntegerField(default=0)
    star = models.DecimalField(default=0, max_digits=2, decimal_places=1)

エラー

スクリーンショット 2021-01-25 13.20.49.png
スクリーンショット 2021-01-25 13.21.04.png

htmlファイル内でカラムを選択しブラウザに表示することはできますが、
pythonファイル内からカラム(movie_id)を選択しようとした際にエラーが出てしまい、
行き詰まってしまいました。

至らないところも多々あると思いますがよろしくお願いします。

1

6Answer

@login_required(login_url='/movieist/accounts/login/')
def profile(request):
    profileData = Profile.objects.filter(id=request.user.id)
    reviewDataOrg = Review.objects.filter(owner=request.user.id)
    reviewData = (add_movie_info(review) for review in reviewDataOrg)
    print(list(reviewData))

    params = {
        'reviewDataOrg': reviewDataOrg,
        'profileData': profileData,
        'reviewData': reviewData,

    }

    return render(request, 'movieist/profile.html', params)


def add_movie_info(review):
    review.movie_info = api.get_movie(review.movie_id)
    title = review.movie_info['title']
    image = api.get_movie_images(review.movie_id)
    image = f"{api.img_base_url_}{image['posters'][0]['file_path']}"

このような形で変更を行いました。
print(list(reviewData))の部分で[None, None]と表示されてしまいます。

1Like

filter()の戻り値はlist型(配列)のため、"movie_id"というキーが存在せずエラーとなっています。
(Review.objects.filter()にはReviewの配列が返ってきていると思います)

命名から推測するに「レビュー1件毎の映画情報を自DB以外から取得して出力させたい」ような場合、reviewDataをループして各レコードを拡張するような対応が必要かと思います。

以下のようなイメージで伝わるでしょうか。

def profile(request):
  # ..
  reviewDataOrg = Review.objects.filter(owner=request.user.id) # オリジナルのReview
  reviewData = (add_movie_info(review) for review in reviewDataOrg) # 拡張後のReview

# ..

# Reviewを拡張する関数
def add_movie_info(review):
    review.movie_info = api.get_movie(review.movie_id)
0Like

Comments

  1. @katsumasa0514

    Questioner

    回答ありがとうございます!
    pythonファイルの中でデータを所得することができました!

    しかし、拡張した関数を呼び出した後のreviewDataに値が入りません。
    review.movie_infoをHTMLで表示したい場合どうすればいいでしょうか?

    自分なりに調べたのですが、検索の仕方が悪いのか解決できませんでした。
    忙しいところ申し訳ありませんがよろしくお願いします。
  2. ご確認ありがとうございます。

    すみません、私の回答で1点誤りがあったためコメントを追加しました。

リスト内包表記で呼びだしている関数add_movie_info(review)ですが、
拡張後の値をreturnしなければ reviewData には None が設定されてしまいます。

お手数ですが、以下の修正でreviewDataに値が入るかを試して頂けますでしょうか。

def add_movie_info(review):
  review.movie_info = api.get_movie(review.movie_id)
  # ..
+ return review

よろしくお願いいたします。

0Like

Comments

  1. @katsumasa0514

    Questioner

    回答ありがとうございます!

    コメントを追加致しました。

こちらの知識不足です。申し訳ありません。
データ

[<Review: Review object (5)>, <Review: Review object (6)>]

が入りました!
ありがとうございます!

何度も申し訳ありませんが、HTMLの出力はどのように行えばいいでしょうか?
よろしくお願いします。

0Like
                    {% for review in reviewData %}
                    <h1>{{review.title}}</h1>
                    {% endfor %}

このように表示させようとしているのですが、ブラウザで確認してもh1に何も入っていない状態になってしまいます。

0Like

情報ありがとうございます。

movie_infoの中身を参照するのは、以下の方法があります。

  1. HTML内でreview.movie_info['title']のようにアクセス
  2. review.title = movie_info['title'] のように拡張するプロパティへ追加して、HTML内でreview.titleのようにアクセス

ただ、ソースを拝見したところimageをAPIで取得していることから、2の方法でtitleimageを設定してしまった方が良いかもしれないです。

その場合、以下のようになるかと思います。

HTMLへ受け渡すReviewの拡張
views.py
def add_movie_info(review):

    # プロパティ拡張の元ネタ取得
    movie_info = api.get_movie(review.movie_id)
    image = api.get_movie_images(review.movie_id)

    # reviewのプロパティ拡張
    review.title = movie_info['title']
    review.image_path = f"{api.img_base_url_}{image['posters'][0]['file_path']}"

    return review
HTML内で参照
html
{% for review in reviewData %}
<h1>{{review.title}}</h1>
<image src="{{ review.image_path }}">
{% endfor %}

※views.pyにてimageimage_pathを分けている理由は以下になります。
諸説ありますので参考まで。
変数への再代入を避けたいのは何故か

0Like

Comments

  1. @katsumasa0514

    Questioner

    問題なく思い通りの動作をしました!
    本当に丁寧な説明を何度もありがとうございました!
    まだまだ勉強が必要ですね!
    フォローさせていただきますので、機会がありましたらまたよろしくお願いします。
  2. お力になれていればよかったです!
    私もDjangoを勉強中ですので、お互いに頑張りましょう。
    また機会がありましたらよろしくお願いします。

Your answer might help someone💌