↓↓クリックして頂けると励みになります。
【26 | 配達依頼モデル】 << 【ホーム】 >> 【28 | 荷物受取先フォーム】
「core/customer/forms.py」ファイルを編集します。
記述編集 【Desktop/crowdsource/core/customer/forms.py】
from django import forms from django.contrib.auth.models import User from core.models import Customer, Job class BasicUserForm(forms.ModelForm): class Meta: model = User fields = ('last_name', 'first_name') class BasicCustomerForm(forms.ModelForm): class Meta: model = Customer fields = ('avatar',) class JobCreateStep1Form(forms.ModelForm): class Meta: model = Job fields = ('name', 'description', 'category', 'size', 'quantity', 'photo')
「core/customer/views.py」ファイルを編集します。
記述編集 【Desktop/crowdsource/core/customer/views.py】
import firebase_admin from firebase_admin import credentials, auth import stripe from django.shortcuts import render, redirect from django.contrib.auth.decorators import login_required from django.urls import reverse from core.customer import forms from django.contrib import messages from django.contrib.auth.forms import PasswordChangeForm from django.contrib.auth import update_session_auth_hash from django.conf import settings cred = credentials.Certificate(settings.FIREBASE_ADMIN_CREDENTIAL) firebase_admin.initialize_app(cred) stripe.api_key = settings.STRIPE_API_SECRET_KEY @login_required() def home(request): return redirect(reverse('customer:profile')) @login_required(login_url="/sign-in/?next=/customer/") def profile_page(request): user_form = forms.BasicUserForm(instance=request.user) customer_form = forms.BasicCustomerForm(instance=request.user.customer) password_form = PasswordChangeForm(request.user) if request.method == "POST": if request.POST.get('action') == 'update_profile': user_form = forms.BasicUserForm(request.POST, instance=request.user) customer_form = forms.BasicCustomerForm(request.POST, request.FILES, instance=request.user.customer) if user_form.is_valid() and customer_form.is_valid(): user_form.save() customer_form.save() messages.success(request, 'プロフィールが更新されました。') return redirect(reverse('customer:profile')) elif request.POST.get('action') == 'update_password': password_form = PasswordChangeForm(request.user, request.POST) if password_form.is_valid(): user = password_form.save() update_session_auth_hash(request, user) messages.success(request, 'パスワードが更新されました。') return redirect(reverse('customer:profile')) elif request.POST.get('action') == 'update_phone': # Get Firebase user data firebase_user = auth.verify_id_token(request.POST.get('id_token')) request.user.customer.phone_number = firebase_user['phone_number'] request.user.customer.save() messages.success(request, '電話番号が更新されました。') return redirect(reverse('customer:profile')) return render(request, 'customer/profile.html', { "user_form": user_form, "customer_form": customer_form, "password_form": password_form, }) @login_required(login_url="/sign-in/?next=/customer/") def payment_method_page(request): current_customer = request.user.customer # Remove existing card if request.method == "POST": stripe.PaymentMethod.detach(current_customer.stripe_payment_method_id) current_customer.stripe_payment_method_id = "" current_customer.stripe_card_last4 = "" current_customer.save() return redirect(reverse('customer:payment_method')) # Save stripe customer infor if not current_customer.stripe_customer_id: customer = stripe.Customer.create() current_customer.stripe_customer_id = customer['id'] current_customer.save() # Get Stripe payment method stripe_payment_methods = stripe.PaymentMethod.list( customer = current_customer.stripe_customer_id, type = "card", ) print(stripe_payment_methods) if stripe_payment_methods and len(stripe_payment_methods.data) > 0: payment_method = stripe_payment_methods.data[0] current_customer.stripe_payment_method_id = payment_method.id current_customer.stripe_card_last4 = payment_method.card.last4 current_customer.save() else: current_customer.stripe_payment_method_id = "" current_customer.stripe_card_last4 = "" current_customer.save() if not current_customer.stripe_payment_method_id: intent = stripe.SetupIntent.create( customer = current_customer.stripe_customer_id ) return render(request, 'customer/payment_method.html', { "client_secret": intent.client_secret, "STRIPE_API_PUBLIC_KEY": settings.STRIPE_API_PUBLIC_KEY, }) else: return render(request, 'customer/payment_method.html') @login_required(login_url="/sign-in/?next=/customer/") def create_job_page(request): current_customer = request.user.customer if not current_customer.stripe_payment_method_id: return redirect(reverse('customer:payment_method')) step1_form = forms.JobCreateStep1Form() return render(request, 'customer/create_job.html', { "step1_form": step1_form, })
「core/templates/customer/create_job.html」ファイルを編集します。
記述編集 【Desktop/crowdsource/core/templates/customer/create_job.html】
{% extends 'base.html' %}
{% load bootstrap4 %}
{% block head %}
<style>
#pills-tab a {
color: black;
}
#pills-tab a:hover {
color: green;
text-decoration: none;
}
#pills-tab a.active {
color: red;
}
#pickup-map,
#delivery-map {
height: 100%;
}
</style>
{% endblock %}
{% block content %}
<div class="container mt-4">
<div class="row">
<!-- 左側 -->
<div class="col-lg-4">
<div class="card">
<div class="card-header">
依頼する配達の概要
</div>
<div class="card-body">
{% if not job %}
<p>依頼する配達の概要がここに表示されます</p>
{% else %}
{% endif %}
</div>
</div>
</div>
<!-- 右側 -->
<div class="col-lg-8">
<!-- Step tabs -->
<div class="card mb-5">
<div class="card-body">
<ul class="nav nav-pills nav-justified align-items-center mb-3" id="pills-tab" role="tablist">
<li class="nav-item" role="presentation">
<a class="active" id="pills-info-tab" data-toggle="pill" href="#pills-info"
role="tab" aria-controls="pills-info" aria-selected="true">配達の依頼内容</a>
</li>
<i class="fas fa-chevron-right"></i>
<li class="nav-item" role="presentation">
<a id="pills-pickup-tab" data-toggle="pill"
href="#pills-pickup" role="tab" aria-controls="pills-pickup" aria-selected="false">荷物受取先</a>
</li>
<i class="fas fa-chevron-right"></i>
<li class="nav-item" role="presentation">
<a id="pills-delivery-tab" data-toggle="pill"
href="#pills-delivery" role="tab" aria-controls="pills-delivery" aria-selected="false">配達先</a>
</li>
<i class="fas fa-chevron-right"></i>
<li class="nav-item" role="presentation">
<a id="pills-payment-tab" data-toggle="pill"
href="#pills-payment" role="tab" aria-controls="pills-payment" aria-selected="false">支払い</a>
</li>
</ul>
</div>
</div>
<!-- Step forms -->
<b>配達依頼作成</b>
<div class="tab-content" id="pills-tabContent">
<div class="tab-pane fade show active" id="pills-info" role="tabpanel" aria-labelledby="pills-info-tab">
<h1>配達依頼の内容</h1>
<form method="POST" enctype="multipart/form-data">
<b class="text-secondary">配達依頼の情報</b><br />
<div class="card bg-white mt-2 mb-5">
<div class="card-body">
{% csrf_token %}
{% bootstrap_form step1_form %}
</div>
</div>
<input type="hidden" name="step" value="1">
<button type="submit" class="btn btn-success">保存して続ける</button>
</form>
</div>
<div class="tab-pane fade" id="pills-pickup" role="tabpanel" aria-labelledby="pills-info-tab">
<h1>荷物受取先</h1>
</div>
<div class="tab-pane fade" id="pills-delivery" role="tabpanel" aria-labelledby="pills-info-tab">
<h1>配送先</h1>
</div>
<div class="tab-pane fade" id="pills-payment" role="tabpanel" aria-labelledby="pills-info-tab">
<h1>支払い</h1>
</div>
</div>
</div>
</div>
{% endblock %}
一度ブラウザを確認します。
http://127.0.0.1:8000/customer/create_job/

