0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

商談履歴管理システムの作成

Posted at

この記事は、「Djangoを使用した顧客管理システムの作成」の4つ目の記事です。

前回顧客管理のCRUD機能を作りました。今回は、商談履歴のCRUD機能を作成していきます。

商談履歴のCRUD機能の実装

作業内容

  • 商談履歴のCRUD
    • 商談履歴の登録・閲覧・編集・削除するビューとテンプレートの作成
    • 顧客ごとの商談履歴を一覧表示

ビューの作成

↑前回の記事で作成したviews.pyを編集していきます。前回の記事ですでに商談履歴モデルDealはインポート済みなので、クラスの作成から行っていきます。

crm_app/views.py
from django.core.paginator import Paginator #追加
from .forms import AddDealForm #追加

#商談履歴の閲覧
class DealList(View):
    def get(self,request):
        sort_by = request.GET.get('sort', 'date')  # デフォルトは商談日でソート
        deal = Deal.objects.all().order_by(sort_by)
        paginator = Paginator(deal,10) #1ページに10件
        page = request.GET.get('page')
        deals = paginator.get_page(page)
        return render(request,'crm_app/deal_list.html',{'deal':deals}) 

#商談情報の追加
class AddDeal(View):
    def get(self,request):
        form = AddDealForm()
        return render(request,'crm_app/add_deal.html',{'form':form})

    def post(self,request):
        form = AddDealForm(request.POST)
        if form.is_valid():
            form.save()
            return redirect('deal_list')
        return render(request,'crm_app/add_deal.html',{'form':form})


#商談情報の編集
class EditDeal(View):
    def get(self,request,id):
        deal = get_object_or_404(Deal,id=id)
        form = AddDealForm(instance=deal)
        return render(request,'crm_app/edit_deal.html',{'form':form,'id':id})      
    
    def post(self,request,id):
        deal = get_object_or_404(Deal,id=id)
        form = AddDealForm(request.POST,instance=deal)
        if form.is_valid():
            form.save()
            return redirect('deal_list')
        return render(request,'crm_app/edit_deal.html',{'form':form,'id':id})

#商談情報の削除
class DeleteDeal(View):
    def get(self,request,id):
        deal = get_object_or_404(Deal,id=id)
        return render(request,'crm_app/delete_deal.html',{'deal':deal})
    
    def post(self,request,id):
        deal = get_object_or_404(Deal,id=id)
        deal.delete()
        return redirect('deal_list')
        
deal_list = DealList.as_view()
add_deal = AddDeal.as_view()
edit_deal = EditDeal.as_view()
delete_deal = DeleteDeal.as_view()

基本的に前回記事で作成したCRUD機能を同様に作っています。違う点として、商談履歴一覧表示にページネーションを付けてみました。ページネーションとは情報をページごとに分割して整理するものです。今回は、商談履歴が1ページに10件だけ表示されるようにし、10件を超える商談履歴が保存されたときは、複数ページ作られるようになっています。

テンプレートの作成

こちらも前回同様に作成したビューを基にdeal_list.htmladd_deal.htmledit_deal.htmldelete_deal.htmlを作成していきます。ベースとして前回作成したbase.htmlを使用します。テンプレートは前回とほぼ同じなので、ページネーションを追加したdeal_list.htmlのみ紹介します。

templates/crm_app/deal_list.html
{% extends 'base.html' %}

