質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Django

DjangoはPythonで書かれた、オープンソースウェブアプリケーションのフレームワークです。複雑なデータベースを扱うウェブサイトを開発する際に必要な労力を減らす為にデザインされました。

リストボックス

ユーザーがリストから1つ以上のアイテムを選択できるようにするGUI要素です。

ログイン

ログインは、ユーザーがコンピューターシステムにアクセスするプロセスの事を呼びます。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

3回答

2277閲覧

todoアプリでログインユーザーごとのtodoリストを表示する方法

reol-777

総合スコア14

Django

DjangoはPythonで書かれた、オープンソースウェブアプリケーションのフレームワークです。複雑なデータベースを扱うウェブサイトを開発する際に必要な労力を減らす為にデザインされました。

リストボックス

ユーザーがリストから1つ以上のアイテムを選択できるようにするGUI要素です。

ログイン

ログインは、ユーザーがコンピューターシステムにアクセスするプロセスの事を呼びます。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

1クリップ

投稿2021/01/05 07:38

現在、DjangoでTodoアプリを作っています。ログイン機能は実装できたのですが、ログインしてきたユーザーは全ての情報(todoリスト)を見ることができます。そこで、以下のことを実現したいです。

・ログインしてきたユーザーは個人のtodoリストのみ見ることができる。
・ログインされていない場合(ログアウト状態)は、todoリストを表示、制作できないようにする。

イメージ説明

view

1from django.shortcuts import render 2from django.views.generic import ListView,CreateView,UpdateView 3from .models import TodoModel 4from django.urls import reverse_lazy 5from django_filters.views import FilterView 6from .filters import TodoFilter 7from django.shortcuts import redirect 8from .form import TodoForm 9from django.conf import settings 10import datetime 11from django.core.mail import send_mail 12# Create your views here. 13 14class TodoList(FilterView): 15 template_name = 'list.html' 16 model = TodoModel 17 paginate_by = 10 18 19 filterset_class = TodoFilter 20 strict = False 21 22 def get(self, request, **kwargs): 23 if request.GET: 24 request.session['query'] = request.GET 25 else: 26 request.GET = request.GET.copy() 27 if 'query' in request.session.keys(): 28 for key in request.session['query'].keys(): 29 request.GET[key] = request.session['query'][key] 30 31 return super().get(request, **kwargs) 32 33# 削除ボタンの処理 34 def post(self,request): 35 delete_pk = request.POST['delete'] 36 TodoModel.objects.filter(pk=delete_pk).delete() 37 return redirect('list') 38 39# 通知処理 40 nowtime = datetime.datetime.now().strftime('%Y-%m-%d %H:%M') 41 time = datetime.datetime.strptime(nowtime,'%Y-%m-%d %H:%M') 42 todo_obj = TodoModel.objects.all() 43 for obj in todo_obj: 44 if time == obj.duedate: 45 subject = 'タイトル:{}'.format(obj.title) 46 massege = 'メモ:{}\n期日:{}\nカテゴリ:{}\n'.format(obj.memo,obj.duedate,obj.category) 47 from_mail = [] 48 recipient = [settings.EMAIL_HOST_USER] 49 send_mail(subject, massege, from_mail, recipient) 50 51class TodoCreate(CreateView): 52 template_name = 'create.html' 53 model = TodoModel 54 form_class = TodoForm 55 success_url = reverse_lazy('list') 56 57 58class TodoUpdate(UpdateView): 59 template_name = 'update.html' 60 model = TodoModel 61 fields = ('title','memo','priority','duedate','category') 62 success_url = reverse_lazy('list') 63

basehtml