「core/customer/views.py」ファイルを編集します。
記述編集 【Desktop/crowdsource/core/customer/views.py】
import firebase_admin from firebase_admin import credentials, auth import stripe from django.shortcuts import render, redirect from django.contrib.auth.decorators import login_required from django.urls import reverse from core.customer import forms from django.contrib import messages from django.contrib.auth.forms import PasswordChangeForm from django.contrib.auth import update_session_auth_hash from django.conf import settings from core.models import * cred = credentials.Certificate(settings.FIREBASE_ADMIN_CREDENTIAL) firebase_admin.initialize_app(cred) stripe.api_key = settings.STRIPE_API_SECRET_KEY @login_required() def home(request): return redirect(reverse('customer:profile')) @login_required(login_url="/sign-in/?next=/customer/") def profile_page(request): user_form = forms.BasicUserForm(instance=request.user) customer_form = forms.BasicCustomerForm(instance=request.user.customer) password_form = PasswordChangeForm(request.user) if request.method == "POST": if request.POST.get('action') == 'update_profile': user_form = forms.BasicUserForm(request.POST, instance=request.user) customer_form = forms.BasicCustomerForm(request.POST, request.FILES, instance=request.user.customer) if user_form.is_valid() and customer_form.is_valid(): user_form.save() customer_form.save() messages.success(request, 'プロフィールが更新されました。') return redirect(reverse('customer:profile')) elif request.POST.get('action') == 'update_password': password_form = PasswordChangeForm(request.user, request.POST) if password_form.is_valid(): user = password_form.save() update_session_auth_hash(request, user) messages.success(request, 'パスワードが更新されました。') return redirect(reverse('customer:profile')) elif request.POST.get('action') == 'update_phone': # Get Firebase user data firebase_user = auth.verify_id_token(request.POST.get('id_token')) request.user.customer.phone_number = firebase_user['phone_number'] request.user.customer.save() messages.success(request, '電話番号が更新されました。') return redirect(reverse('customer:profile')) return render(request, 'customer/profile.html', { "user_form": user_form, "customer_form": customer_form, "password_form": password_form, }) @login_required(login_url="/sign-in/?next=/customer/") def payment_method_page(request): current_customer = request.user.customer # Remove existing card if request.method == "POST": stripe.PaymentMethod.detach(current_customer.stripe_payment_method_id) current_customer.stripe_payment_method_id = "" current_customer.stripe_card_last4 = "" current_customer.save() return redirect(reverse('customer:payment_method')) # Save stripe customer infor if not current_customer.stripe_customer_id: customer = stripe.Customer.create() current_customer.stripe_customer_id = customer['id'] current_customer.save() # Get Stripe payment method stripe_payment_methods = stripe.PaymentMethod.list( customer = current_customer.stripe_customer_id, type = "card", ) print(stripe_payment_methods) if stripe_payment_methods and len(stripe_payment_methods.data) > 0: payment_method = stripe_payment_methods.data[0] current_customer.stripe_payment_method_id = payment_method.id current_customer.stripe_card_last4 = payment_method.card.last4 current_customer.save() else: current_customer.stripe_payment_method_id = "" current_customer.stripe_card_last4 = "" current_customer.save() if not current_customer.stripe_payment_method_id: intent = stripe.SetupIntent.create( customer = current_customer.stripe_customer_id ) return render(request, 'customer/payment_method.html', { "client_secret": intent.client_secret, "STRIPE_API_PUBLIC_KEY": settings.STRIPE_API_PUBLIC_KEY, }) else: return render(request, 'customer/payment_method.html') @login_required(login_url="/sign-in/?next=/customer/") def create_job_page(request): current_customer = request.user.customer if not current_customer.stripe_payment_method_id: return redirect(reverse('customer:payment_method')) creating_job = Job.objects.filter(customer=current_customer, status=Job.CREATING_STATUS).last() step1_form = forms.JobCreateStep1Form(instance=creating_job) if request.method == "POST": if request.POST.get('step') == '1': step1_form = forms.JobCreateStep1Form(request.POST, request.FILES) if step1_form.is_valid(): creating_job = step1_form.save(commit=False) creating_job.customer = current_customer creating_job.save() return redirect(reverse('customer:create_job')) return render(request, 'customer/create_job.html', { "job": creating_job, "step1_form": step1_form, })
配達依頼を登録できるか確認します。
http://127.0.0.1:8000/customer/create_job/