{% block content %}
<div class="container mt-4">
    <h2>商談履歴一覧</h2>
    <a href="{% url 'add_deal' %}" class="btn btn-primary mb-3">新規商談登録</a>
    
    <div class="mb-3">
        <span class="me-2">ソート:</span>
        <a href="?sort=date" class="btn btn-outline-secondary btn-sm">商談日</a>
        <a href="?sort=customer" class="btn btn-outline-secondary btn-sm">顧客名</a>
        <a href="?sort=title" class="btn btn-outline-secondary btn-sm">商談タイトル</a>
        <a href="?sort=status" class="btn btn-outline-secondary btn-sm">ステータス</a>
    </div>
    
    <table class="table table-striped">
        <thead>
            <tr>
                <th>ID</th>
                <th>顧客名</th>
                <th>商談日</th>
                <th>商談内容</th>
            </tr>
        </thead>
        <tbody>
            {% for d in deal %}
            <tr>
                <td>{{ d.id }}</td>
                <td>{{ d.customer }}</td>
                <td>{{ d.date|date:"Y/m/d" }}</td>
                <td>{{ d.content }}</td>
                <td>
                    <a href="{% url 'edit_deal' d.id %}" class="btn btn-sm btn-warning">編集</a>
                    <a href="{% url 'delete_deal' d.id %}" class="btn btn-sm btn-danger">削除</a>
                </td>
            </tr>
            {% endfor %}
        </tbody>
    </table>

    #ページネーション
    {% if deal.has_other_pages %}
    <nav aria-label="Page navigation" class="mt-4">
        <ul class="pagination justify-content-center">
            {% if deal.has_previous %}
                <li class="page-item">
                    <a class="page-link" href="?page={{ deal.previous_page_number }}{% if request.GET.sort %}&sort={{ request.GET.sort }}{% endif %}">前へ</a>
                </li>
            {% else %}
                <li class="page-item disabled">
                    <span class="page-link">前へ</span>
                </li>
            {% endif %}

            {% for i in deal.paginator.page_range %}
                {% if deal.number == i %}
                    <li class="page-item active">
                        <span class="page-link">{{ i }}</span>
                    </li>
                {% else %}
                    <li class="page-item">
                        <a class="page-link" href="?page={{ i }}{% if request.GET.sort %}&sort={{ request.GET.sort }}{% endif %}">{{ i }}</a>
                    </li>
                {% endif %}
            {% endfor %}

            {% if deal.has_next %}
                <li class="page-item">
                    <a class="page-link" href="?page={{ deal.next_page_number }}{% if request.GET.sort %}&sort={{ request.GET.sort }}{% endif %}">次へ</a>
                </li>
            {% else %}
                <li class="page-item disabled">
                    <span class="page-link">次へ</span>
                </li>
            {% endif %}
        </ul>
    </nav>
    {% endif %}
</div>
{% endblock %}

上記のプログラムの一覧表示の部分は前回とほぼ同じなので、ページネーション部分から説明していきます。
{% if deal.has_other_pages %}は、複数ページあるときTrueを返します。つまり商談履歴が11件以上あるとき、このコードより下の部分が表示されるということです。

{% if deal.has_previous %}は、「前のページがあるか」を確認しています。前のページがあるときTrueを返し、リンクを表示します。

{% for i in deal.paginator.page_range %}は、ページ数に応じて、ページ番号を作成しています。今いるページ以外のページ番号は、リンクにして、ページ移動ができるようにしています。

{% if deal.has_next %}は、「次のページがあるか」を確認しています。動作としては{% if deal.has_previous %}と同様です。

最後にリンクのURL部分<a class="page-link" href="?page={{ i }}{% if request.GET.sort %}&sort={{ request.GET.sort }}{% endif %}">{{ i }}</a>についてです。?page={{ i }}はURLにページ番号を渡している部分です。

https://example.com/?page=2のようなURLを見たことがあると思います。これと同じようにURLを渡しているということです。
{% if request.GET.sort %}の部分は現在のページはソート(並び方の指定)がされているかを確認しています。ページが移動してソートが変わるのは使い勝手が悪くなってしますので、ソート内容も引き継ぐために使用しています。

フォームの作成とルーティング設定

ここも前回とほぼ同じなので、さらっと行きます。
crm_app/forms.pyAddDealFormクラスを作成します。

crm_app/forms.py
class AddDealForm(forms.ModelForm):
    class Meta:
        model = Deal
        fields = ['customer','title','date','status','content','responsible_staff']

違いとしては、fieldぐらいですね。モデルが違うので、fieldが違うのは当たり前です。

ルーティング設定は、プロジェクトのほうは前回設定したので、アプリケーションのほうだけ設定します。

crm_app/urls.py
urlpatterns = [

    ...
    #追加
    path('deals/',deal_list,name='deal_list'),                 
    path('deals/add/',add_deal,name='add_deal'),               
    path('deals/<id>/edit/',edit_deal,name='edit_deal'), 
    path('deals/<id>/delete/',delete_deal,name='delete_deal'), 
]

ここはURLの名前が違うだけです。

今回はここまでにします。今までの部分だけでも普通にwebアプリとして成り立つと思います。
次回は検索機能とダッシュボード機能を追加していきます。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?