1<!doctype html> 2{% load static %} 3{% load crispy_forms_tags %} 4<html lang="ja"> 5 <head> 6 <!-- Required meta tags --> 7 <meta charset="utf-8"> 8 <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> 9 10 <!-- Bootstrap CSS --> 11 <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous"> 12 <link rel='stylesheet' href="{% static 'css/style.css' %}"> 13 <title>Todoアプリ</title> 14 {% block customcss %} 15 {% endblock customcss %} 16 </head> 17 <body> 18 19 <div class="nabar-custom-menu"> 20 {% if user.is_authenticated %} 21 <a class="username"><i class="fas fa-user-circle"></i> username : {{ user.get_username }}</a> 22 <a class="redirect-button" href="{% url 'accounts:logout' %}"><i class="fa fa-fw fa-sign-out"></i>Logout</a> 23 {% else %} 24 <a class="redirect-button" href="{% url 'accounts:signup' %}"><i class="fas fa-user-plus"></i> Signup</a> 25 <a class="redirect-button" href="{% url 'accounts:login' %}"><i class="fas fa-sign-in-alt"></i> Login</a> 26 {% endif %} 27 </div> 28 <div class="jumbotron jumbotron-fluid"> 29 <div class="container"> 30 <h1 class="display-4"><a class="title" href="{% url 'list' %}">Todo List</a></h1> 31 <p class="lead">TodoListを使って毎日を効率的に過ごしましょう。</p> 32 </div> 33 </div> 34 35 {% block content %} 36 {% endblock content %} 37 38 <!-- Optional JavaScript --> 39 <!-- jQuery first, then Popper.js, then Bootstrap JS --> 40 <script type="text/javascript" src="{% static 'js/style.js' %}"></script> 41 <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script> 42 <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script> 43 <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js" integrity="sha384-OgVRvuATP1z7JjHLkuOU7Xw704+h835Lr+6QL9UvYjZE3Ipu6Tp75j7Bh/kR0JKI" crossorigin="anonymous"></script> 44 </body> 45</html> 46

listhtml

1{% extends 'base.html' %} 2{% load crispy_forms_tags %} 3 4{% block customcss %} 5 <link href="https://use.fontawesome.com/releases/v5.15.1/css/all.css" rel="stylesheet"> 6 <script src="https://kit.fontawesome.com/5b1578e2a2.js" crossorigin="anonymous"></script> 7{% endblock customcss %} 8 9{% block content %} 10<!-- モーダル 絞り込み検索--> 11<div class='container'> 12 <div id="myModal" class="modal fade" tabindex="-1" role="dialog"> 13 <div class="modal-dialog" role="document"> 14 <div class="modal-content"> 15 <div class="modal-header"> 16 <h5 class="modal-title">絞り込み検索</h5> 17 <button type="button" class="close" data-dismiss="modal" aria-label="閉じる"> 18 <span aria-hidden="true">&times;</span> 19 </button> 20 </div> 21 <form id="filter" method="get"> 22 <div class="modal-body"> 23 {{filter.form|crispy}} 24 </div> 25 </form> 26 <div class="modal-footer"> 27 <a class="btn btn-outline-secondary" data-dismiss="modal">戻る</a> 28 <button type="submit" class="btn btn-outline-secondary" form="filter">検索</button> 29 </div> 30 </div> 31 </div> 32 </div> 33 34 35 <div class="create"><a href="{% url 'create' %}" class="btn btn--orange btn--cubic btn--shadow" tabindex="-1" role="button" aria-disabled="true">NEW LIST</a></div> 36 <div class="search"><a class="btn btn-outline-secondary" data-toggle="modal" data-target="#myModal" href="#">SEARCH</a></div> 37 38<!-- タスク --> 39 {% for item in object_list %} 40 <div class="alert alert-{{ item.priority }}" role="alert"> 41 <!-- 完了ボタン --> 42 <a href="#" class="btn-circle-3d"></a> 43 <div class="item_object">TITLE:{{ item.title}} LIMIT:{{ item.duedate|date:"Y-m-d H:i" }} CATEGORY:{{ item.category }}</div> 44 <a data-toggle="modal" data-target="#DetailModal{{ item.pk }}" class="btn2 btn--detail btn--circle btn--shadow--a" tabindex="-1" role="button" aria-disabled="true"><i class="fas fa-eye fa-3x" data-fa-transform="shrink-8 up-5 left-1.05"></i></a> 45 <a data-toggle="modal" data-target="#DeleteModal{{ item.pk }}" class="btn2 btn--delete btn--circle btn--shadow--a" tabindex="-1" role="button" aria-disabled="true"><i class="fas fa-trash-alt fa-3x" data-fa-transform="shrink-8 up-5 right-1.1"></i></a> 46 <a href="{% url 'update' item.pk %}" class="btn2 btn--update btn--circle btn--shadow--a" tabindex="-1" role="button" aria-disabled="true"><i class="fas fa-pen-fancy fa-3x" data-fa-transform="shrink-8 up-5"></i></a> 47 </div> 48 49 <!-- モーダル 削除画面 --> 50 <div class="modal fade" id="DeleteModal{{ item.pk }}" tabindex="-1" role="dialog" aria-labelledby="basicModal" aria-hidden="true"> 51 <div class="modal-dialog"> 52 <div class="modal-content"> 53 <div class="modal-header"> 54 <h4 class="modal-title" id="myModalLabel">削除確認画面</h4> 55 </div> 56 <div class="modal-body"> 57 <label>データを削除しますか?</label> 58 <p>TITLE:{{ item.title}} LIMIT:{{ item.duedate|date:"Y-m-d H:i" }} CATEGORY:{{ item.category }}</p> 59 </div> 60 <div class="modal-footer"> 61 <form action="" method="POST">{% csrf_token %} 62 <button type="button" class="btn btn-default" data-dismiss="modal">閉じる</button> 63 <button type="submit" class="delete-button" name="delete" value="{{item.pk}}">削除</button> 64 </form> 65 </div> 66 </div> 67 </div> 68 </div> 69 <!-- モーダル 詳細画面 --> 70 <div class="modal fade" id="DetailModal{{ item.pk }}" tabindex="-1" role="dialog" aria-labelledby="basicModal" aria-hidden="true"> 71 <div class="modal-dialog"> 72 <div class="modal-content"> 73 <div class="modal-header"> 74 <h4 class="modal-title" id="myModalLabel">詳細画面</h4> 75 </div> 76 <div class="modal-body"> 77 <p>タイトル:{{ item.title }}</p> 78 <p>メモ:{{ item.memo|linebreaksbr }}</p> 79 <p>期日:{{ item.duedate|date:"Y-m-d H:i" }}</p> 80 <p>カテゴリ:{{ item.category }}</p> 81 </div> 82 <div class="modal-footer"> 83 <button type="button" class="btn btn-default" data-dismiss="modal">閉じる</button> 84 </div> 85 </div> 86 </div> 87 </div> 88 89 {% empty %} 90 <li class="list-group-item"> 91 対象のデータがありません 92 </li> 93 {% endfor %} 94</div> 95<!-- ページネーション読み込み --> 96 {% include "./pagination.html" %} 97{% endblock content %} 98

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