「core/templates/customer/create_job.html」ファイルを編集します。
記述編集 【Desktop/crowdsource/core/templates/customer/create_job.html】
{% extends 'base.html' %}
{% load bootstrap4 %}
{% block head %}
<style>
#pills-tab a {
color: black;
}
#pills-tab a:hover {
color: green;
text-decoration: none;
}
#pills-tab a.active {
color: red;
}
#pickup-map,
#delivery-map {
height: 100%;
}
</style>
{% endblock %}
{% block content %}
<div class="container mt-4">
<div class="row">
<!-- 左側 -->
<div class="col-lg-4">
<div class="card">
<div class="card-header">
配達依頼の概要
</div>
<div class="card-body">
{% if not job %}
<p>配達依頼があればここに表示されます。</p>
{% else %}
<h4>{{ job.name }}</h4>
<span>数量:{{ job.quantity }}</span><br />
<span>大きさ:{{ job.get_size_display }}</span>
{% endif %}
</div>
</div>
</div>
<!-- 右側 -->
<div class="col-lg-8">
<!-- Step tabs -->
<div class="card mb-5">
<div class="card-body">
<ul class="nav nav-pills nav-justified align-items-center mb-3" id="pills-tab" role="tablist">
<li class="nav-item" role="presentation">
<a class="active" id="pills-info-tab" data-toggle="pill" href="#pills-info"
role="tab" aria-controls="pills-info" aria-selected="true">内容</a>
</li>
<i class="fas fa-chevron-right"></i>
<li class="nav-item" role="presentation">
<a id="pills-pickup-tab" data-toggle="pill"
href="#pills-pickup" role="tab" aria-controls="pills-pickup" aria-selected="false">荷物受取先</a>
</li>
<i class="fas fa-chevron-right"></i>
<li class="nav-item" role="presentation">
<a id="pills-delivery-tab" data-toggle="pill"
href="#pills-delivery" role="tab" aria-controls="pills-delivery" aria-selected="false">配達先</a>
</li>
<i class="fas fa-chevron-right"></i>
<li class="nav-item" role="presentation">
<a id="pills-payment-tab" data-toggle="pill"
href="#pills-payment" role="tab" aria-controls="pills-payment" aria-selected="false">支払い</a>
</li>
</ul>
</div>
</div>
<!-- Step forms -->
<b>配達依頼作成</b>
<div class="tab-content" id="pills-tabContent">
<div class="tab-pane fade show active" id="pills-info" role="tabpanel" aria-labelledby="pills-info-tab">
<h1>内容</h1>
<form method="POST" enctype="multipart/form-data">
<b class="text-secondary">情報</b><br />
<div class="card bg-white mt-2 mb-5">
<div class="card-body">
{% csrf_token %}
{% bootstrap_form step1_form %}
</div>
</div>
<input type="hidden" name="step" value="1">
<button type="submit" class="btn btn-success">保存して続ける</button>
</form>
</div>
<div class="tab-pane fade" id="pills-pickup" role="tabpanel" aria-labelledby="pills-info-tab">
<h1>ピックアップ</h1>
</div>
<div class="tab-pane fade" id="pills-delivery" role="tabpanel" aria-labelledby="pills-info-tab">
<h1>配達</h1>
</div>
<div class="tab-pane fade" id="pills-payment" role="tabpanel" aria-labelledby="pills-info-tab">
<h1>支払い</h1>
</div>
</div>
</div>
</div>
{% endblock %}
ブラウザを確認します。
右側のCOLを追加しています。
http://127.0.0.1:8000/customer/create_job/

