<< home

Django QRコード生成アプリ 組み込み手順

1. 必要なパッケージをインストール

QRコードを生成するために qrcode ライブラリをインストールします。

pip install qrcode[pil]

これで、QRコード生成ライブラリが使えるようになります。


2. アプリ作成と登録

アプリ作成

python manage.py startapp qrcodes

settings.pyに追加

INSTALLED_APPS = [
    # 既存のアプリ
    'qrcodes',  # ←追加
]

3. モデル作成

qrcodes/models.py に次のコードを追加します。

from django.db import models
from django.contrib.auth import get_user_model

User = get_user_model()

class Qr_Cords(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    title = models.CharField(max_length=100)
    text = models.TextField()
    qrimage = models.ImageField(upload_to='qrcodes/')
    created = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.title

マイグレーション

python manage.py makemigrations qrcodes
python manage.py migrate

4. ビューの作成

qrcodes/views.py に以下のコードを記述します。

from .models import Qr_Cords
from django.contrib.auth import get_user_model
from django.contrib.auth.mixins import LoginRequiredMixin
from django.core.files.uploadedfile import SimpleUploadedFile
from django.core.paginator import Paginator
from django.http import JsonResponse
from django.shortcuts import redirect
from django.urls import reverse
from django.utils.encoding import force_bytes
from django.utils.http import urlsafe_base64_encode
from django.views.generic import ListView
import io
import qrcode

User = get_user_model()

class Qr_Cord_View( ListView):
    template_name = 'qrcode/qr_home.html'
    paginate_by = 10

    def get_queryset(self):
        self.stex = self.request.GET.get('s_text', '')
        return Qr_Cords.objects.filter(title__contains=self.stex, user=self.request.user).order_by('-created')

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        data = Paginator(self.get_queryset(), self.paginate_by)
        page_number = self.request.GET.get('page')
        page_obj = data.get_page(page_number)

        items = []
        for d in page_obj.object_list:
            items.append({
                'pk': urlsafe_base64_encode(force_bytes(d.pk)),
                'title': d.title,
                'explanation': d.text,
                'article_image': d.qrimage.url,
                'created': d.created.date()
            })

        context['stxt'] = self.stex
        context['page_obj'] = page_obj
        context['items'] = items
        context['title'] = '二次元バーコード生成'
        return context

    def post(self, request, **kwargs):
        mord = self.request.POST.get('mord')
        if mord == 'add':
            title = self.request.POST.get('agenda')
            text = self.request.POST.get('explanation')

            qr = qrcode.QRCode(
                version=1,
                error_correction=qrcode.constants.ERROR_CORRECT_L,
                box_size=10,
                border=4,
            )
            qr.add_data(text)
            qr.make(fit=True)

            img = qr.make_image(fill_color="black", back_color="white")
            img_io = io.BytesIO()
            img.save(img_io, format='PNG')
            img_io.seek(0)

            qr_file = SimpleUploadedFile(f"{title[:5]}_qr.png", img_io.read(), content_type="image/png")

            Qr_Cords.objects.create(
                user=self.request.user,
                title=title,
                text=text,
                qrimage=qr_file
            )

            redirect_url = reverse('qrcodes:qr')
            return JsonResponse({'message': '正常にアップロードされました。', 'redirect_url': redirect_url})

        return redirect('accounts:index')

5. URL設定

qrcodes/urls.py を作成して、以下の内容を記述します。

from django.urls import path
from .views import Qr_Cord_View

app_name = 'qrcodes'

urlpatterns = [
    path('qr/', Qr_Cord_View.as_view(), name='qr'),
]

プロジェクトの urls.py にも追加します。

from django.urls import path, include

urlpatterns = [
    path('', include('qrcodes.urls')),
]

6. テンプレート作成

以下のHTMLファイルを templates/qrcode/qr_home.html に保存してください。


<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>Django QRコード生成アプリ 組み込み手順</title>
    <style>
        .pagination {
            display: -ms-flexbox;
            display: flex;
            padding-left: 0;
            list-style: none;
            border-radius: .25rem;
            justify-content: center;
            margin:5px;
        }
        ul li {
            font-size: 0.9rem;
            display:flex;
            align-items: center;
            font-weight: bolder;
        }
        .text-primary {color: #d500e9!important;}
        .text-secondary {color: #989898!important;}
        .page-link {
            position: relative;
            display: block;
            padding: .5rem .75rem;
            margin-left: -1px;
            line-height: 1.25;
            color: #d500e9;
        }
        .page-dott {color: #d500e9;}
        .d-inline-block {display: inline-block!important;}
        .pagination a {
            color: #d500e9;
            text-decoration: none;
        }
    </style>
</head>
<body>


    <h1>{{ title }}</h1>

<form method="post" enctype="multipart/form-data" id="qr-form">
    {% csrf_token %}
    <input type="hidden" name="mord" value="add">
    <label>タイトル:</label><input type="text" name="agenda"><br>
    <label>QRコードにする文字:</label><input type="text" name="explanation"><br>
    <button type="submit">QRコードを生成</button>
</form>

<h2>生成したQRコード</h2>
{% for item in items %}
<a href="{{ item.article_image }}" target="_blank" rel="noopener noreferrer">
    <p>{{ item.title }} ({{ item.created }})</p>
    <img src="{{ item.article_image }}" width="150"> <br>
    <p>{{ item.explanation }}</p>
</a>
{% endfor %}

    {% if page_obj.has_previous %}
        {% if page_obj.previous_page_number != 1 %}
            <li><a class="page-link text-primary d-inline-block" href="?page=1">1</a></li>
            <li class="page-dott">…</li>
        {% endif %}

        <li><a class="page-link text-primary d-inline-block" href="?page={{ page_obj.previous_page_number }}{% if request.GET.s_text %}&s_text={{ request.GET.s_text }}{% endif %}">{{ page_obj.previous_page_number }}</a></li>
    {% endif %}

    <li class="disabled"><div class="page-link text-secondary d-inline-block disabled" href="#">{{ page_obj.number }}</div></li>

    {% if page_obj.has_next %}
        <li><a class="page-link text-primary d-inline-block" href="?page={{ page_obj.next_page_number }}{% if request.GET.s_text %}&s_text={{ request.GET.s_text }}{% endif %}">{{ page_obj.next_page_number }}</a></li>

        {% if page_obj.next_page_number != page_obj.paginator.num_pages %}
            <li class="page-dott">…</li>
            <li><a class="page-link text-primary d-inline-block" href="?page={{ page_obj.paginator.num_pages }}{% if request.GET.s_text %}&s_text={{ request.GET.s_text }}{% endif %}">{{ page_obj.paginator.num_pages }}</a></li>
        {% endif %}
    {% endif %}

    {% if page_obj.has_next %}
        <li><a class="page-link text-primary d-inline-block" href="?page={{ page_obj.next_page_number }}{% if request.GET.s_text %}&s_text={{ request.GET.s_text }}{% endif %}">>></a></li>
    {% else %}
        <li class="disabled"><div class="page-link text-secondary d-inline-block disabled" href="#">>></div></li>
    {% endif %}
</ul>

<script>
document.getElementById('qr-form').addEventListener('submit', function(e) {
    e.preventDefault();
    const formData = new FormData(this);
    fetch("", {
        method: "POST",
        body: formData,
        headers: {'X-Requested-With': 'XMLHttpRequest'}
    })
    .then(response => response.json())
    .then(data => {
        alert(data.message);
        location.href = data.redirect_url;
    });
});
</script>
</body>
</html>

7. メディア設定

settings.py に以下を追加してください。

MEDIA_URL = '/media/'
MEDIA_ROOT = BASE_DIR / 'media'

urls.py にも次を追加します。

from django.conf import settings
from django.conf.urls.static import static

urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)


ページにアクセスできるようにする(index.html

index.html にボタンを配置します。

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>こんにちは</title>
    {% load static %}
    <link rel="stylesheet" href="{% static 'hello/style.css' %}">
</head>
<body>
    <h1>{{message }}</h1>
    <form action="{% url 'hello:next' %<">
      <button type="submit">次のページへ</button>
    </form>
    

<form action="{% url 'qrcodes:qr' %}">
<button type="submit">二次元バーコード</button>
</form>

</body> </html>

8. 動作確認

  1. python manage.py runserver を実行
  2. http://127.0.0.1:8000/qr/ にアクセス
  3. 文字列を入力してQRコードを生成

これでQRコード生成アプリの完成です!

<< home