FilterViewをよく知らないんですけど、Djangoの 汎用クラスビューと同じ感じなら、

Python

1class TodoList(FilterView): 2 template_name = 'list.html' 3 # 略 4 5 def get_queryset(self): 6 return TodoModel.objects.filter(user=self.request.user) 7 8 def get(self, request, **kwargs): 9 # 略 10 11 def post(self,request): 12 # 略 13```get_querysetを追加していけると思います。 14TodoModelがどんなモデルかわからないんですけど、Userと結びついてるカラム名がuserということにして書いてます。 15*** 16**----追記----** 17TodoModelにuserフィールドを追加したのち、 18```Python 19class TodoCreate(CreateView): 20 template_name = 'create.html' 21 model = TodoModel 22 form_class = TodoForm 23 success_url = reverse_lazy('list') 24 def get_initial(self): 25 return {'user': self.request.user} 26```CreateViewを変更 27`create.html`で、from.userを表示しないようにする

投稿2021/01/05 22:04

編集2021/01/07 01:27
ForestSeo

総合スコア2720

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

reol-777

2021/01/06 05:55

TodoModelには元々userフィールドが入っていないのですが、後から作っても上手くいきますか?
ForestSeo

2021/01/06 07:18

TodoModelで、Userと結びついてるカラムの名前はなんですか? TodoModelってどんなかんじでしょうか?
reol-777

2021/01/06 07:26 編集

モデルはこんな感じです。 ``` from django.db import models from django.utils import timezone # Create your models here. class Category(models.Model): class Meta: db_table = "category" verbose_name = "カテゴリ" verbose_name_plural = "カテゴリ" category_name = models.CharField(max_length=255,unique=True,verbose_name="カテゴリの名前",null=True) def __str__(self): return self.category_name PRIORITY = (('danger','high'),('info','normal'),('success','low')) class TodoModel(models.Model): class Meta: db_table = "todomodel" verbose_name = "todoモデル" verbose_name_plural = "todoモデル" title = models.CharField(max_length=100,verbose_name="タイトル") memo = models.TextField(verbose_name="メモ") priority = models.CharField( max_length = 50, choices = PRIORITY, verbose_name="優先度" ) duedate = models.DateTimeField(verbose_name="期日",default=timezone.now) category = models.ForeignKey(Category,on_delete = models.PROTECT,verbose_name="カテゴリ",null=True) def __str__(self): return self.title ```
ForestSeo