仕事を登録したら次のステップに進めるよう実装します。
「core/customer/views.py」ファイルを編集します。
記述編集 【Desktop/crowdsource/core/customer/views.py】
import firebase_admin from firebase_admin import credentials, auth import stripe from django.shortcuts import render, redirect from django.contrib.auth.decorators import login_required from django.urls import reverse from core.customer import forms from django.contrib import messages from django.contrib.auth.forms import PasswordChangeForm from django.contrib.auth import update_session_auth_hash from django.conf import settings from core.models import * cred = credentials.Certificate(settings.FIREBASE_ADMIN_CREDENTIAL) firebase_admin.initialize_app(cred) stripe.api_key = settings.STRIPE_API_SECRET_KEY @login_required() def home(request): return redirect(reverse('customer:profile')) @login_required(login_url="/sign-in/?next=/customer/") def profile_page(request): user_form = forms.BasicUserForm(instance=request.user) customer_form = forms.BasicCustomerForm(instance=request.user.customer) password_form = PasswordChangeForm(request.user) if request.method == "POST": if request.POST.get('action') == 'update_profile': user_form = forms.BasicUserForm(request.POST, instance=request.user) customer_form = forms.BasicCustomerForm(request.POST, request.FILES, instance=request.user.customer) if user_form.is_valid() and customer_form.is_valid(): user_form.save() customer_form.save() messages.success(request, 'プロフィールが更新されました。') return redirect(reverse('customer:profile')) elif request.POST.get('action') == 'update_password': password_form = PasswordChangeForm(request.user, request.POST) if password_form.is_valid(): user = password_form.save() update_session_auth_hash(request, user) messages.success(request, 'パスワードが更新されました。') return redirect(reverse('customer:profile')) elif request.POST.get('action') == 'update_phone': # Get Firebase user data firebase_user = auth.verify_id_token(request.POST.get('id_token')) request.user.customer.phone_number = firebase_user['phone_number'] request.user.customer.save() messages.success(request, '電話番号が更新されました。') return redirect(reverse('customer:profile')) return render(request, 'customer/profile.html', { "user_form": user_form, "customer_form": customer_form, "password_form": password_form, }) @login_required(login_url="/sign-in/?next=/customer/") def payment_method_page(request): current_customer = request.user.customer # Remove existing card if request.method == "POST": stripe.PaymentMethod.detach(current_customer.stripe_payment_method_id) current_customer.stripe_payment_method_id = "" current_customer.stripe_card_last4 = "" current_customer.save() return redirect(reverse('customer:payment_method')) # Save stripe customer infor if not current_customer.stripe_customer_id: customer = stripe.Customer.create() current_customer.stripe_customer_id = customer['id'] current_customer.save() # Get Stripe payment method stripe_payment_methods = stripe.PaymentMethod.list( customer = current_customer.stripe_customer_id, type = "card", ) print(stripe_payment_methods) if stripe_payment_methods and len(stripe_payment_methods.data) > 0: payment_method = stripe_payment_methods.data[0] current_customer.stripe_payment_method_id = payment_method.id current_customer.stripe_card_last4 = payment_method.card.last4 current_customer.save() else: current_customer.stripe_payment_method_id = "" current_customer.stripe_card_last4 = "" current_customer.save() if not current_customer.stripe_payment_method_id: intent = stripe.SetupIntent.create( customer = current_customer.stripe_customer_id ) return render(request, 'customer/payment_method.html', { "client_secret": intent.client_secret, "STRIPE_API_PUBLIC_KEY": settings.STRIPE_API_PUBLIC_KEY, }) else: return render(request, 'customer/payment_method.html') @login_required(login_url="/sign-in/?next=/customer/") def create_job_page(request): current_customer = request.user.customer if not current_customer.stripe_payment_method_id: return redirect(reverse('customer:payment_method')) creating_job = Job.objects.filter(customer=current_customer, status=Job.CREATING_STATUS).last() step1_form = forms.JobCreateStep1Form(instance=creating_job) if request.method == "POST": if request.POST.get('step') == '1': step1_form = forms.JobCreateStep1Form(request.POST, request.FILES) if step1_form.is_valid(): creating_job = step1_form.save(commit=False) creating_job.customer = current_customer creating_job.save() return redirect(reverse('customer:create_job')) # 現在のステップ if not creating_job: current_step = 1 else: current_step = 2 return render(request, 'customer/create_job.html', { "job": creating_job, "step": current_step, "step1_form": step1_form, })
「core/templates/customer/create_job.html」ファイルを編集します。
記述編集 【Desktop/crowdsource/core/templates/customer/create_job.html】
{% extends 'base.html' %}
{% load bootstrap4 %}
{% block head %}
<style>
#pills-tab a {
color: black;
}
#pills-tab a:hover {
color: green;
text-decoration: none;
}
#pills-tab a.active {
color: red;
}
#pickup-map,
#delivery-map {
height: 100%;
}
</style>
{% endblock %}
{% block content %}
<div class="container mt-4">
<div class="row">
<!-- 左側 -->
<div class="col-lg-4">
<div class="card">
<div class="card-header">
配達依頼の概要
</div>
<div class="card-body">
{% if not job %}
<p>配達依頼があればここに表示されます。</p>
{% else %}
<h4>{{ job.name }}</h4>
<span>数量:{{ job.quantity }}</span><br />
<span>大きさ:{{ job.get_size_display }}</span>
{% endif %}
</div>
</div>
</div>
<!-- 右側 -->
<div class="col-lg-8">
<!-- Step tabs -->
<div class="card mb-5">
<div class="card-body">
<ul class="nav nav-pills nav-justified align-items-center mb-3" id="pills-tab" role="tablist">
<li class="nav-item" role="presentation">
<a class="{% if step == 1 %}active{% endif %}" id="pills-info-tab" data-toggle="pill" href="#pills-info"
role="tab" aria-controls="pills-info" aria-selected="true">内容</a>
</li>
<i class="fas fa-chevron-right"></i>
<li class="nav-item" role="presentation">
<a class="{% if step == 2 %}active{% endif %}" id="pills-pickup-tab" data-toggle="pill"
href="#pills-pickup" role="tab" aria-controls="pills-pickup" aria-selected="false">荷物受取先</a>
</li>
<i class="fas fa-chevron-right"></i>
<li class="nav-item" role="presentation">
<a class="{% if step == 3 %}active{% endif %}" id="pills-delivery-tab" data-toggle="pill"
href="#pills-delivery" role="tab" aria-controls="pills-delivery" aria-selected="false">配達先</a>
</li>
<i class="fas fa-chevron-right"></i>
<li class="nav-item" role="presentation">
<a class="{% if step == 4 %}active{% endif %}" id="pills-payment-tab" data-toggle="pill"
href="#pills-payment" role="tab" aria-controls="pills-payment" aria-selected="false">支払い</a>
</li>
</ul>
</div>
</div>
<!-- Step forms -->
<b>配達依頼作成</b>
<div class="tab-content" id="pills-tabContent">
<div class="tab-pane fade {% if step == 1 %}show active{% endif %}" id="pills-info" role="tabpanel" aria-labelledby="pills-info-tab">
<h1>内容</h1>
<form method="POST" enctype="multipart/form-data">
<b class="text-secondary">情報</b><br />
<div class="card bg-white mt-2 mb-5">
<div class="card-body">
{% csrf_token %}
{% bootstrap_form step1_form %}
</div>
</div>
<input type="hidden" name="step" value="1">
<button type="submit" class="btn btn-success">保存して続ける</button>
</form>
</div>
<div class="tab-pane fade {% if step == 2 %}show active{% endif %}" id="pills-pickup" role="tabpanel" aria-labelledby="pills-info-tab">
<h1>荷物受取先</h1>
</div>
<div class="tab-pane fade {% if step == 3 %}show active{% endif %}" id="pills-delivery" role="tabpanel" aria-labelledby="pills-info-tab">
<h1>配達先</h1>
</div>
<div class="tab-pane fade {% if step == 4 %}show active{% endif %}" id="pills-payment" role="tabpanel" aria-labelledby="pills-info-tab">
<h1>支払い</h1>
</div>
</div>
</div>
</div>
{% endblock %}
これでStep1「配達依頼内容」が保存されていたら、Step2「荷物受取先」に自動でジャンプするようになりました。

↓↓クリックして頂けると励みになります。
【26 | 配達依頼モデル】 << 【ホーム】 >> 【28 | 荷物受取先フォーム】