Day13-2 Djangoおおおう!
# views.py @login_required def bag(request): bag = request.session.get('bag', {}) bag_products = dict() total_price = 0 for product_id, num in bag.items(): product = Product.objects.get(id=product_id) bag_products[product] = num total_price += product.price * num context = { 'bag_products': bag_products, 'total_price': total_price, } return render(request, 'app/bag.html', context) # bag.html {% block content %} {% for product, num in bag_products.items %} <a href="{% url 'app:detail' product.id %}"> <img src="{{ product.image.url }}" class="product-img"> </a> <h2>{{product.name}}</h2> <div>価格:{{ product.price | intcomma }}</div> <div>個数:{{ num | intcomma }}</div> <div>小計:{{ product.price | multiply:num | intcomma }}</div> {% endfor %} {% endblock %} # sessionのイメージ session = { 'bag' = { '1':99 } }
# views.py
・cart = request.session.get('bag', {}) ........これで、bagセッションを辞書としてとってくる
・bag_products = dict() ........これで、bag_productsという辞書を作成
~~~~~~~~for文の中身~~~~~~~~~~
・ for product_id, num in bag.items() .........これで、bagという辞書に入っているkeyとvalueをproduct_idとnumとしてとってくる。item()は辞書のkeyとvalue両方をとってくる書き方。
・product = Product.objects.get(id=product_id) ......モデルのProductクラスからidをとって、productに入れる
・bag_products[product] = num .....これは辞書に要素を追加している。例えばbag["id"] = valueとすると、表示されるのはbag = {"id":value}というのが追加される。つまりここで表示されるのはbag_products = {"product(つまりproductのid)": numということになる}
【Python入門】dictionary(辞書)の使い方。基本と応用 | 侍エンジニアブログ (ありがとうございます.....)
#xxx.html
ここではviews.pyのcontextからhtmlに渡されたものをもとに、{%%}文の中に中に書く事ができる。
・{% for product, num in bag_products.items %} ..........bag_products.itemsで辞書のペアを取り出す。キーとバリューをproductとnumで置き換えるというか入れるというか。
・a href="{% url 'app:detail' product.id %}"........... product.idでリンクを書ける。
・img src="{{ product.image.url }}" .......... product.image.urlでimageのpathを書く事ができる。
そんな感じっすかね。以上!今日はもっとあげちゃうぜ
Day13 session 辞書
"""bag sessionのイメージ""" session = { 'bag':{ '1': 5, '4': 3, '10': 6, } } # forms.py class AddToBagForm(forms.Form) num = forms.IntegerField( label = '数量', min_value = 1, required=True, ) # views.py """セッションのところだけ取り出す。""" def detail(request, product_id): product = get_objects_or_404(Product, pk=product_id) add_to_bag_form = AddToBagForm(request.POST or None) if add_to_bag_form.is_valid(): num = add_to_bag_form.cleaned_data['num'] if 'bag' in request.session: if str(product_id) in request.session['bag']: request.session['bag'][str(product_id)] += num else: request.session['bag'][str(product_id)] = num else: request.session['bag'] = {str(product_id): num} messages.success(request, f"{product.name}を{num}個買い物カゴにはいってるよ") return redirect('app:detail', product_id=product_id) context = { 'product':product, 'add_to_bag_form':add_to_bag_form, } return render(request, 'app/detail.html', context)
構造:
フォームが有効なら
numに数量というデータを入れる。
1.バッグがセッションに存在するなら
2.product_idというキーがbagというセッションの中に既に存在するなら
bagというセッションの中にあるproduct_idのキーの数量をnum分増加
2.product_idというキーがbagというセッションの中に既に存在しないなら
bagというセッションの中に新しくproduct_idのキーを追加する
1.バッグがセッションに存在しないなら
新しく'bag'というセッションのキーを追加する
3.views.pyのdetailにproduct_idとともにリダイレクトする。
こんな感じかな!また新しくやることがあればこの次のブログでやったるぜ!
Day12 Django基礎
今日は、アップしないが、記録として残しておく。
day11
・名前は狭い範囲のワードを使うこと
・動詞を必ず前に置くこと
def fetch_latest_news(): ... def calc_tax_including(price): ... def aggregate_sum_price(items): ...
is_ , has_ ,で始まる変数名はBoolを返すようにする
def is_valid(sth) return not name.startswith("tttsssss")
意味のまとまりで関数を作ること。
import csv def read_csv(): """ some sentences """ with open(...) as f : reader = csv.reader(f) for row in reader: name = row[0] price = int(row[0]) yield name, price def is_add_price(price): return price < 90000 def main(): products = read.products() for name, price in products: if is_add_price(price) print(name)
・yield とは..........関数を一時的に実行停止させることが出来るもの。下に書いてあるからわからなくなったら読む
【Python入門】yield文の基本的な使い方を解説 | 侍エンジニアブログ
Day10 Django 基礎
#html {% load static %} #base.html <body> {% block content %}{% endblock %} </body>
・{% load static %} でcssやjavascript、画像などを読み込むことができるよん
・この {% block content %}{% endblock %}があるところに他のhtmlを入れていくことができるよん
# html {% extends 'app/base.html' %} {% block content %} {% endblock %}
・{% extends 'app/base.html' %}......これで、base.htmlの延長で他のhtmlを書くことができる。あと{% block content %}{% endblock %}を使うよん
# settings.py STATICFILES_DIRS = ( os.path.join(BASE_DIR, "static") )
・これでプロジェクトディレクトリのstaticを読み込むことができる。
# Interactive console
>>>User.objects.all()
>>><QuerySet [<User: username>]>
・これはクエリセットだけ表示される。
>>>user1 = User.objects.get(username='username') >>>user1.username shijimi >>>user1.date_joined datetime.datetime(10101, 9, 8, 8, 19, 83, 846275, tzin...) >>>user1.is_superuser False
・getで取得するとインスタンス?を表示できる。インスタンスであってるのかわからないが、綺麗なものが取得できる。
# urls.py path('users/<int:pk>', views.users_detail, name='users_detail')
・例えば、views.users_detailというviewの名前であったとしても、クライアントがurlを入力するときの名前もusers_detailとする必要はない。今回のように、users/
・Userモデルの属性はドキュメントにも載っている。
django.contrib.auth | Django documentation | Django
# 画像をアップロードするために。 # models.py class Photo(models.Model): ....... ....... image = models.ImageField(upload_to='photos') ....... # settings.py MEDIA_ROOT = os.path.join(BASE_DIR, 'media') MEDIA_URL = '/media/'
・models.ImageFieldを使うにはPillowをインストールする必要がある
・MEDIA_ROOT......画像の保存先を表す。この記述により、アップロードされた画像はBASE_DIR(ルートディレクトリ)直下のmediaというディレクトリに保存される。
・image = models.ImageField(upload_to='photos')でアップロード先をphotosにしているため、/media/photos/に画像が保存されることになる。
#admin.py from .models import Photo class PhotoAdmin(admin.ModelAdmin) list_display = ('id', 'title') list_display_links = ('id', 'title') admin.site.register(Photo, PhotoAdmin)
・管理者画面で作成したモデルを使うにはadmin.pyに登録する必要がある。このadmin.ModelAdminが何を表すか、継承だろうけど、それがわからない。まあ使っとけということではある。
# console >>> from app.models import Photo >>> photo = Photo.objects.all()[0] <ImageFieldFile: ...> >>> photo.image.url 'MEDIA_URL/photos/........jpeg' >>> photo.image.path ~User/..../...../...../...../...../MEDIA_URL/photos/.........jpeg
・.urlで指定するとその画像のアドレスを指定できるのだが、それらのアドレスの頭には、
MEDIA_URLに指定した文字列がつく。今回はMEDIA_URL = '/media/'としているので画像のアドレスは/media/photos/....jpeg となる。
・MEDIA_URL......ユーザー視点のURL
・STATIC_URL......開発者視点のURL
# プロジェクトのurls.py from django.conf import settings from django.conf.urls.static import static urlpatterns = [ ... ... ] # MEDIA_ROOTをアクセス可能にする urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
これにより、一般ユーザーがmediaディレクトリにアクセスできるようになり、写真が公開することができる。
pip install django-cleanup #settings.py INSTALLED_APPS=[ ... 'django_cleanup']
・これにより写真を消した時に、mediaのなかの写真も一緒に消すことができる。これを入れないと写真が消されてもディレクトリの中に残っていく。
#application urls.py # このauth_viewsにはLoginViewとLogoutViewがあるからそれを今回は使う from django.contrib.auth import views as auth_views urlspattern = [ ..... path('login/', auth_views.LoginView.as_view(template_name='app/login.html'), name='login'), path('logout/', auth_views.LogoutView.as_view(), name='logout') ] # settings.py LOGIN_URL = 'app:login' LOGIN_REDIRECT_URL = 'app:index' LOGOUT_REDIRECT_URL = 'app:index'
・LOGIN_URL.........ユーザーがログインする時に使用するページ
・LOGIN_REDIRECT_URL...........ユーザーがログインした時に最初にリダイレクトさせるURL
・LOGOUT_REDIRECT_URL..........ログアウトしたユーザーをリダイレクトさせるURL
今日はここまで!
Day9 Django 基礎
# views def index(request) return render(request, 'blogs/index.html')
これはrenderメソッドでrequest情報を元にして、blogs/index.htmlを返すよという意味。
# models.py def __str__(self): return self.title
とすると、モデルで設定したものを、adminで表示する時に使うことができる。
# views def index(request): blogs = Blog.objects.order_by('-created_datetime') return render(request, 'blogs/index.html', {'blogs':blogs}) # views def index(request): blogs = Blog.objects.order_by('-created_datetime') params = { 'blogs':blogs } return render(request, 'blogs/index.html', params)
ここの、{'blogs':blogs}でテンプレートに渡すことをしている。これは辞書型でキーが'blogs'、値がblogsとなる。またparamsで定義すれば、paramsを渡すこともできる。
#html <a href="{% url 'blogs:detail' blog_id=blog.id%}">記事を読む</a>
これはblogsアプリケーション内のdetailという名前(urls.py)を選択しているという意味。
blog_id=blog.idというのはblog_idという変数にblogのidを代入している。blog.idでidを取れるから、それを変数に代入している。これでid情報をurlに渡すことができる。
・GETメソッド:情報の読み取り、取得、(サーバーからデータを返してほしい時)
・POSTメソッド:情報の送信、投稿、(サーバーに対して何かしらのデータを送りたい時。データベースに新しい情報を追加することができる。)
# views def new(request) if request.method == POST: form = BlogForm(request.POST) ・ ・ ・
・request.POST........ユーザーがフォームに入力した情報が含まれている。その情報を元に新しいBlogFormインスタンスを生成するという処理になる。
・form = BlogForm(request.POST)を引数にrequest.POSTを取るだけでこのような処理ができる。これはBlogFormがModelFormを継承しているから。
# views def edit(request, blog_id): blog = get_object_or_404(Blog, id=blog_id) form = BlogForm(instance=blog) return render(request, 'blogs/edit.html', {'form':form, 'blog': blog})
・form = BlogForm(instance=blog).........instance=Blogで編集内容の中身を保持しておく。
def edit(request, blog_id): blog = get_object_or_404(Blog, id=blog_id) if request.method == "POST": form = BlogForm(request.POST, instance=blog) if form.is_valid(): form.save() return redirect('blogs:detail', blog_id=blog_id) else: form = BlogForm(instance=blog) return render(request, 'blogs/edit.html', {'form':form, 'blog': blog})
・form = BlogForm(request.POST, instance=blog)........編集の時には、既に特定の記事のインスタンスがあるため、どのインスタンスに対してフォームを作用させるかを指定する必要がある。それがinstance=blogを引数に取る理由。
今日は以上!