2021/01/06 08:55 編集

> ログインしてきたユーザーは個人のtodoリストのみ見ることができる。 とありますが、TodoModelがUserと結びついてないので、誰がどのTodoを書いたかが分かりません(自分が書いたTodoはどれなのか...) ForeginKeyでUserと結びつけてください。 Userモデルを自分で作ってないなら、 from django.contrib.auth.models import User で、Userをimportしてください。
reol-777

2021/01/06 14:34

userフィールドにdefault値として、ログインユーザーを入れることは可能ですか?例えばこれは当然無理なんですけどdefault=self.repuest.userみたいな感じで
ForestSeo

2021/01/06 23:33

それはたぶん無理です。 default=1 とするとid=1のユーザーがデフォルトになります。 Todoを作成する画面を作る時に、user以外の情報を入力してもらって、保存する時にuserにログインユーザーを入れて保存することはできます。
reol-777

2021/01/07 01:20

"Todoを作成する画面を作る時に、user以外の情報を入力してもらって、保存する時にuserにログインユーザーを入れて保存することはできます。" ↑これはどこでどのように書けばいいですか?
ForestSeo

2021/01/07 01:29

追記しました。
reol-777

2021/01/07 06:23

その通りにしたのですが、 AttributeError at /list/ 'TodoList' object has no attribute 'user' というエラーが発生します。
ForestSeo

2021/01/07 06:31

TodoListは、追記した内容とは関係ないと思いますが。
guest

0

各ユーザー(アカウント)の登録は、別アプリになっているかと思われます。

views.py(view.py?) に、以下を追記してみてください。

python

1from django.contrib.auth.mixins import LoginRequiredMixin # 追加 2 3class TodoList(LoginRequiredMixin, FilterView): # LoginRequiredMixin, を追加 4 5class TodoCreate(LoginRequiredMixin, CreateView): # LoginRequiredMixin, を追加 6 7class TodoUpdate(LoginRequiredMixin, UpdateView): # LoginRequiredMixin, を追加

投稿2021/01/05 08:25

編集2021/01/05 08:26
_whitecat_22

総合スコア1305

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

reol-777

2021/01/05 09:20

回答ありがとうございます。しかし、LoginRequiredMixinを追加してもログインしていないユーザーがアクセスするとログイン画面に遷移するだけで、実現したいようにはなりませんでした。
_whitecat_22

2021/01/05 09:52 編集

失礼いたしました。 参考になるか分かりませんが、私が書籍を見ながら作成した 会員制(ユーザー登録制)のサービスサイトです。 https://github.com/whitecat-22/private_diary diary と account というアプリケーションがありまして、diary(日記)を書き込んだり、表示したりするプログラム側に、貴殿が実現したい点の参考になる部分があるはずです。 どこ?と言われると、私もはっきりと示せずに申し訳ないのですが、、 例えば、'views.py`で、queryで読み込んだデータのuserと、ログインユーザーのuserが同じという条件として、`[モデル名].objects.filter(user=self.request.user)` であったり、`[データの].user = self.request.user` といった箇所が該当するはずです。
guest

0

色々調べてこのようにしたらうまくいきました!
解答して下さった方、ありがとうございました!

view

1class TodoList(FilterView): 2 template_name = 'list.html' 3 model = TodoModel 4 context_object_name = "lists" 5 6 def get_queryset(self): 7 if self.request.user.is_active: 8 return TodoModel.objects.filter(user=self.request.user) 9 else: 10 return TodoModel.objects.none() 11 12class TodoCreate(LoginRequiredMixin,CreateView): 13 template_name = 'create.html' 14 model = TodoModel 15 form_class = TodoForm 16 success_url = reverse_lazy('list') 17 18 def form_valid(self, form): 19 todo_object = form.save(commit=False) 20 todo_object.user = self.request.user 21 todo_object.save() 22 return super().form_valid(form) 23

投稿2021/01/08 13:06

reol-777

総合スコア14

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問