前提・実現したいこと
Djangoを用いた料理注文アプリを作成しております。
その機能の中で、
エリア別に送料・配達予想時間・注文に必要な最低金額(料理にかかった金額のみ)の3つのパラメータを予めadminからデーターベースへ情報を格納し、
後からユーザーがアプリでエリアを選択し、現在の注文合計金額が注文に必要な最低金額未満ならば、「あなたのエリアでは△△円の注文金額が必要なので、あと○○円分の注文が必要です」と表示し、それ以上ならば、決済へ進めるボタンが出現する
という仕様を実現しようとしています。
実際のサイトの構成は以下の通りです。
ホーム:アプリ名homepage/テンプレート名top.html--------------
お店トップページ
注文するボタンで住所選択ページへ
住所選択ページ:アプリ名ec/テンプレート名location_register.html-------
エリアA、Bから選択。
仮に
エリアA:送料400円、配達予想時間20分、必要注文最低額1000円
エリアB:送料800円、配達予想時間40分、必要注文最低額2000円
の2つのデータを格納している。
決定ボタンを押して、料理一覧ページへリダイレクト
料理一覧ページ:アプリ名ec/テンプレート名category_list.html---------
カテゴリー別に料理の画像、料理名、価格が並び、各料理に「カートへ追加する」ボタンがある。
カートへ料理を追加するとカート内ページへ。
料理の画像をクリックすると料理詳細ページへ。
料理詳細ページ:アプリ名ec/テンプレート名menu_detail.html------------
その料理の画像、料理名、価格、特記事項が表示され
料理一覧ページへ戻るボタンと、カートへ追加するボタンがある。
カート内ページ:アプリ名cart/テンプレート名cart.html-----------------
追加された料理の一覧(料理名、個数、価格)を表示し、
合計金額を表示。
その下に現在の合計金額が必要注文最低額未満ならば、「あなたのエリアでは△△円の注文金額が必要なので、あと○○円分の注文が必要です」と表示し、
それ以上ならば、決済へ進めるボタンが出現する
(例:ユーザーがエリアAを選択していて、合計金額が800円の時。必要注文最低額の1000円に対して200円足りないので「あなたのエリアでは1000円の注文金額が必要なので、あと200円分の注文が必要です」と表示されているところ、300円の商品を追加したので決済へ進めるボタンが出現した)
なお、カート内の料理の個数は+-ボタンで加減できる。
発生している問題・エラーメッセージ
・エリアに応じた必要注文最低額が画面に表示されない。
(あとのソースコード内の{{ location.mustorderprice }}および、Location.mustorderpriceが反映されない)
・上記の問題のせいで、追加で注文するべき金額がうまく計算できていない。
・上記の問題のせいで、テンプレート内で決済へ進めるボタンを出現させるかしないかを決定するif文がうまく実行できていない。
Internal Server Error: /cart/ Traceback (most recent call last): File "/Users/myname/qsqs/cart/views.py", line 41, in cart_detail rest = Location.mustorderprice - total TypeError: unsupported operand type(s) for -: 'DeferredAttribute' and 'int'
該当のソースコード
アプリ名ec/models.py
Python
1from django.db import models 2 3# Create your models here. 4class Category(models.Model): 5 name = models.CharField('カテゴリ名', max_length=12, unique=True) 6 7 def __str__(self): 8 return self.name 9 10class Menu(models.Model): 11 name = models.CharField('料理名', max_length=36) 12 category = models.ForeignKey(Category, on_delete=models.PROTECT, verbose_name='料理カテゴリ',related_name='menus') 13 price = models.IntegerField('価格') 14 text = models.TextField('特記事項やアレルギー等', blank=True, null=True) 15 image = models.ImageField(upload_to='images', blank=True, null=True) 16 17 def __str__(self): 18 return self.name 19 20class Location(models.Model): 21 name = models.CharField('住所', max_length=64) 22 shippingtax = models.IntegerField('送料') 23 shippingtime = models.IntegerField('配達所要時間(分)') 24 mustorderprice = models.IntegerField('必要注文最低額') 25 26 def __str__(self): 27 return self.name 28 29class ChoiceLocation(models.Model): 30 location = models.ForeignKey(Location, on_delete=models.PROTECT, verbose_name='住所') 31 32 def __str__(self): 33 return self.location 34 35
アプリ名cart/models.py
Python
1from django.db import models 2from ec.models import Menu 3# Create your models here. 4 5class Cart(models.Model): 6 cart_id = models.CharField(max_length=250, blank=True) 7 date_added = models.DateField(auto_now_add=True) 8 9 class Meta: 10 db_table = 'Cart' 11 ordering = ['date_added'] 12 13 def __str__(self): 14 return self.cart_id 15 16class CartItem(models.Model): 17 product = models.ForeignKey(Menu, on_delete=models.CASCADE) 18 cart = models.ForeignKey(Cart, on_delete=models.CASCADE) 19 quantity = models.IntegerField() 20 active = models.BooleanField(default=True) 21 22 class Meta: 23 db_table = 'CartItem' 24 25 def sub_total(self): 26 return self.product.price * self.quantity 27 28 def __str__(self): 29 return self.product
アプリ名ec/views.py
Python
1from django.shortcuts import render, redirect 2from django.http import HttpResponse 3from .models import Menu, Category 4from django.views import generic 5from .forms import LocationRegisterForm 6 7 8class MenuList(generic.ListView): 9 model = Category 10 11class MenuDetail(generic.DetailView): 12 model = Menu 13 14def location_register(request): 15 form = LocationRegisterForm(request.POST or None) 16 if request.method == 'POST' and form.is_valid(): 17 form.save() 18 return redirect('ec:menu_list') 19 20 context = { 21 'form': form 22 } 23 return render(request, 'ec/location_register.html', context)
アプリ名cart/views.py
Python
1from django.shortcuts import render, redirect, get_object_or_404 2from ec.models import Menu, Location 3from .models import Cart, CartItem 4from django.core.exceptions import ObjectDoesNotExist 5 6def _cart_id(request): 7 cart = request.session.session_key 8 if not cart: 9 cart = request.session.create() 10 return cart 11 12def add_cart(request, pk): 13 product = Menu.objects.get(id=pk) 14 try: 15 cart = Cart.objects.get(cart_id=_cart_id(request)) 16 except Cart.DoesNotExist: 17 cart = Cart.objects.create( 18 cart_id = _cart_id(request) 19 ) 20 cart.save() 21 try: 22 cart_item = CartItem.objects.get(product=product, cart=cart) 23 cart_item.quantity += 1 24 cart_item.save() 25 except CartItem.DoesNotExist: 26 cart_item = CartItem.objects.create( 27 product = product, 28 quantity = 1, 29 cart = cart 30 ) 31 cart_item.save() 32 return redirect('cart:cart_detail') 33 34def cart_detail(request, total=0, counter=0, cart_items = None): 35 try: 36 cart = Cart.objects.get(cart_id=_cart_id(request)) 37 cart_items = CartItem.objects.filter(cart=cart, active=True) 38 for cart_item in cart_items: 39 total += (cart_item.product.price * cart_item.quantity) 40 counter += cart_item.quantity 41 rest = Location.mustorderprice - total 42 except ObjectDoesNotExist: 43 pass 44 45 return render(request, 'cart/cart.html', dict(cart_items = cart_items, total = total, counter = counter)) 46 47def cart_remove(request, pk): 48 cart = Cart.objects.get(cart_id=_cart_id(request)) 49 product = get_object_or_404(Menu, id=pk) 50 cart_item = CartItem.objects.get(product=product, cart=cart) 51 if cart_item.quantity > 1: 52 cart_item.quantity -= 1 53 cart_item.save() 54 else: 55 cart_item.delete() 56 return redirect('cart:cart_detail')
アプリ名ec/location_register.html(住所選択ページ)
HTML
1{% extends 'ec/base.html' %} 2{% block content %} 3<p>住所を選択してください</p> 4<p>住所により必要注文最低金額が変化します。</p> 5<form action="" method="Post"> 6 {{ form.as_p }} 7 {% csrf_token %} 8 <button type="submit">決定</button> 9</form> 10{% endblock %}
アプリ名ec/category_list.html(料理一覧ページ)
HTML
1{% extends 'ec/base.html' %} 2{% block content %} 3<a class="nav-link" href="{% url 'cart:cart_detail' %}">カートを見る:({{item_count}})</a> 4 {% for category in object_list %} 5 <div class="each-category-content"> 6 <p>{{category.name}}</p> 7 <div class="article-flex"> 8 {% for menu in category.menus.all %} 9 <p>料理名:{{ menu.name }}</p> 10 <p>価格:{{ menu.price }}</p> 11 <a href="{% url 'ec:menu_detail' menu.pk %}"> 12 <img src='/{{ IMAGE_URL }}{{menu.image}}' height=100 width=200> 13 </a> 14 <a href="{% url 'cart:add_cart' menu.pk %}">Add to Cart</a> 15 {% endfor %} 16 </div> 17 </div> 18 {% endfor %} 19{% endblock %}
アプリ名cart/cart.html(カート内ページ)
HTML
1{% extends 'cart/base.html' %} 2{% block content %} 3{% if not cart_items %} 4 <h1>カートは空です。</h1> 5 <p><a href="{% url 'ec:menu_list' %}">こちら</a>からカートへ料理を追加してください。</p> 6{% else %} 7 <h1>カートの中の料理</h1> 8 <div> 9 <table> 10 <thead> 11 <tr> 12 <th>カート内料理</th> 13 </tr> 14 </thead> 15 <tbody> 16 {% for cart_item in cart_items %} 17 <tr> 18 <td> 19 {{cart_item.product.name}} 20 <br> 21 単価: ¥{{cart_item.product.price}} 22 <br> 23 個数: {{cart_item.quantity}} x ¥{{cart_item.product.price}} 24 </td> 25 <td> 26 ¥{{cart_item.sub_total}} 27 </td> 28 <td> 29 <a href="{% url 'cart:add_cart' cart_item.product.id %}">+</a> 30 31 <p>{{cart_item.quantity}}</p> 32 33 <a href="{% url 'cart:cart_remove' cart_item.product.id %}">-</a> 34 35 </td> 36 </tr> 37 {% endfor %} 38 </tbody> 39 </table> 40 <a href="{% url 'ec:menu_list' %}">料理を追加する</a> 41 <h2>CheckOut</h2> 42 <p>合計金額は: <strong>¥{{ total }}</strong>です。</p> 43 {% if total >= Location.mustorderprice %} 44 <a href="#">決済へすすむ</a> 45 {% else %} 46 <p>あなたのエリアでは{{ location.mustorderprice }}円の注文金額が必要なので、あと{{ rest }}円分の注文が必要です </p> 47 {% endif %} 48 </div> 49 {% endif %} 50{% endblock %}
アプリ名ec/forms.py
Python
1from django import forms 2from .models import ChoiceLocation 3 4class LocationRegisterForm(forms.ModelForm): 5 6 class Meta: 7 model = ChoiceLocation 8 fields = '__all__'
試したこと
昨晩から一日格闘して、最終的にこのような状況になっております。どのように変更すれば、エリアに対応した最低注文金額が表示されるのか、全く正解への検討がつきませんでした。
この度は非常に経験が浅く、周りに頼れる人もいないため、質問させていただくこととしました。
お手数おかけしますが、知恵をお貸しいただけないでしょうか。
どうかよろしくお願いします。
補足情報(FW/ツールのバージョンなど)
MacOS
Django2.2
Python3
回答1件
あなたの回答
tips
プレビュー