{"id":226,"date":"2022-10-22T22:06:37","date_gmt":"2022-10-22T13:06:37","guid":{"rendered":"http:\/\/192.168.0.16:3005\/?p=226"},"modified":"2022-10-22T22:06:39","modified_gmt":"2022-10-22T13:06:39","slug":"django%e3%81%a7%e5%85%ac%e9%96%8bweb%e3%82%a2%e3%83%97%e3%83%aa%e3%82%92firebase%e8%aa%8d%e8%a8%bc%e3%81%a7%e4%bd%9c%e3%82%8b","status":"publish","type":"post","link":"https:\/\/blog.solong.jp\/?p=226","title":{"rendered":"Django\u3067\u516c\u958bWeb\u30a2\u30d7\u30ea\u3092Firebase\u8a8d\u8a3c\u3067\u4f5c\u308b"},"content":{"rendered":"\n<p>Django\u3067\u306e\u958b\u767a\u306e\u52c9\u5f37\u3068\u3057\u3066\u3001\u7df4\u7fd2\u7528\u306b\u4ee5\u4e0b\u306e\u3088\u3046\u306a\u30b5\u30f3\u30d7\u30eb\u30a2\u30d7\u30ea\u3092\u4f5c\u308b\u3002<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>\u6975\u529b\u3084\u3084\u3053\u3057\u3044\u3053\u3068\u306f\u305b\u305a\u3001Google\u3001Twitter\u3001Facebook\u7b49\u3067\u30e6\u30fc\u30b6\u767b\u9332\u3084\u8a8d\u8a3c(\u30ed\u30b0\u30a4\u30f3)\u304c\u3067\u304d\u308b\u3002<\/li><li>\u300c\u30b5\u30fc\u30af\u30eb\u300d\u3068\u3044\u3046\u30e6\u30fc\u30b6\u304c\u96c6\u307e\u308b\u5358\u4f4d\u304c\u3042\u308a\u3001\u30e6\u30fc\u30b6\u306f\u8907\u6570\u306e\u30b5\u30fc\u30af\u30eb\u306b\u6240\u5c5e\u3059\u308b\u3002<\/li><li>\u3042\u3089\u3086\u308b\u30e6\u30fc\u30b6\u306f\u65b0\u3057\u3044\u30b5\u30fc\u30af\u30eb\u3092\u4f5c\u6210\u3067\u304d\u308b\u3002<\/li><li>\u30b5\u30fc\u30af\u30eb\u3078\u306e\u53c2\u52a0\u306f\u3001\u305d\u306e\u30b5\u30fc\u30af\u30eb\u306b\u3059\u3067\u306b\u53c2\u52a0\u3057\u3066\u3044\u308b\u30e1\u30f3\u30d0\u30fc\u306e\u62db\u5f85\u306b\u3088\u308a\u53ef\u80fd\u3068\u306a\u308b\u3002<\/li><li>\u30b5\u30fc\u30af\u30eb\u3054\u3068\u306b\u306f\u3001\u7c21\u5358\u306a\u30e1\u30c3\u30bb\u30fc\u30b8\u30dc\u30fc\u30c9\u304c\u3042\u3063\u3066\u30e1\u30c3\u30bb\u30fc\u30b8\u3092\u3084\u308a\u53d6\u308a\u3067\u304d\u308b\u3002<\/li><\/ul>\n\n\n\n<p>\u6280\u8853\u7684\u306a\u5236\u7d04\u3068\u3057\u3066\u306f\u4ee5\u4e0b\u3068\u3059\u308b\u3002<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>\u30d5\u30ed\u30f3\u30c8\u30a8\u30f3\u30c9\u958b\u767a\u306f\u306a\u3057\u3002React\u3084Angular\u306a\u3093\u304b\u306e\u30d5\u30ec\u30fc\u30e0\u30ef\u30fc\u30af\u4f7f\u308f\u306a\u3044\u3057\u3001Javascript\u3082\u6700\u4f4e\u9650\u306b\u3059\u308b\u3002\u753b\u9762\u9077\u79fb\u306fDjango\u306e\u57fa\u672c\u7684\u306a\u4f7f\u3044\u65b9\u3067\u3001Template\u306eHTML\u3092\u4f7f\u3046\u3002<\/li><\/ul>\n\n\n\n<p>\u4ee5\u964d\u306e\u624b\u9806\u306e\u8aac\u660e\u306b\u304a\u3044\u3066\u3001\u89e3\u8aac\u306f\u30dd\u30a4\u30f3\u30c8\u3060\u3051\u3068\u3057\u3066Django\u306e\u5b66\u7fd2\u30ec\u30d9\u30eb\u306e\u8aac\u660e\u306f\u3057\u306a\u3044\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\u30c6\u30b9\u30c8\u7528\u306e\u30a2\u30d7\u30ea\u3092\u7528\u610f\u3057\u3066\u52d5\u304b\u3059<\/h2>\n\n\n\n<p>\u307e\u305a\u306fDjango\u3092\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3057\u3066StartApp\u307e\u3067\u884c\u304f\u3002<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># Home\u306b\u30a2\u30d7\u30ea\u7528\u306e\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u3092\u4f5c\u6210\nuser@sv:~$ mkdir simplecircle\nuser@sv:~$ cd .\/simplecircle\n\nuser@sv:~\/simplecircle$ python3 -V\nPython 3.10.6\n\n# VirtualEnv\u74b0\u5883\u3092\u4f5c\u6210\nuser@sv:~\/simplecircle$ python3 -m venv scenv\nuser@sv:~\/simplecircle$ . .\/scenv\/bin\/activate\n\n# pip\u306e\u66f4\u65b0\u3001Django\u3068\u30b0\u30ed\u30fc\u30d0\u30eb\u30ed\u30b0\u30a4\u30f3\u30e2\u30b8\u30e5\u30fc\u30eb\u3092\u5c0e\u5165\n(scenv) user@sv:~\/simplecircle$ pip install -U pip\n(\u7701\u7565)\nSuccessfully installed pip-22.2.2\n\n(scenv) user@sv:~\/simplecircle$ pip install django\n(\u7701\u7565)\nSuccessfully installed asgiref-3.5.2 django-4.1.2 sqlparse-0.4.3\n\n(scenv) user@sv:~\/simplecircle$ pip install django-glrm\n(\u7701\u7565)\nSuccessfully installed django-glrm-1.1.3\n\n(scenv) user@sv:~\/simplecircle$ django-admin startproject simplecircle\n(scenv) user@sv:~\/simplecircle$ cd simplecircle\/\n(scenv) user@sv:~\/simplecircle\/simplecircle$ python manage.py startapp app<\/code><\/pre>\n\n\n\n<p>\u3055\u3066\u3001Settings\u306e\u65b9\u306f\u3053\u3053\u3060\u3051\u3044\u3058\u308b\u3002<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><strong>&#91;simplecircle\/settings.py]<\/strong>\n\nALLOWED_HOSTS = &#91;'localhost']\n\nINSTALLED_APPS = &#91;\n    ...\n    'django.contrib.staticfiles',\n    'app'\n]\n\nMIDDLEWARE = &#91;\n    ...\n    'global_login_required.GlobalLoginRequiredMiddleware', &amp;lt;- \u8ffd\u52a0\n    'simplecircle.middleware.AppMiddleware', &amp;lt;- \u8ffd\u52a0\u3001\u5f8c\u3067\u4f5c\u308b\n]\n\n### \u66f8\u304d\u8db3\u3059 \u2193\u2193\u2193\nLOGIN_REDIRECT_URL = '\/app\/circle_board'\nLOGOUT_REDIRECT_URL = '\/accounts\/login'\n\nPUBLIC_PATHS = &#91;\n\t'\/accounts\/',\n]\n### \u66f8\u304d\u8db3\u3059 \u2191\u2191\u2191<\/code><\/pre>\n\n\n\n<p>\u307e\u305a\u306fModel\u3092\u4f5c\u3063\u3066\u3057\u307e\u3046\u3002<br>Circle\u3068\u3044\u3046\u306e\u304c\u3053\u306e\u30a2\u30d7\u30ea\u306e\u4eba\u304c\u96c6\u307e\u3063\u3066\u3044\u308b\u30b5\u30fc\u30af\u30eb\u306e\u30de\u30b9\u30bf\u306b\u306a\u308b\u3002\u5c5e\u6027\u306f\u540d\u524d\u3060\u3051\u3002Joining\u3068\u3044\u3046\u306e\u304cManyToMany\u7684\u306aCircle\u3068\u30e6\u30fc\u30b6\u306e\u7d10\u4ed8\u3051\u30c6\u30fc\u30d6\u30eb\u3002<br>\u6700\u521d\u306f\u4f7f\u308f\u306a\u3044\u3051\u3069\u3082\u3001\u30b5\u30fc\u30af\u30eb\u3078\u306e\u62db\u5f85\u3092\u3059\u308b\u3053\u3068\u306b\u306a\u308b\u306e\u3067\u305d\u306e\u62db\u5f85\u30c1\u30b1\u30c3\u30c8\u306e\u30c6\u30fc\u30d6\u30eb\u3082\u4f5c\u308a\u3001\u3042\u3068\u306f\u30e1\u30c3\u30bb\u30fc\u30b8\u30dc\u30fc\u30c9\u7684\u306a\u3068\u3053\u308d\u306b\u6d41\u308c\u308b\u30e1\u30c3\u30bb\u30fc\u30b8\u3068\u3057\u305f\u3002<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><strong>&#91;app\/models.py]<\/strong>\nfrom django.db import models\nfrom django.contrib.auth.models import User\n\n# Circle - \u30b5\u30fc\u30af\u30eb\nclass Circle(models.Model):\n    def __str__(self):\n        return self.name\n    name = models.CharField(max_length=64)\n\n# Joining - \u30e6\u30fc\u30b6\u304c\u30b5\u30fc\u30af\u30eb\u306b\u5165\u3063\u3066\u3044\u308b\u7d10\u4ed8\u3051\nclass Joining(models.Model):\n    def __str__(self):\n        return self.circle.name + \" hires \" + str(self.user)\n    circle = models.ForeignKey(Circle, on_delete=models.CASCADE)\n    user = models.ForeignKey(User, on_delete=models.CASCADE)\n\n# CircleInvitation - \u30b5\u30fc\u30af\u30eb\u3078\u306e\u62db\u5f85\nclass CircleInvitation(models.Model):\n    def __str__(self):\n        return 'invitation of ' + str(self.circle)\n    circle = models.ForeignKey(Circle, on_delete=models.CASCADE)\n    key = models.TextField('Random Hash')\n    expired_at = models.DateTimeField('Expired At')\n\n# Message - \u30b5\u30fc\u30af\u30eb\u306e\u4f1d\u8a00\u677f\nclass Message(models.Model):\n    def __str__(self):\n        return 'message at' + str(self.posted_at)\n    circle = models.ForeignKey(Circle, on_delete=models.CASCADE)\n    user_posted = models.ForeignKey(User, on_delete=models.CASCADE)\n    body = models.TextField('Message Body')\n    posted_at = models.DateTimeField('Posted At')\n<\/code><\/pre>\n\n\n\n<p>Model\u304c\u6e80\u8db3\u884c\u304f\u51fa\u6765\u306b\u306a\u3063\u305f\u3089\u3082\u3061\u308d\u3093\u3053\u308c\u3002<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ python manage.py makemigrations\n$ python manage.py migrate<\/code><\/pre>\n\n\n\n<p>\u6b21\u306burl\u95a2\u4fc2\u3092\u3002<br>Django\u306e\u4ed8\u5c5e\u306e\u7ba1\u7406\u753b\u9762(admin)\u3082\u4e00\u65e6\u6709\u52b9\u306b\u3059\u308b\u3002\u3053\u306e\u307e\u307e\u3060\u3068\u516c\u958b\u306f\u3067\u304d\u306a\u3044\u3088\u3046\u306a\u6c17\u3082\u3059\u308b\u3051\u3069\u8a2d\u5b9a\u3092\u9593\u9055\u3048\u306a\u3051\u308c\u3070\u554f\u984c\u306a\u3044\u3088\u3046\u306a\u6c17\u3082\u3059\u308b\u3002accounts\u306b\u95a2\u3057\u3066\u306f\u30ed\u30b0\u30a4\u30f3\u8a8d\u8a3c\u95a2\u4fc2\u3092\u3084\u3063\u3066\u304f\u308c\u308b\u306e\u3067\u3044\u3063\u305f\u3093\u5165\u308c\u308b\u304c\u3001\u30ed\u30b0\u30a4\u30f3\u753b\u9762\u3092\u7528\u610f\u3059\u308b\u304f\u3089\u3044\u306b\u3057\u304b\u4f7f\u308f\u306a\u3044\u3002<br>\u30a2\u30d7\u30ea\u5074\u306e\u753b\u9762\u306f1\u753b\u9762\u3060\u3051\u3002\u30b5\u30fc\u30af\u30eb\u306e\u4f1d\u8a00\u8868\u793a\uff06\u6295\u7a3f\u753b\u9762\u3060\u3051\u3068\u3059\u308b\u3002\u30e6\u30fc\u30b6\u304c\u8907\u6570\u306e\u30b5\u30fc\u30af\u30eb\u306b\u53c2\u52a0\u3057\u3066\u3044\u308b\u5834\u5408\u306f\u30b5\u30fc\u30af\u30eb\u306e\u5207\u308a\u66ff\u3048\u304c\u5fc5\u8981\u306a\u306e\u3067\u3001\u305d\u306e\u305f\u3081\u306eView\u3092\u4e00\u3064\u7528\u610f\u3057\u3066\u3044\u308b\u3002<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><strong>&#91;simplecircle\/urls.py]<\/strong>\nfrom django.contrib import admin\nfrom django.urls import path, include\n\nurlpatterns = &#91;\n    path('admin\/', admin.site.urls),\n    path('accounts\/', include('django.contrib.auth.urls')),\n    path('app\/',include('app.urls')),\n]\n\n<strong>&#91;app\/urls.py]<\/strong>\nfrom django.urls import path\nfrom . import views\n\napp_name='app'\nurlpatterns = &#91;\n    path('circle_board', views.circle_board, name='circle_board'),\n    path('circle_switch\/&lt;int:to_circle&gt;', views.circle_switch, name='circle_switch'),\n]\n<\/code><\/pre>\n\n\n\n<p>Admin\u753b\u9762\u304b\u3089\u30c6\u30b9\u30c8\u30c7\u30fc\u30bf\u3092\u767b\u9332\u3057\u3066\u307f\u305f\u3044\u306e\u3067<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><strong>&#91;app\/admin.py]<\/strong>\nfrom django.contrib import admin\nfrom .models import *\n\nadmin.site.register(Circle)\nadmin.site.register(Joining)\nadmin.site.register(CircleInvitation)\nadmin.site.register(Message)<\/code><\/pre>\n\n\n\n<p>\u3053\u306e\u8fba\u307e\u3067\u6765\u305f\u3089\u30b9\u30fc\u30d1\u30fc\u30e6\u30fc\u30b6\u3092\u3072\u3068\u308a\u3001Mike\u304f\u3093\u3068\u3044\u3046\u306e\u3092\u4f5c\u3063\u3066\u304b\u3089\u3001 Django \u306e\u4eee\u30b5\u30fc\u30d0\u3092\u4e0a\u3052\u3066\u898b\u308b\u3002<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ python manage.py createsuperuser --username mike\nEmail address: mike@greatmail.com\nPassword: \nPassword (again): \nSuperuser created successfully.\n$ python manage.py runserver 0.0.0.0:8000<\/code><\/pre>\n\n\n\n<p>Admin\u753b\u9762(http:\/\/localhost:8000\/admin\/)\u306b\u5165\u3063\u3066\u307f\u3066\u3001\u30c6\u30b9\u30c8\u30c7\u30fc\u30bf\u3092\u767b\u9332\u3057\u3066\u307f\u308b\u3002\u307e\u305a\u306f\u30ae\u30bf\u30fc\u7df4\u7fd2\u3068\u7b4b\u30c8\u30ec\u3068\u9aa8\u8463\u30ab\u30e1\u30e9\u3068\u3044\u30463\u3064\u306e\u30b5\u30fc\u30af\u30eb\u3092\u767b\u9332\u3057\u305f\u3002<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"882\" height=\"448\" src=\"http:\/\/192.168.0.16:3005\/wp-content\/uploads\/2022\/10\/image-8.png\" alt=\"\" class=\"wp-image-233\" srcset=\"https:\/\/blog.solong.jp\/wp-content\/uploads\/2022\/10\/image-8.png 882w, https:\/\/blog.solong.jp\/wp-content\/uploads\/2022\/10\/image-8-300x152.png 300w, https:\/\/blog.solong.jp\/wp-content\/uploads\/2022\/10\/image-8-768x390.png 768w\" sizes=\"auto, (max-width: 882px) 100vw, 882px\" \/><\/figure>\n\n\n\n<p>\u6b21\u306bMike\u304f\u3093\u4ee5\u5916\u306b\u3082Kevin\u3068Anna\u3092\u767b\u9332\u3002<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"920\" height=\"466\" src=\"http:\/\/192.168.0.16:3005\/wp-content\/uploads\/2022\/10\/image-9.png\" alt=\"\" class=\"wp-image-234\" srcset=\"https:\/\/blog.solong.jp\/wp-content\/uploads\/2022\/10\/image-9.png 920w, https:\/\/blog.solong.jp\/wp-content\/uploads\/2022\/10\/image-9-300x152.png 300w, https:\/\/blog.solong.jp\/wp-content\/uploads\/2022\/10\/image-9-768x389.png 768w\" sizes=\"auto, (max-width: 920px) 100vw, 920px\" \/><\/figure>\n\n\n\n<p>3\u4eba\u30683\u3064\u306e\u30b5\u30fc\u30af\u30eb\u3092\u9069\u5f53\u306b\u7d10\u3064\u3051\u3066\u3042\u3052\u308b\u3002(anna\u306f\u5168\u90e8\u3001kevin\u306f\u30ab\u30e1\u30e9\u3068\u30ae\u30bf\u30fc\u3001mike\u306f\u7b4b\u30c8\u30ec\u3068\u30ae\u30bf\u30fc)<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"991\" height=\"530\" src=\"http:\/\/192.168.0.16:3005\/wp-content\/uploads\/2022\/10\/image-11.png\" alt=\"\" class=\"wp-image-236\" srcset=\"https:\/\/blog.solong.jp\/wp-content\/uploads\/2022\/10\/image-11.png 991w, https:\/\/blog.solong.jp\/wp-content\/uploads\/2022\/10\/image-11-300x160.png 300w, https:\/\/blog.solong.jp\/wp-content\/uploads\/2022\/10\/image-11-768x411.png 768w\" sizes=\"auto, (max-width: 991px) 100vw, 991px\" \/><\/figure>\n\n\n\n<p>\u3044\u3088\u3044\u3088View\u3092\u3002\u305d\u3053\u307e\u3067\u8907\u96d1\u306a\u3053\u3068\u306f\u3057\u3066\u3044\u306a\u3044\u304c\u3001ModelForm\u3092\u4f7f\u3063\u3066\u3044\u308b\u306e\u3068redirect\u306a\u3093\u304b\u306e\u610f\u5473\u5408\u3044\u304c\u308f\u304b\u3089\u306a\u3044\u5834\u5408\u306fDjango\u306e\u516c\u5f0f\u30c1\u30e5\u30fc\u30c8\u30ea\u30a2\u30eb\u306a\u3069\u3067\u78ba\u8a8d\u3059\u308b\u3068\u3088\u3044\u3002<br>cirecle_board\u306f\u30b5\u30fc\u30af\u30eb\u306e\u4f1d\u8a00\u677f\u30da\u30fc\u30b8\u306b\u306a\u308b\u3002\u3072\u3068\u3053\u3068\u306e\u30e1\u30c3\u30bb\u30fc\u30b8\u304c\u6295\u7a3f\u53ef\u80fd\u306a\u306e\u3067\u30d5\u30a9\u30fc\u30e0\u3092\u51fa\u3057\u3066\u304a\u308a\u3001POST\u30c7\u30fc\u30bf\u304c\u6295\u7a3f\u3055\u308c\u305f\u3089Message\u30af\u30e9\u30b9\u3092\u5229\u7528\u3057\u3066Save\u3092\u884c\u3063\u3066\u3044\u308b\u3002<br>circle_switch\u306frequest.session[&#8216;circle&#8217;]\u3068\u3044\u3046\u3068\u3053\u308d\u306b\u5165\u308bcircle\u306eid\u3092\u5909\u66f4\u3059\u308b\u3060\u3051\u3068\u3044\u3046\u30b7\u30f3\u30d7\u30eb\u306a\u51e6\u7406\u3092\u3057\u3066\u4f1d\u8a00\u677f\u306b\u30ea\u30c0\u30a4\u30ec\u30af\u30c8\u3057\u3066\u3044\u308b\u3002\u4e00\u5fdc\u3001\u53c2\u52a0\u3057\u3066\u3044\u306a\u3044\u4eba\u306f\u5f3e\u304f\u3068\u3044\u3046\u5206\u5c90\u3060\u3051\u306f\u5b9f\u88c5\u3057\u3066\u3044\u308b\u3002<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><strong>&#91;app\/views.py]<\/strong>\nfrom django.shortcuts import render, get_object_or_404, redirect\nfrom django.http import Http404\nfrom .models import *\nfrom .forms import MessageForm\nfrom django.utils import timezone as tz\n\ndef circle_board(request):\n\n    context={}\n\n    context&#91;'circle'] = get_object_or_404(Circle, pk=request.circle.id)\n    context&#91;'swcs'] = Joining.objects.filter(user=request.user)\\\n        .exclude(circle=request.circle.id)\n    context&#91;'form'] = MessageForm()\n    context&#91;'messages'] = Message.objects.filter(circle=request.circle)\n\n    if(request.method == 'POST'):\n\n        p = request.POST\n        m = Message(\n            circle=request.circle,\n            user_posted=request.user,\n            body=p&#91;'body'],\n            posted_at=tz.now(),\n        )\n        m.save()\n\n        return redirect('app:circle_board')\n\n    return render(request, 'circle_board.html', context)\n\ndef circle_switch(request, to_circle):\n\n    j = Joining.objects.filter(user=request.user,circle=to_circle).first()\n    if(j is None):\n        raise Http404('Not be joining to this circle.')\n\n    request.session&#91;'circle'] = to_circle\n\n    return redirect('app:circle_board')\n<\/code><\/pre>\n\n\n\n<p>\u4e0a\u3067\u3001MessageForm\u3068\u51fa\u3066\u304d\u305fModelform\u3092app\u30d5\u30a9\u30eb\u30c0\u306e\u4e0b\u306bforms.py\u3068\u3057\u3066\u4f5c\u6210\u3002<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><strong>&#91;app\/forms.py]<\/strong>\nfrom django import forms\nfrom .models import Message\n\nclass MessageForm(forms.ModelForm):\n\n    class Meta:\n        model = Message\n        fields = &#91;\"body\"]\n<\/code><\/pre>\n\n\n\n<p>Template\u3092\u4f5c\u6210\u3002\u307e\u305a\u306fapp\/temlates\u30d5\u30a9\u30eb\u30c0\u3092\u5207\u3063\u305f\u4e0a\u3067\u3001\u305d\u3053\u306bcircle_board\u753b\u9762\u306ehtml\u3092\u7f6e\u304f\u3002<br>\u5927\u304d\u304f3\u30d6\u30ed\u30c3\u30af\u3042\u308b\u3053\u3068\u3092\u78ba\u8a8d\u3057\u3066\u307b\u3057\u3044\u3002<br> 1: \u30b5\u30fc\u30af\u30eb\u306e\u540d\u79f0\u3092\u5927\u304d\u304f\u8868\u793a\u3001\u30ed\u30b0\u30a4\u30f3\u4e2d\u306e\u30e6\u30fc\u30b6\u3068\u30ed\u30b0\u30a2\u30a6\u30c8\u7528\u306e\u30ea\u30f3\u30af\u3092\u8868\u793a\u3002<br> 2: \u4ed6\u306e\u30b5\u30fc\u30af\u30eb\u306e\u30dc\u30fc\u30c9\u3078\u5207\u308a\u66ff\u3048(circle_switch)\u3092\u3059\u308b<br> 3: \u4f1d\u8a00\u30e1\u30c3\u30bb\u30fc\u30b8\u306e\u6295\u7a3f\u30d5\u30a9\u30fc\u30e0\u3068\u3001\u6295\u7a3f\u6e08\u307f\u306e\u30e1\u30c3\u30bb\u30fc\u30b8\u306e\u8868\u793a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><strong>&#91;app\/templates\/circle_board.html]<\/strong>\n&lt;!DOCTYPE html&gt;\n&lt;html lang=\"en\" dir=\"ltr\"&gt;\n  &lt;head&gt;\n    &lt;meta charset=\"utf-8\"&gt;\n    &lt;title&gt;Circle Board&lt;\/title&gt;\n  &lt;\/head&gt;\n  &lt;body&gt;\n    &lt;h1&gt;Circle: {{circle.name}}&lt;\/h1&gt;\n    &lt;p&gt;Hi {{request.user.username}}. &lt;a href=\"{% url 'logout' %}\"&gt;Logout&lt;\/a&gt;&lt;\/p&gt;\n\n\n    &lt;h2&gt;Change Circle&lt;\/h2&gt;\n      {% for c in swcs %}\n        &lt;p&gt;&lt;a href=\"{% url 'app:circle_switch' c.circle.id %}\"&gt;\n          {{c.circle.name}}\n        &lt;\/a&gt;&lt;\/p&gt;\n      {% endfor %}\n\n\n\n    &lt;h2&gt;Message Board&lt;\/h2&gt;\n\n    &lt;form method=\"POST\"&gt; {% csrf_token %}\n        &lt;fieldset&gt;\n          {% for field in form %}\n            &lt;label&gt;{{ field.label_tag }}&lt;\/label&gt;\n            &lt;div&gt;\n                {{ field }}\n                {{ field.errors }}\n            &lt;\/div&gt;\n          {% endfor %}\n          &lt;input name=\"submit\" type=\"submit\" value=\"Post\" \/&gt;\n        &lt;\/fieldset&gt;\n    &lt;\/form&gt;\n\n    {% for m in messages %}\n    &lt;p&gt;\n      {{m.user_posted.username}} sayid in {{m.posted_at}} : {{m.body}}\n    &lt;\/p&gt;\n    {% endfor %}\n\n\n  &lt;\/body&gt;\n&lt;\/html&gt;<\/code><\/pre>\n\n\n\n<p>\u305d\u308c\u3068\u3001\u30ed\u30b0\u30a4\u30f3\u753b\u9762\u7528\u306b\u4e00\u3064\u3060\u3051templates\u306e\u4e0b\u306bregistration\u3068\u3044\u3046\u30d5\u30a9\u30eb\u30c0\u3092\u6398\u3063\u3066\u30d5\u30a1\u30a4\u30eb\u3092\u7f6e\u304f\u3002<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><strong>&#91;app\/templates\/login.html]<\/strong>\n&lt;\/&lt;!DOCTYPE html&gt;\n&lt;html lang=\"en\" dir=\"ltr\"&gt;\n  &lt;head&gt;\n    &lt;meta charset=\"utf-8\"&gt;\n    &lt;title&gt;Circle Board&lt;\/title&gt;\n  &lt;\/head&gt;\n  &lt;body&gt;\n\n    &lt;h2&gt;Login&lt;\/h2&gt;\n    &lt;form method=\"post\"&gt;\n      {% csrf_token %}\n      {{ form.as_p }}\n      &lt;button type=\"submit\"&gt;Login&lt;\/button&gt;\n    &lt;\/form&gt;\n\n  &lt;\/body&gt;\n&lt;\/html&gt;<\/code><\/pre>\n\n\n\n<p>\u3042\u3068\u306f\u3001\u30e6\u30fc\u30b6\u304c\u4eca\u3069\u3053\u306e\u30b5\u30fc\u30af\u30eb\u3092\u898b\u3066\u3044\u308b\u306e\u304b\u3092Session\u3067\u7ba1\u7406\u3057\u305f\u3044\u306e\u3067\u30df\u30c9\u30eb\u30a6\u30a7\u30a2\u3092\u4e00\u3064\u4f5c\u308b\u3002\u3084\u3063\u3066\u3044\u308b\u3053\u3068\u306f\u30b7\u30f3\u30d7\u30eb\u306b\u3044\u3046\u30683\u3064\u304f\u3089\u3044\u3067<br>\u300c\u30a2\u30af\u30bb\u30b9\u3092\u53d7\u3051\u305f\u3068\u304d\u306b\u30e6\u30fc\u30b6\u304c\u30ed\u30b0\u30aa\u30f3\u3057\u3066\u3044\u3066\u307e\u3060request.session[&#8216;circle&#8217;]\u304c\u30bb\u30c3\u30c8\u3055\u308c\u3066\u3044\u306a\u3044\u5834\u5408\u306f\u9069\u5f53\u306a\u3082\u306e\u3092\u4e00\u3064\u9078\u3076\u300d<br>\u300crequest.session[&#8216;circle&#8217;]\u306bID\u306e\u6570\u5024\u304c\u4fdd\u5b58\u3055\u308c\u3066\u3044\u305f\u3089\u3001Circle\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u3092request.circle\u306b\u30bb\u30c3\u30c8\u3059\u308b=View\u3067request.circle\u304c\u3044\u304d\u306a\u308a\u4f7f\u3048\u308b\u300d<br>\u300c\u30ed\u30b0\u30aa\u30f3\u3057\u3066\u3044\u308b\u30e6\u30fc\u30b6\u304c\u3069\u3053\u306eCircle\u306b\u3082\u6240\u5c5e\u3057\u3066\u3044\u306a\u3044\u5834\u5408\u306f\u30a8\u30e9\u30fc\u306b\u306a\u308b(return &#8220;error&#8221; \u3068\u304b\u3044\u307e\u6642\u70b9\u306f\u9069\u5f53)\u300d<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>from app.models import Circle, Joining\nfrom django.shortcuts import redirect,get_object_or_404\n\ndef AppMiddleware(get_response):\n\n    def middleware(request):\n\n        if request.user.is_authenticated:\n            if('circle' not in request.session):\n                j = Joining.objects.filter(user=request.user).first()\n                if j is None:\n\n                    # the user is orfan!!\n                    return \"error\"\n\n                else:\n                    # get company and set session from top hire records.\n                    request.session&#91;'circle'] = j.circle.id\n                    circle = j.circle\n\n            else:\n                circle = get_object_or_404(Circle, pk=request.session&#91;'circle'])\n\n        else:\n            circle = None\n\n        request.circle = circle\n\n        response = get_response(request)\n        return response\n\n    return middleware\n<\/code><\/pre>\n\n\n\n<p>\u3055\u3066\u52d5\u304b\u3057\u3066\u898b\u308b\u3068\u3001\u3053\u3093\u306a\u30a2\u30d7\u30ea\u304c\u3061\u3083\u3093\u3068\u52d5\u3044\u305f\u3002Mike\u3067\u30ed\u30b0\u30a4\u30f3\u3057\u3066\u3044\u3066\u30ae\u30bf\u30fc\u306e\u30b5\u30fc\u30af\u30eb\u306b\u3044\u308b\u3002Mike\u304c\u53c2\u52a0\u3057\u3066\u3044\u308b\u4ed6\u306e\u30b5\u30fc\u30af\u30eb\u3068\u3057\u3066\u306f\u7b4b\u30c8\u30ec\u304c\u3042\u308b\u306e\u3067Change Circle\u306b\u306f\u305d\u308c\u304c\u8868\u793a\u3055\u308c\u3066\u3044\u308b\u3002<br>Message Board\u306b\u306f\u4ed6\u306e\u30e6\u30fc\u30b6\u304c\u6295\u7a3f\u3057\u305f\u30e1\u30c3\u30bb\u30fc\u30b8\u3082\u542b\u3081\u3066\u8868\u793a\u3055\u308c\u3066\u3044\u308b\u3002<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"975\" height=\"800\" src=\"http:\/\/192.168.0.16:3005\/wp-content\/uploads\/2022\/10\/image-13.png\" alt=\"\" class=\"wp-image-238\" srcset=\"https:\/\/blog.solong.jp\/wp-content\/uploads\/2022\/10\/image-13.png 975w, https:\/\/blog.solong.jp\/wp-content\/uploads\/2022\/10\/image-13-300x246.png 300w, https:\/\/blog.solong.jp\/wp-content\/uploads\/2022\/10\/image-13-768x630.png 768w\" sizes=\"auto, (max-width: 975px) 100vw, 975px\" \/><\/figure>\n\n\n\n<p>\u3053\u308c\u3067\u57fa\u672c\u7684\u306a\u30a2\u30d7\u30ea\u306f\u4f5c\u308a\u7d42\u3048\u305f\u3068\u3059\u308b\u3002\u4eca\u306e\u6240Circle\u306e\u65b0\u898f\u8ffd\u52a0\u753b\u9762\u3084\u30e6\u30fc\u30b6\u3092\u65b0\u898f\u306b\u767b\u9332\u3059\u308b\u753b\u9762\u306fAdmin\u753b\u9762\u306b\u3057\u304b\u306a\u3044\u304c\u3001\u3053\u308c\u306f\u8a8d\u8a3c\u3092Firebase\u3092\u4f7f\u3063\u3066Google\u306a\u3069\u306e\u30bd\u30fc\u30b7\u30e3\u30eb\u30b5\u30fc\u30d3\u30b9\u3068\u306e\u9023\u643a\u3067\u4f5c\u308b\u7df4\u7fd2\u7528\u306e\u524d\u63d0\u306a\u306e\u3067\u3001\u305d\u3053\u3078\u9032\u3080\u3053\u3068\u306b\u3059\u308b\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Firebase\u8a8d\u8a3c\u3092\u5c0e\u5165<\/h2>\n\n\n\n<p>\u3053\u306e\u7c21\u5358\u306a\u30a2\u30d7\u30ea\u306bFirebase\u8a8d\u8a3c\u3092\u7d44\u307f\u8fbc\u3093\u3067\u3044\u304f\u300240\u6642\u9593\u304f\u3089\u3044\u8abf\u3079\u307e\u304f\u3063\u3066\u3088\u3046\u3084\u304f\u5927\u4f53\u52d5\u304f\u3088\u3046\u306b\u306a\u3063\u305f\u3002<\/p>\n\n\n\n<p>\u3072\u3068\u307e\u305aFirebase\u306b\u306e\u30a2\u30ab\u30a6\u30f3\u30c8\u3092\u767b\u9332\u3057\u3066\u4ee5\u4e0b\u306e\u753b\u9762\u3067\u3000&lt;\/> \u306eWeb\u3092\u9078\u629e\u3057\u3001\u3042\u308c\u3053\u308c\u307f\u3064\u3064\u306a\u3093\u3068\u306a\u304f\u3053\u306e\u753b\u9762\u307e\u3067\u305f\u3069\u308a\u7740\u304f\u3002<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"445\" src=\"http:\/\/192.168.0.16:3005\/wp-content\/uploads\/2022\/10\/image-18-1024x445.png\" alt=\"\" class=\"wp-image-252\" srcset=\"https:\/\/blog.solong.jp\/wp-content\/uploads\/2022\/10\/image-18-1024x445.png 1024w, https:\/\/blog.solong.jp\/wp-content\/uploads\/2022\/10\/image-18-300x130.png 300w, https:\/\/blog.solong.jp\/wp-content\/uploads\/2022\/10\/image-18-768x334.png 768w, https:\/\/blog.solong.jp\/wp-content\/uploads\/2022\/10\/image-18.png 1304w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>\u30e1\u30fc\u30eb\/\u30d1\u30b9\u30ef\u30fc\u30c9\u8a8d\u8a3c\u3068\u3001Google\u3068Twitter\u3042\u305f\u308a\u3092\u30ed\u30b0\u30aa\u30f3\u65b9\u6cd5\u306b\u306f\u5165\u308c\u3066\u304a\u304d\u305f\u3044\u306e\u3067\u3001\u3053\u3053\u306fWeb\u3067\u8abf\u3079\u306a\u304c\u3089\u5b9f\u65bd\u3002Google\u306f\u7c21\u5358\u3060\u3063\u305f\u6c17\u304c\u3059\u308b\u3051\u3069\u3001Twitter\u306b\u3064\u3044\u3066\u306fElevated Access\u306e\u7533\u8acb\u3068\u3044\u3046\u306e\u304c\u5fc5\u8981\u3067\u5c11\u3057\u624b\u9593\u53d6\u3063\u305f\u3002\u624b\u9806\u306e\u30e1\u30e2\u3092\u3053\u3053\u306f\u6b8b\u3057\u3066\u3044\u306a\u3044\u3002<\/p>\n\n\n\n<p>Firebase\u5074\u304c\u5927\u4f53\u6574\u3063\u305f\u306a\u3089\u3070\u3001\u30a2\u30d7\u30ea\u5074\u3092\u4f5c\u3063\u3066\u3044\u304f\u3002<br>\u307e\u305a\u3001\u5168\u4f53\u7684\u306b\u4ee5\u4e0b\u306e\u69cb\u6210\u3068\u306a\u3063\u3066\u3044\u308b\u3002\u7d50\u69cb\u3084\u3084\u3053\u3057\u3044\u3051\u3069\u6700\u4f4e\u9650\u8a8d\u8a3c\u51fa\u3084\u308a\u305f\u3044\u3053\u3068\u3092\u3084\u3063\u3066\u3044\u304f\u3068\u307b\u307c\u3053\u308c\u304f\u3089\u3044\u306b\u306f\u306a\u308b\u6c17\u304c\u3059\u308b\u3002<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"545\" src=\"http:\/\/192.168.0.16:3005\/wp-content\/uploads\/2022\/10\/image-17-1024x545.png\" alt=\"\" class=\"wp-image-251\" srcset=\"https:\/\/blog.solong.jp\/wp-content\/uploads\/2022\/10\/image-17-1024x545.png 1024w, https:\/\/blog.solong.jp\/wp-content\/uploads\/2022\/10\/image-17-300x160.png 300w, https:\/\/blog.solong.jp\/wp-content\/uploads\/2022\/10\/image-17-768x409.png 768w, https:\/\/blog.solong.jp\/wp-content\/uploads\/2022\/10\/image-17.png 1169w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">Portal<\/h3>\n\n\n\n<p>Django\u3068\u3057\u3066View\u3092\u4e00\u3064\u5207\u308b\u3002\u3084\u3063\u3066\u3044\u308b\u3053\u3068\u306fFirebase Auth UI\u3092\u307b\u307c\u30de\u30cb\u30e5\u30a2\u30eb\u901a\u308a\u306b\u8868\u793a\u3059\u308b\u3060\u3051\u3002<br>\u3082\u3057\u3059\u3067\u306bDjango\u30a2\u30d7\u30ea\u306b\u8a8d\u8a3c\u6e08\u307f\u3067\u3042\u308c\u3070\u30a2\u30d7\u30ea\u306e\u30c8\u30c3\u30d7\u30da\u30fc\u30b8(circle_board)\u306b\u98db\u3070\u3059\u304c\u3001\u305d\u3046\u3067\u306a\u3051\u308c\u3070portal.html\u3092\u30ec\u30f3\u30c0\u30ea\u30f3\u30b0\u3059\u308b\u3060\u3051\u3002<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&#91;views.py]\ndef portal(request):\n\n    if(request.user.is_authenticated):\n        return redirect('app:circle_board')\n\n    return render(request, 'portal.html')<\/code><\/pre>\n\n\n\n<p>templates\/portal.html\u306f\u3001\u307b\u307c\u30de\u30cb\u30e5\u30a2\u30eb\u901a\u308a\u306bFirebase Auth UI\u3092\u8868\u793a\u3055\u305b\u308b\u3002<br>\u305f\u3060\u3001firebase\u305d\u306e\u3082\u306e\u306e\u30de\u30cb\u30e5\u30a2\u30eb\u3068\u304b\u3060\u3068firebase-app.js\u3068\u304b\u3092\u4f7f\u308f\u305b\u3088\u3046\u3068\u3057\u304f\u308b\u304c\u3001&#8221;-compat&#8221;\u4ed8\u304d\u306e\u30d5\u30a1\u30a4\u30eb\u3092\u9078\u3076\u3088\u3046\u306b\u6ce8\u610f\u3002\u305d\u3046\u3067\u306a\u3051\u308c\u3070module\u3068\u3057\u3066\u5229\u7528\u3057\u306a\u3051\u308c\u3070\u306a\u3089\u306a\u304f\u306a\u308a\u3001Javascript\u3042\u307e\u308a\u8a73\u3057\u304f\u306a\u3044\u3051\u3069\u3001&lt;script type=&#8221;module&#8221;>\u3063\u3066\u306e\u306b\u306f\u6c17\u3092\u3064\u3051\u306a\u3044\u3068\u6050\u308d\u3057\u3044\u6cbc\u306b\u306f\u307e\u308b\u3002\u3042\u3068config\u306b\u95a2\u3057\u3066\u306f\u74b0\u5883\u3054\u3068\u306b\u3053\u3068\u306a\u308b\u306e\u3067\u8abf\u3079\u3066\u8a2d\u5b9a\u304c\u5fc5\u8981\u3002signInSuccessURL\u3068\u3044\u3046\u306e\u304c\u3001\u6b21\u306eBridge\u3068\u3044\u3046View\u306b\u98db\u3070\u3057\u3066\u3044\u308b\u90e8\u5206\u306b\u306a\u308b\u3002<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&#91;teemplates\/portal.html]\n{% load static %}\n&lt;!DOCTYPE html>\n&lt;html lang=\"en\" dir=\"ltr\">\n  &lt;head>\n    &lt;meta charset=\"utf-8\">\n    &lt;script src=\"https:\/\/www.gstatic.com\/firebasejs\/9.11.0\/firebase-app-compat.js\">&lt;\/script>\n    &lt;script src=\"https:\/\/www.gstatic.com\/firebasejs\/9.11.0\/firebase-auth-compat.js\">&lt;\/script>\n    &lt;script type=\"text\/javascript\">\n      var config = {\n        apiKey: \"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\",\n        authDomain: \"xxxxxxxxxxxx.firebaseapp.com\",\n        projectId: \"xxxxxxxxxxxxxxxx\",\n        storageBucket: \"xxxxxxxxxxxx.firebaseapp.com\",\n        messagingSenderId: \"333333333333333\",\n        appId: \"9:9999999999999:web:01234567890123456\",\n      };\n      firebase.initializeApp(config);\n    &lt;\/script>\n    &lt;script src=\"https:\/\/www.gstatic.com\/firebasejs\/ui\/3.1.1\/firebase-ui-auth__{{request.LANGUAGE_CODE}}.js\">&lt;\/script>\n    &lt;link type=\"text\/css\" rel=\"stylesheet\" href=\"https:\/\/www.gstatic.com\/firebasejs\/ui\/3.1.1\/firebase-ui-auth.css\" \/>\n    &lt;title>SimpleCircle Logon&lt;\/title>\n  &lt;\/head>\n  &lt;body>\n\n    &lt;h1>Simple Circle Service&lt;\/h1>\n\n    &lt;div id=\"firebaseui-auth-container\">&lt;\/div>\n    &lt;div id=\"loader\">Loading...&lt;\/div>\n\n    &lt;script type=\"text\/javascript\">\n\n      var uiConfig = {\n        callbacks: {\n          signInSuccessWithAuthResult: function(authResult, redirectUrl) {\n            return true;\n          },\n          uiShown: function() {\n            document.getElementById('loader').style.display = 'none';\n          }\n        },\n        signInFlow: 'redirect',\n        signInSuccessUrl: 'http:\/\/localhost:8000\/app\/bridge',\n        signInOptions: &#91;\n          firebase.auth.EmailAuthProvider.PROVIDER_ID,\n          firebase.auth.GoogleAuthProvider.PROVIDER_ID,\n          firebase.auth.TwitterAuthProvider.PROVIDER_ID,\n        ],\n\n        tosUrl: 'http:\/\/localhost:8000\/app\/term_of_service',\n        \/\/ Privacy policy url\/callback.\n        privacyPolicyUrl: 'http:\/\/localhost:8000\/app\/privacy_policy',\n\n      };\n\n      var ui = new firebaseui.auth.AuthUI(firebase.auth());\n      ui.start('#firebaseui-auth-container', uiConfig);\n    &lt;\/script>\n  &lt;\/body>\n  &lt;\/body>\n&lt;\/html><\/code><\/pre>\n\n\n\n<p>\u3053\u308c\u3067\u4ee5\u4e0b\u304c\uff08\u305f\u3076\u3093\uff09\u8868\u793a\u3055\u308c\u308b\u3002<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"643\" height=\"362\" src=\"http:\/\/192.168.0.16:3005\/wp-content\/uploads\/2022\/10\/image-20.png\" alt=\"\" class=\"wp-image-254\" srcset=\"https:\/\/blog.solong.jp\/wp-content\/uploads\/2022\/10\/image-20.png 643w, https:\/\/blog.solong.jp\/wp-content\/uploads\/2022\/10\/image-20-300x169.png 300w\" sizes=\"auto, (max-width: 643px) 100vw, 643px\" \/><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">Bridge<\/h3>\n\n\n\n<p>\u3053\u3063\u3061\u3082Django\u306eView\u306f\u5168\u304f\u540c\u3058\u3002<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>def bridge(request):\n\n    if(request.user.is_authenticated):\n        return redirect('app:circle_board')\n\n    return render(request, 'bridge.html')<\/code><\/pre>\n\n\n\n<p>\u554f\u984c\u306fHTML\u3068Javascript\u3067\u305d\u3053\u305d\u3053\u306e\u3084\u3084\u3053\u3057\u3044\u3002\u3053\u306eHTML\u306f\u767d\u7d19\u306e\u30da\u30fc\u30b8\u3057\u304b\u898b\u3048\u306a\u304f\u306a\u3063\u3066\u3044\u308b\u3002<br>Firebase\u306eonAuthStatusChanged\u3063\u3066\u3044\u3046\u306e\u304c\u3001Firebase Auth\u306e\u30d6\u30e9\u30a6\u30b6\u306e\u30ed\u30b0\u30aa\u30f3\u60c5\u5831\u304c\u5909\u66f4\u3055\u308c\u305f\u3068\u304d\u306b\u30c8\u30ea\u30ac\u3055\u308c\u308b\u3082\u306e\u3063\u3066\u3044\u3046\u8aac\u660e\u306b\u306a\u3063\u3066\u3044\u308b\u306e\u3060\u3051\u3069\u3001\u3069\u3046\u3084\u3089\u30da\u30fc\u30b8\u304c\u30ed\u30fc\u30c9\u3055\u308c\u305f\u3089\u3059\u3050\u78ba\u8a8d\u306b\u884c\u304f\u3088\u3046\u306a\u306e\u3067Portal\u304b\u3089\u98db\u3070\u3055\u308c\u3066\u304d\u305f\u3068\u304d\u306b\u8d77\u52d5\u3059\u308b\u3088\u3046\u3002<\/p>\n\n\n\n<p>\u305d\u306e\u6642\u70b9\u3067Firebase\u7684\u306b\u30ed\u30b0\u30aa\u30f3\u3067\u304d\u3066\u306a\u3044\u5834\u5408\u3001Portal\u306b\u8fd4\u3059\u3002<br>\u30ed\u30b0\u30aa\u30f3\u3067\u304d\u3066\u3044\u308b\u5834\u5408\u306f\u5f8c\u3067\u89e3\u8aac\u3059\u308b\u300ctrytoken\u300d\u3068\u3044\u3046Django\u5074\u3067\u81ea\u4f5c\u3059\u308bAPI\u306b\u3001Firebase\u304b\u3089user.getIdToken()\u3067\u53d7\u3051\u53d6\u3063\u305f\u30c8\u30fc\u30af\u30f3\u3092\u9001\u3063\u3066\u3001Django\u5074\u3001\u3064\u307e\u308a\u30b5\u30fc\u30d0\u30b5\u30a4\u30c9\u3067\u3082Firebase\u306b\u30c8\u30fc\u30af\u30f3\u3092\u9001\u3063\u3066\u771f\u8d0b\u5224\u5b9a\u3092\u884c\u3063\u3066\u3044\u308b\u3002JSON.stringify\u3060\u3051\u3060\u3068\u3001\u306a\u305c\u304b\u30c8\u30fc\u30af\u30f3\u304c&#8221;xxxxxx&#8221;\u3063\u3066\u30c0\u30d6\u30eb\u30af\u30a9\u30fc\u30c6\u30fc\u30b7\u30e7\u30f3\u3067\u56f2\u308f\u308c\u305f\u307e\u307e\u306b\u306a\u3063\u3066\u3048\u30fc\u3063\u3066\u601d\u3063\u305f\u3051\u3069\u3001\u30cd\u30c3\u30c8\u3067\u8abf\u3079\u3066\u3082\u3088\u304f\u308f\u304b\u3089\u305a\u3001\u52d8\u3067eval\u3057\u3066\u3084\u3063\u305f\u3089\u306a\u3093\u304b\u3046\u307e\u304f\u884c\u3063\u305f\u3002<br>\u305d\u3057\u3066Jquery\u306e$.post\u3067API\u3092\u691c\u8a3c\u3055\u305b\u3066\u3044\u308b\u3002<br>API\u304c\u8fd4\u3057\u3066\u304d\u305f\u7d50\u679c\u306b\u3088\u308a<br>\u3000Firebase\u306eToken\u304c\u901a\u3089\u306a\u304b\u3063\u305f \u2192 Portal\u3078\u30ea\u30c0\u30a4\u30ec\u30af\u30c8<br>\u3000Token\u304c\u901a\u308a\u3001\u30e6\u30fc\u30b6ID\u3067\u7167\u5408\u3057\u305f\u3089Django\u30a2\u30d7\u30ea\u3068\u3057\u3066\u3082\u767b\u9332\u6e08\u307f\u306e\u30e6\u30fc\u30b6\u3060\u3063\u305f \u2192 \u30ed\u30b0\u30aa\u30f3\u51e6\u7406\u306fAPI\u5074\u3067\u7d42\u308f\u3089\u305b\u3066\u3042\u3052\u3066\u3044\u308b\u306e\u3067\u3001\u30a2\u30d7\u30ea\u306e\u30c8\u30c3\u30d7\u30da\u30fc\u30b8\u306b\u30ea\u30c0\u30a4\u30ec\u30af\u30c8\u3059\u308b\u3002<br>\u3000Token\u304c\u901a\u3063\u305f\u304c\u3001\u304a\u521d\u306e\u8a8d\u8a3c\u306e\u4eba\u306e\u5834\u5408\u3001Google\u3084Twitter\u8a8d\u8a3c\u306e\u5834\u5408\u306f\u4e00\u6c17\u306b\u30a2\u30d7\u30ea\u5074\u306e\u30e6\u30fc\u30b6\u767b\u9332\u3082API\u3067\u7d42\u308f\u3063\u3066\u3044\u308b\u306e\u3067\u3001\u30a2\u30d7\u30ea\u306e\u30c8\u30c3\u30d7\u30da\u30fc\u30b8\u306b\u8fce\u3048\u5165\u308c\u308b\u3002<br>\u3000Token\u304c\u901a\u3063\u3066\u304a\u521d\u306e\u4eba\u3001\u307e\u305f\u306f\u30e1\u30fc\u30eb\/\u30d1\u30b9\u30ef\u30fc\u30c9\u8a8d\u8a3c\u3067\u30e1\u30fc\u30eb\u30a2\u30c9\u30ec\u30b9\u306e\u691c\u8a3c\u304c\u7d42\u308f\u3063\u3066\u3044\u306a\u3044\u4eba\u306e\u5834\u5408\u306b\u306f\u30ea\u30f3\u30af\u4ed8\u304d\u306e\u30e1\u30fc\u30eb\u3092\u9001\u3063\u3066\u305d\u306e\u30ea\u30f3\u30af\u3092\u5206\u3067\u3082\u3089\u3063\u3066\u521d\u3081\u3066\u304a\u8fce\u3048\u3059\u308b\u3053\u3068\u306b\u3059\u308b\u306e\u3067&lt;div id=&#8221;email_verify&#8221;>\u306e\u90e8\u5206\u3092\u8868\u793a\u3055\u305b\u3066\u30e1\u30fc\u30eb\u30dc\u30c3\u30af\u30b9\u3092\u898b\u308b\u3088\u3046\u306b\u8a98\u5c0e\u3057\u3066\u3044\u308b\u3002<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>{% load static %}\n&lt;!DOCTYPE html>\n&lt;html lang=\"en\" dir=\"ltr\">\n  &lt;head>\n    &lt;meta charset=\"utf-8\">\n    &lt;script src=\"https:\/\/www.gstatic.com\/firebasejs\/9.11.0\/firebase-app-compat.js\">&lt;\/script>\n    &lt;script src=\"https:\/\/www.gstatic.com\/firebasejs\/9.11.0\/firebase-auth-compat.js\">&lt;\/script>\n    &lt;script type=\"text\/javascript\">\n      var config = {\n        apiKey: \"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\",\n        authDomain: \"xxxxxxxxxxxx.firebaseapp.com\",\n        projectId: \"xxxxxxxxxxxxxxxx\",\n        storageBucket: \"xxxxxxxxxxxx.firebaseapp.com\",\n        messagingSenderId: \"333333333333333\",\n        appId: \"9:9999999999999:web:01234567890123456\",\n      };\n      firebase.initializeApp(config);\n    &lt;\/script>\n    &lt;script type=\"text\/javascript\" src=\"{% static 'js\/jquery\/jquery.min.js' %}\">&lt;\/script>\n    &lt;title>SimpleCircle Logon&lt;\/title>\n  &lt;\/head>\n  &lt;body>\n\n    &lt;div id=\"email_verify\" class=\"email_verify\" style=\"display: none;\">\n      &lt;p>Email Verification mail is sent to your address.&lt;\/p>\n      &lt;p>Please confirm it and follow the link. you can close this window.&lt;\/p>\n    &lt;\/div>\n    &lt;script type=\"text\/javascript\">\n\n      firebase.auth().onAuthStateChanged(user => {\n        console.log(user.displayName)\n        if (user == null){\n          window.location.href = \"{% url 'app:portal' %}\";\n        } else {\n\n            user.getIdToken(true).then((data) => {\n\n              var token = eval(JSON.stringify(data));\n\n              $.post({\n                  url: \"{% url 'app:trytoken' %}\",\n                  data: {\n                    'token': token,\n                    'csrfmiddlewaretoken' : '{{ csrf_token }}'\n                  },\n                  dataType: 'json',\n                  success: function(rjson){\n                    console.log(rjson.vertoken);\n                    if (rjson.vertoken == false) {\n                      window.location.href = \"{% url 'app:portal' %}\";\n                    }else if(rjson.dloggedin == true){\n                      console.log('logged on to django, redirect.');\n                      window.location.href = \"{% url 'app:circle_board' %}\";\n                    }else {\n                      if(rjson.emailvalid == false){\n                        console.log('email has not verified yet.');\n                        document.getElementById('email_verify').style.display = 'block';\n                        var uri = new URL(window.location.href);\n                        var actionCodeSettings = {\n                          url: uri.origin + \"{% url 'app:bridge' %}\",\n                          handleCodeInApp: false\n                        };\n\n                        firebase.auth().currentUser.sendEmailVerification(actionCodeSettings);\n                      }\n                    }\n                  },\n                  error: function(){\n                    alert('Server Error');\n                  }\n\n              });\n          });\n        }\n      });\n    &lt;\/script>\n  &lt;\/body>\n  &lt;\/body>\n&lt;\/html>\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">trytoken API<\/h3>\n\n\n\n<p>\u3053\u308c\u306fAjax\u3067Firebase\u306e\u30c8\u30fc\u30af\u30f3\u3092\u691c\u8a3c\u3059\u308b\u3001Bridge\u304b\u3089\u547c\u3093\u3067\u3044\u305f\u3082\u306e\u3002HTML\u306eTemplate\u306f\u3044\u3089\u306a\u304f\u3066Django\u306eapp\/views.py\u3060\u3051\u3092\u4f5c\u3063\u3066\u3084\u308c\u3070\u3088\u3044\u3002<br>\u307e\u305aPOST\u3067&#8221;token&#8221;\u3068\u3044\u3046\u30ad\u30fc\u304c\u4f55\u304b\u3057\u3089\u6765\u3066\u3044\u306a\u3051\u308c\u3070\u5f53\u7136\u30a8\u30e9\u30fc\u3002<br>firebase_admin\u3068\u3044\u3046\u30d1\u30c3\u30b1\u30fc\u30b8\u306fpip\u3067\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3057\u3066import\u3057\u3066\u304a\u3044\u3066\u3084\u308b\u5fc5\u8981\u304c\u3042\u308b\u3002\u305d\u3057\u3066initialize_app\u3057\u3066\u3042\u3052\u308b\u306e\u3060\u304c\u3001\u306a\u305c\u304bif not\u3067\u3059\u3067\u306binitialize\u304c\u7d42\u308f\u3063\u3066\u306a\u3044\u304b\u5224\u5b9a\u5f8c\u306b\u3057\u3066\u3042\u3052\u306a\u3044\u3068\u30a8\u30e9\u30fc\u304c\u51fa\u308b\u3002\u3053\u3053\u306e\u7406\u5c48\u306f\u308f\u304b\u3089\u306a\u3044\u3051\u3069\u3068\u308a\u3042\u3048\u305a\u3053\u3046\u3057\u305f\u3089\u7121\u96e3\u306b\u52d5\u3044\u305f\u3002json\u3067\u5225\u9014Firebase\u306e\u30b3\u30f3\u30bd\u30fc\u30eb\u3067\u4f5c\u308b\uff08\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u306e\u8a2d\u5b9a\u2192\u30a2\u30ab\u30a6\u30f3\u30c8\u2192\u79d8\u5bc6\u9375\u306e\u751f\u6210\uff09Service Account Key\u306a\u308b\u3082\u306e\u3092\u3092\u98df\u308f\u305b\u308b\u3002<br>\u3067\u3001auth.verify_id_token\u3068\u3044\u3046\u3053\u3068\u3092\u3057\u3066\u3042\u3052\u308b\u3068\u88cf\u3067firebase\u306b\u691c\u8a3c\u3092\u304b\u3051\u306b\u884c\u3063\u3066\u304f\u308c\u3066\u3053\u306e\u8fba\u306f\u7c21\u5358\u3002firebase\u4e0a\u3067\u6301\u3063\u3066\u3044\u308buid\u3092\u8fd4\u3057\u3066\u304f\u308b\u306e\u3067\u3053\u308c\u3092Django\u306eusername\u3068\u3057\u3066\u4f7f\u3046\u3002User\u30e2\u30c7\u30eb\u304c\u53d6\u5f97\u3067\u304d\u308c\u3070django.contrib.auth\u306elogin(request, user)\u3068\u3044\u3046\u306e\u3092\u547c\u3093\u3067\u3084\u308c\u3070Django\u5074\u3067\u306e\u30ed\u30b0\u30a4\u30f3\u51e6\u7406\u304c\u3067\u304d\u3066\u3057\u307e\u3046\u306e\u3067\u3001\u305d\u308c\u3092Bridge\u306eJavascript\u3078\u8fd4\u3057\u3066\u3042\u3052\u308c\u3070\u30ea\u30c0\u30a4\u30ec\u30af\u30c8\u3067\u30a2\u30d7\u30ea\u5185\u306b\u304a\u8fce\u3048\u304c\u3067\u304d\u308b\u3002<br>Firebase\u306e\u30c8\u30fc\u30af\u30f3\u691c\u8a3c\u3067\u306f\u3001Email\u8a8d\u8a3c\u304c\u7d42\u308f\u3063\u3066\u3044\u308b\u304b\u3069\u3046\u304b\u3092&#8217;email_verified&#8217;\u3068\u3044\u3046\u9805\u76ee\u3067\u8fd4\u3057\u3066\u304f\u308c\u3066\u3044\u308b\u306e\u3067\u3001\u30e1\u30fc\u30eb\u8a8d\u8a3c\u304c\u7d42\u308f\u3063\u3066\u3044\u306a\u3051\u308c\u3070\u3001Bridge\u306e\u753b\u9762\u3067\u8a8d\u8a3c\u3092\u4fc3\u3059\uff08\u524d\u8ff0\uff09\u3002<br>Google\u3084Twitter\u8a8d\u8a3c\u306e\u4eba\u306f\u3053\u3053\u306f\u5fc5\u305aTrue\u3060\u3063\u305f\u308a\u3059\u308b\u306e\u3067\u3001\u30e1\u30fc\u30eb\u8a8d\u8a3c\u304c\u7d42\u308f\u3063\u3066\u3044\u308b\u4eba\u3082\u542b\u3081\u3066\u3001\u3053\u3053\u307e\u3067\u304d\u305f\u3089Django\u30a2\u30d7\u30ea\u306bUser\u3092\u767b\u9332\u3057\u3066\u3042\u3052\u3066\u3001\u30d1\u30b9\u30ef\u30fc\u30c9\u306f\u7121\u52b9\u306a\u3082\u306e\u3068\u3057\uff08set_unusable_password\uff09\u3001\u30ed\u30b0\u30aa\u30f3\u3055\u305b\u3066\u3042\u3052\u3066\u30c7\u30d5\u30a9\u30eb\u30c8\u306e\u30b5\u30fc\u30af\u30eb\u30dc\u30fc\u30c9\u3082\u4f5c\u3063\u3066\u3042\u3052\u3066\u8fce\u3048\u5165\u308c\u308b\u3002<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&#91;app\/views.py]\nfrom django.contrib.auth import login\nfrom django.contrib.auth.models import User\nimport firebase_admin\nfrom firebase_admin import credentials, auth\n\ndef trytoken(request):\n\n    id_token = request.POST.get('token')\n    if(id_token is None):\n        return JsonResponse({\n            'dloggedin':False,'emailvalid':False,\n            'vertoken':False,'message':str(e)\n        })\n\n    if not firebase_admin._apps:\n        cred = credentials.Certificate(\n            os.path.join('\/xxxx\/xxxxxx\/sak.json'))\n        firebase_admin.initialize_app(cred)\n\n    try:\n        decoded_token = auth.verify_id_token(id_token)\n    except Exception as e:\n        return JsonResponse({\n            'dloggedin':False,'emailvalid':False,\n            'vertoken':False,'message':str(e)\n        })\n\n    uid = decoded_token&#91;\"uid\"]\n\n    user = User.objects.filter(last_name=uid).first()\n\n    if(user is not None):\n        login(request, user)\n        return JsonResponse({\n            'dloggedin':True,'emailvalid':True,\n            'error':False\n        })\n\n    if(decoded_token&#91;'firebase']&#91;'sign_in_provider'] == 'password'):\n        if(decoded_token&#91;'email_verified'] == False):\n            return JsonResponse({\n                'dloggedin':False,'emailvalid':False,\n                'vertoken':True\n            })\n\n    # Email is verified so create user\n    user = User.objects.create_user(\n        username = decoded_token.get('user_id'),\n        email = decoded_token.get('email'),\n        first_name = decoded_token&#91;'name'],\n        last_name = decoded_token&#91;'uid']\n    )\n    user.set_unusable_password()\n    user.save()\n\n    login(request, user)\n\n    circle = Circle(\n        name = 'Personal Board of ' + user.first_name\n    )\n    circle.save()\n\n    j = Joining(\n        user = user,\n        circle = circle\n    )\n    j.save()\n\n    return JsonResponse({\n        'dloggedin':True,'emailvalid':True,\n        'vertoken':True\n    })<\/code><\/pre>\n\n\n\n<p>\u809d\u306e\u90e8\u5206\u306f\u3053\u3053\u307e\u3067\u3067\u307b\u3068\u3093\u3069OK\u3002<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">django\u306esettings.py<\/h3>\n\n\n\n<p>Django\u306esettings.py\u3092\u5c11\u3057\u5909\u3048\u308b\u5fc5\u8981\u304c\u3042\u308b\u3002<br>LocaleMiddleWare\u306f\u3001Portal\u3067firebase authui\u306b\u8a00\u8a9e\u3092\u6559\u3048\u3066\u4e0a\u3052\u308b\u305f\u3081\u306b\u8ffd\u52a0\u3057\u305f\u3002<br>LOGOUT_REDIRECT_URL\u306f\u3001logout_firebase\u3068\u3044\u3046\u753b\u9762\u306b\u4e00\u5ea6\u98db\u3070\u3057\u3066\u4e0a\u3052\u3066\u3001Firebase\u3068\u30d6\u30e9\u30a6\u30b6\u306e\u95a2\u4fc2\u3082\u3061\u3087\u3093\u5207\u3063\u3066\u4e0a\u3052\u308b\u305f\u3081\u306b\u3002\u3042\u3068\u306fGlobalLoginRequiredMiddleware\u306b\u6559\u3048\u3066\u3042\u3052\u308b\u305f\u3081\u306e\u8a8d\u8a3c\u3092\u5fc5\u8981\u3068\u3057\u306a\u3044\u30d1\u30b9\u3092PUBLIC_PATH\u3068\u3057\u3066\u8a2d\u5b9a\u3057\u3066\u3084\u308b\u3002<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>MIDDLEWARE = &#91;\n    ......\n    'django.middleware.locale.LocaleMiddleware',\n    ......\n]\n\nLOGIN_REDIRECT_URL = '\/app\/circle_board'\nLOGOUT_REDIRECT_URL = '\/app\/logout_firebase'\n\nPUBLIC_PATHS = &#91;\n    '\/app\/portal',\n    '\/app\/bridge',\n    '\/app\/trytoken',\n    '\/app\/logout_firebase',\n]<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">logout_firebase<\/h3>\n\n\n\n<p>view\u306f\u3053\u308c\u3060\u3051\u3067\u3044\u3044\u3002<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>def logout_firebase(request):\n    return render(request, 'logout_firebase.html')<\/code><\/pre>\n\n\n\n<p>HTML\u5074\u3067\u3001\u30d6\u30e9\u30a6\u30b6\u3068Firebase\u306e\u30ed\u30b0\u30aa\u30f3\u72b6\u614b\u3092\u5207\u3063\u3066\u304b\u3089\u3001Portal\u306b\u30ea\u30c0\u30a4\u30ec\u30af\u30c8\u3057\u3066\u3084\u308b\u3002<br>\u306a\u305c\u304b\u3053\u308c\u3060\u3051Module\u3067\u3084\u3063\u3066\u308b\u306e\u3067\u5f8c\u3067\u66f8\u304d\u76f4\u3059\u3002window.xxxx = function () => { };\u307f\u305f\u3044\u306a\u3053\u3068\u3092\u3084\u3063\u3066\u30b0\u30ed\u30fc\u30d0\u30eb\u306b\u547c\u3079\u308b\u95a2\u6570\u3092\u4f5c\u3063\u3066\u3042\u3052\u305f\u308a\u3057\u306a\u3044\u3068\u3044\u3051\u306a\u304f\u3066\u3001\u3053\u308c\u307b\u3093\u3068\u3069\u3046\u304b\u3057\u3066\u3044\u308b\u3088\u306a\u30fb\u30fb\u30fb\u3002<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>{% load static %}\n&lt;!DOCTYPE html>\n&lt;html lang=\"en\" dir=\"ltr\">\n  &lt;head>\n    &lt;meta charset=\"utf-8\">\n    &lt;script type=\"text\/javascript\" src=\"{% static 'js\/jquery\/jquery.min.js' %}\">&lt;\/script>\n    &lt;title>Logout also from Firebase&lt;\/title>\n  &lt;\/head>\n  &lt;body>\n\n    &lt;h1>Simple Circle Service&lt;\/h1>\n\n    &lt;input type='hidden' value=\"\" name=\"status\" id=\"status\" \/>\n\n    &lt;p id=\"exit\" style=\"visibility: hidden;\">&lt;a href=\"{% url 'app:portal' %}\">Back to Logon Screen.&lt;\/a>&lt;\/p>\n\n    &lt;script type=\"text\/javascript\">\n      setInterval(nnn,1000);\n      function nnn(){\n        logon_check();\n        if($('#status').val() == 'logout'){\n            $(\"#exit\").css('visibility','visible');\n        }\n      }\n    &lt;\/script>\n\n    &lt;script type=\"module\">\n      import { initializeApp } from 'https:\/\/www.gstatic.com\/firebasejs\/9.10.0\/firebase-app.js'\n      import { getAnalytics } from 'https:\/\/www.gstatic.com\/firebasejs\/9.10.0\/firebase-analytics.js'\n      import { getAuth, signInWithEmailAndPassword, signOut, signInWithRedirect,\n        onAuthStateChanged, GoogleAuthProvider, getRedirectResult }\n       from 'https:\/\/www.gstatic.com\/firebasejs\/9.10.0\/firebase-auth.js'\n      import { getFirestore } from 'https:\/\/www.gstatic.com\/firebasejs\/9.10.0\/firebase-firestore.js'\n\n      const firebaseConfig = {\n        apiKey: \"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\",\n        authDomain: \"xxxxxxxxxxxx.firebaseapp.com\",\n        projectId: \"xxxxxxxxxxxxxxxx\",\n        storageBucket: \"xxxxxxxxxxxx.firebaseapp.com\",\n        messagingSenderId: \"333333333333333\",\n        appId: \"9:9999999999999:web:01234567890123456\",\n      };\n\n      \/\/ Initialize Firebase\n      const app = initializeApp(firebaseConfig);\n      const auth = getAuth(app);\n \n      window.logon_check = () => {\n        console.log(auth.currentUser);\n      }\n\n      signOut(auth).then(() => {\n        \/\/ Sign-out successful.\n        console.log(\"Logout Successful.\")\n        window.document.getElementById(\"status\").value = \"logout\";\n      }).catch((error) => {\n        \/\/ An error happened.\n      });\n\n    &lt;\/script>\n  &lt;\/body>\n&lt;\/html>\n<\/code><\/pre>\n\n\n\n<p>\u4ee5\u4e0a\u3067\u3001Firebase\u3092\u4f7f\u3063\u305fDjango\u30a2\u30d7\u30ea\u3078\u306e\u30ed\u30b0\u30aa\u30f3\u306e\u4ed5\u7d44\u307f\u304c\u3067\u304d\u305f\u3002\u9577\u3044\u9053\u306e\u308a\u3060\u3063\u305f\u3002\u4eca\u5f8c\u306a\u306b\u304b\u516c\u958b\u30b5\u30fc\u30d3\u30b9\u30a2\u30d7\u30ea\u3092\u4f5c\u308b\u305e\u3068\u601d\u3063\u305f\u3089\u3053\u308c\u3067\u5927\u4f53\u3084\u308c\u305d\u3046\u3067\u5b09\u3057\u3044\u3002<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Django\u3067\u306e\u958b\u767a\u306e\u52c9\u5f37\u3068\u3057\u3066\u3001\u7df4\u7fd2\u7528\u306b\u4ee5\u4e0b\u306e\u3088\u3046\u306a\u30b5\u30f3\u30d7\u30eb\u30a2\u30d7\u30ea\u3092\u4f5c\u308b\u3002 \u6975\u529b\u3084\u3084\u3053\u3057\u3044\u3053\u3068\u306f\u305b\u305a\u3001Google\u3001Twitter\u3001Facebook\u7b49\u3067\u30e6\u30fc\u30b6\u767b\u9332\u3084\u8a8d\u8a3c(\u30ed\u30b0\u30a4\u30f3)\u304c\u3067\u304d\u308b\u3002 \u300c\u30b5\u30fc\u30af\u30eb\u300d\u3068\u3044\u3046\u30e6\u30fc\u30b6\u304c\u96c6\u307e\u308b\u5358\u4f4d\u304c\u3042\u308a\u3001\u30e6\u30fc\u30b6\u306f\u8907\u6570\u306e\u30b5\u30fc\u30af\u30eb\u306b\u6240\u5c5e\u3059\u308b\u3002 \u3042\u3089\u3086\u308b\u30e6\u30fc\u30b6\u306f\u65b0\u3057\u3044\u30b5\u30fc\u30af\u30eb\u3092\u4f5c\u6210\u3067\u304d\u308b\u3002 \u30b5\u30fc\u30af\u30eb\u3078\u306e\u53c2\u52a0\u306f\u3001\u305d\u306e\u30b5\u30fc\u30af\u30eb\u306b\u3059\u3067\u306b\u53c2\u52a0\u3057\u3066\u3044\u308b\u30e1\u30f3\u30d0\u30fc\u306e\u62db\u5f85\u306b\u3088\u308a\u53ef\u80fd\u3068\u306a\u308b\u3002 \u30b5\u30fc\u30af\u30eb\u3054\u3068\u306b\u306f\u3001\u7c21\u5358\u306a\u30e1\u30c3\u30bb\u30fc\u30b8\u30dc\u30fc\u30c9\u304c\u3042\u3063\u3066\u30e1\u30c3\u30bb\u30fc\u30b8\u3092\u3084\u308a\u53d6\u308a\u3067\u304d\u308b\u3002 \u6280\u8853\u7684\u306a\u5236\u7d04\u3068\u3057\u3066\u306f\u4ee5\u4e0b\u3068\u3059\u308b\u3002 \u30d5\u30ed\u30f3\u30c8\u30a8\u30f3\u30c9\u958b\u767a\u306f\u306a\u3057\u3002React\u3084Angular\u306a\u3093\u304b\u306e\u30d5\u30ec\u30fc\u30e0\u30ef\u30fc\u30af\u4f7f\u308f\u306a\u3044\u3057\u3001Javascript\u3082\u6700\u4f4e\u9650\u306b\u3059\u308b\u3002\u753b\u9762\u9077\u79fb\u306fDjango\u306e\u57fa\u672c\u7684\u306a\u4f7f\u3044\u65b9\u3067\u3001Template\u306eHTML\u3092\u4f7f\u3046\u3002 \u4ee5\u964d\u306e\u624b\u9806\u306e\u8aac\u660e\u306b\u304a\u3044\u3066\u3001\u89e3\u8aac\u306f\u30dd\u30a4\u30f3\u30c8\u3060\u3051\u3068\u3057\u3066Django\u306e\u5b66\u7fd2\u30ec\u30d9\u30eb\u306e\u8aac\u660e\u306f\u3057\u306a\u3044\u3002 \u30c6\u30b9\u30c8\u7528\u306e\u30a2\u30d7\u30ea\u3092\u7528\u610f\u3057\u3066\u52d5\u304b\u3059 \u307e\u305a\u306fDjango\u3092\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3057\u3066StartApp\u307e\u3067\u884c\u304f\u3002 \u3055\u3066\u3001Settings\u306e\u65b9\u306f\u3053\u3053\u3060\u3051\u3044\u3058\u308b\u3002 \u307e\u305a\u306fModel\u3092\u4f5c\u3063\u3066\u3057\u307e\u3046\u3002Circle\u3068\u3044\u3046\u306e\u304c\u3053\u306e\u30a2\u30d7\u30ea\u306e\u4eba\u304c\u96c6\u307e\u3063\u3066\u3044\u308b\u30b5\u30fc\u30af\u30eb\u306e\u30de\u30b9\u30bf\u306b\u306a\u308b\u3002\u5c5e\u6027\u306f\u540d\u524d\u3060\u3051\u3002Joining\u3068\u3044\u3046\u306e\u304cManyToMany\u7684\u306aCircle\u3068\u30e6\u30fc\u30b6\u306e\u7d10\u4ed8\u3051\u30c6\u30fc\u30d6\u30eb\u3002\u6700\u521d\u306f\u4f7f\u308f\u306a\u3044\u3051\u3069\u3082\u3001\u30b5\u30fc\u30af\u30eb\u3078\u306e\u62db\u5f85\u3092\u3059\u308b\u3053\u3068\u306b\u306a\u308b\u306e\u3067\u305d\u306e\u62db\u5f85\u30c1\u30b1\u30c3\u30c8\u306e\u30c6\u30fc\u30d6\u30eb\u3082\u4f5c\u308a\u3001\u3042\u3068\u306f\u30e1\u30c3\u30bb\u30fc\u30b8\u30dc\u30fc\u30c9\u7684\u306a\u3068\u3053\u308d\u306b\u6d41\u308c\u308b\u30e1\u30c3\u30bb\u30fc\u30b8\u3068\u3057\u305f\u3002 Model\u304c\u6e80\u8db3\u884c\u304f\u51fa\u6765\u306b\u306a\u3063\u305f\u3089\u3082\u3061\u308d\u3093\u3053\u308c\u3002 \u6b21\u306burl\u95a2\u4fc2\u3092\u3002Django\u306e\u4ed8\u5c5e\u306e\u7ba1\u7406\u753b\u9762(admin)\u3082\u4e00\u65e6\u6709\u52b9\u306b\u3059\u308b\u3002\u3053\u306e\u307e\u307e\u3060\u3068\u516c\u958b\u306f\u3067\u304d\u306a\u3044\u3088\u3046\u306a\u6c17\u3082\u3059\u308b\u3051\u3069\u8a2d\u5b9a\u3092\u9593\u9055\u3048\u306a\u3051\u308c\u3070\u554f\u984c\u306a\u3044\u3088\u3046\u306a\u6c17\u3082\u3059\u308b\u3002accounts\u306b\u95a2\u3057\u3066\u306f\u30ed\u30b0\u30a4\u30f3\u8a8d\u8a3c\u95a2\u4fc2\u3092\u3084\u3063\u3066\u304f\u308c\u308b\u306e\u3067\u3044\u3063\u305f\u3093\u5165\u308c\u308b\u304c\u3001\u30ed\u30b0\u30a4\u30f3\u753b\u9762\u3092\u7528\u610f\u3059\u308b\u304f\u3089\u3044\u306b\u3057\u304b\u4f7f\u308f\u306a\u3044\u3002\u30a2\u30d7\u30ea\u5074\u306e\u753b\u9762\u306f1\u753b\u9762\u3060\u3051\u3002\u30b5\u30fc\u30af\u30eb\u306e\u4f1d\u8a00\u8868\u793a\uff06\u6295\u7a3f\u753b\u9762\u3060\u3051\u3068\u3059\u308b\u3002\u30e6\u30fc\u30b6\u304c\u8907\u6570\u306e\u30b5\u30fc\u30af\u30eb\u306b\u53c2\u52a0\u3057\u3066\u3044\u308b\u5834\u5408\u306f\u30b5\u30fc\u30af\u30eb\u306e\u5207\u308a\u66ff\u3048\u304c\u5fc5\u8981\u306a\u306e\u3067\u3001\u305d\u306e\u305f\u3081\u306eView\u3092\u4e00\u3064\u7528\u610f\u3057\u3066\u3044\u308b\u3002 Admin\u753b\u9762\u304b\u3089\u30c6\u30b9\u30c8\u30c7\u30fc\u30bf\u3092\u767b\u9332\u3057\u3066\u307f\u305f\u3044\u306e\u3067 \u3053\u306e\u8fba\u307e\u3067\u6765\u305f\u3089\u30b9\u30fc\u30d1\u30fc\u30e6\u30fc\u30b6\u3092\u3072\u3068\u308a\u3001Mike\u304f\u3093\u3068\u3044\u3046\u306e\u3092\u4f5c\u3063\u3066\u304b\u3089\u3001 Django \u306e\u4eee\u30b5\u30fc\u30d0\u3092\u4e0a\u3052\u3066\u898b\u308b\u3002 Admin\u753b\u9762(http:\/\/localhost:8000\/admin\/)\u306b\u5165\u3063\u3066\u307f\u3066\u3001\u30c6\u30b9\u30c8\u30c7\u30fc\u30bf\u3092\u767b\u9332\u3057\u3066\u307f\u308b\u3002\u307e\u305a\u306f\u30ae\u30bf\u30fc\u7df4\u7fd2\u3068\u7b4b\u30c8\u30ec\u3068\u9aa8\u8463\u30ab\u30e1\u30e9\u3068\u3044\u30463\u3064\u306e\u30b5\u30fc\u30af\u30eb\u3092\u767b\u9332\u3057\u305f\u3002 \u6b21\u306bMike\u304f\u3093\u4ee5\u5916\u306b\u3082Kevin\u3068Anna\u3092\u767b\u9332\u3002 3\u4eba\u30683\u3064\u306e\u30b5\u30fc\u30af\u30eb\u3092\u9069\u5f53\u306b\u7d10\u3064\u3051\u3066\u3042\u3052\u308b\u3002(anna\u306f\u5168\u90e8\u3001kevin\u306f\u30ab\u30e1\u30e9\u3068\u30ae\u30bf\u30fc\u3001mike\u306f\u7b4b\u30c8\u30ec\u3068\u30ae\u30bf\u30fc) \u3044\u3088\u3044\u3088View\u3092\u3002\u305d\u3053\u307e\u3067\u8907\u96d1\u306a\u3053\u3068\u306f\u3057\u3066\u3044\u306a\u3044\u304c\u3001ModelForm\u3092\u4f7f\u3063\u3066\u3044\u308b\u306e\u3068redirect\u306a\u3093\u304b\u306e\u610f\u5473\u5408\u3044\u304c\u308f\u304b\u3089\u306a\u3044\u5834\u5408\u306fDjango\u306e\u516c\u5f0f\u30c1\u30e5\u30fc\u30c8\u30ea\u30a2\u30eb\u306a\u3069\u3067\u78ba\u8a8d\u3059\u308b\u3068\u3088\u3044\u3002cirecle_board\u306f\u30b5\u30fc\u30af\u30eb\u306e\u4f1d\u8a00\u677f\u30da\u30fc\u30b8\u306b\u306a\u308b\u3002\u3072\u3068\u3053\u3068\u306e\u30e1\u30c3\u30bb\u30fc\u30b8\u304c\u6295\u7a3f\u53ef\u80fd\u306a\u306e\u3067\u30d5\u30a9\u30fc\u30e0\u3092\u51fa\u3057\u3066\u304a\u308a\u3001POST\u30c7\u30fc\u30bf\u304c\u6295\u7a3f\u3055\u308c\u305f\u3089Message\u30af\u30e9\u30b9\u3092\u5229\u7528\u3057\u3066Save\u3092\u884c\u3063\u3066\u3044\u308b\u3002circle_switch\u306frequest.session[&#8216;circle&#8217;]\u3068\u3044\u3046\u3068\u3053\u308d\u306b\u5165\u308bcircle\u306eid\u3092\u5909\u66f4\u3059\u308b\u3060\u3051\u3068\u3044\u3046\u30b7\u30f3\u30d7\u30eb\u306a\u51e6\u7406\u3092\u3057\u3066\u4f1d\u8a00\u677f\u306b\u30ea\u30c0\u30a4\u30ec\u30af\u30c8\u3057\u3066\u3044\u308b\u3002\u4e00\u5fdc\u3001\u53c2\u52a0\u3057\u3066\u3044\u306a\u3044\u4eba\u306f\u5f3e\u304f\u3068\u3044\u3046\u5206\u5c90\u3060\u3051\u306f\u5b9f\u88c5\u3057\u3066\u3044\u308b\u3002 \u4e0a\u3067\u3001MessageForm\u3068\u51fa\u3066\u304d\u305fModelform\u3092app\u30d5\u30a9\u30eb\u30c0\u306e\u4e0b\u306bforms.py\u3068\u3057\u3066\u4f5c\u6210\u3002 Template\u3092\u4f5c\u6210\u3002\u307e\u305a\u306fapp\/temlates\u30d5\u30a9\u30eb\u30c0\u3092\u5207\u3063\u305f\u4e0a\u3067\u3001\u305d\u3053\u306bcircle_board\u753b\u9762\u306ehtml\u3092\u7f6e\u304f\u3002\u5927\u304d\u304f3\u30d6\u30ed\u30c3\u30af\u3042\u308b\u3053\u3068\u3092\u78ba\u8a8d\u3057\u3066\u307b\u3057\u3044\u3002 1: \u30b5\u30fc\u30af\u30eb\u306e\u540d\u79f0\u3092\u5927\u304d\u304f\u8868\u793a\u3001\u30ed\u30b0\u30a4\u30f3\u4e2d\u306e\u30e6\u30fc\u30b6\u3068\u30ed\u30b0\u30a2\u30a6\u30c8\u7528\u306e\u30ea\u30f3\u30af\u3092\u8868\u793a\u3002 2: \u4ed6\u306e\u30b5\u30fc\u30af\u30eb\u306e\u30dc\u30fc\u30c9\u3078\u5207\u308a\u66ff\u3048(circle_switch)\u3092\u3059\u308b 3: \u4f1d\u8a00\u30e1\u30c3\u30bb\u30fc\u30b8\u306e\u6295\u7a3f\u30d5\u30a9\u30fc\u30e0\u3068\u3001\u6295\u7a3f\u6e08\u307f\u306e\u30e1\u30c3\u30bb\u30fc\u30b8\u306e\u8868\u793a \u305d\u308c\u3068\u3001\u30ed\u30b0\u30a4\u30f3\u753b\u9762\u7528\u306b\u4e00\u3064\u3060\u3051templates\u306e\u4e0b\u306bregistration\u3068\u3044\u3046\u30d5\u30a9\u30eb\u30c0\u3092\u6398\u3063\u3066\u30d5\u30a1\u30a4\u30eb\u3092\u7f6e\u304f\u3002 \u3042\u3068\u306f\u3001\u30e6\u30fc\u30b6\u304c\u4eca\u3069\u3053\u306e\u30b5\u30fc\u30af\u30eb\u3092\u898b\u3066\u3044\u308b\u306e\u304b\u3092Session\u3067\u7ba1\u7406\u3057\u305f\u3044\u306e\u3067\u30df\u30c9\u30eb\u30a6\u30a7\u30a2\u3092\u4e00\u3064\u4f5c\u308b\u3002\u3084\u3063\u3066\u3044\u308b\u3053\u3068\u306f\u30b7\u30f3\u30d7\u30eb\u306b\u3044\u3046\u30683\u3064\u304f\u3089\u3044\u3067\u300c\u30a2\u30af\u30bb\u30b9\u3092\u53d7\u3051\u305f\u3068\u304d\u306b\u30e6\u30fc\u30b6\u304c\u30ed\u30b0\u30aa\u30f3\u3057\u3066\u3044\u3066\u307e\u3060request.session[&#8216;circle&#8217;]\u304c\u30bb\u30c3\u30c8\u3055\u308c\u3066\u3044\u306a\u3044\u5834\u5408\u306f\u9069\u5f53\u306a\u3082\u306e\u3092\u4e00\u3064\u9078\u3076\u300d\u300crequest.session[&#8216;circle&#8217;]\u306bID\u306e\u6570\u5024\u304c\u4fdd\u5b58\u3055\u308c\u3066\u3044\u305f\u3089\u3001Circle\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u3092request.circle\u306b\u30bb\u30c3\u30c8\u3059\u308b=View\u3067request.circle\u304c\u3044\u304d\u306a\u308a\u4f7f\u3048\u308b\u300d\u300c\u30ed\u30b0\u30aa\u30f3\u3057\u3066\u3044\u308b\u30e6\u30fc\u30b6\u304c\u3069\u3053\u306eCircle\u306b\u3082\u6240\u5c5e\u3057\u3066\u3044\u306a\u3044\u5834\u5408\u306f\u30a8\u30e9\u30fc\u306b\u306a\u308b(return &#8220;error&#8221; \u3068\u304b\u3044\u307e\u6642\u70b9\u306f\u9069\u5f53)\u300d \u3055\u3066\u52d5\u304b\u3057\u3066\u898b\u308b\u3068\u3001\u3053\u3093\u306a\u30a2\u30d7\u30ea\u304c\u3061\u3083\u3093\u3068\u52d5\u3044\u305f\u3002Mike\u3067\u30ed\u30b0\u30a4\u30f3\u3057\u3066\u3044\u3066\u30ae\u30bf\u30fc\u306e\u30b5\u30fc\u30af\u30eb\u306b\u3044\u308b\u3002Mike\u304c\u53c2\u52a0\u3057\u3066\u3044\u308b\u4ed6\u306e\u30b5\u30fc\u30af\u30eb\u3068\u3057\u3066\u306f\u7b4b\u30c8\u30ec\u304c\u3042\u308b\u306e\u3067Change Circle\u306b\u306f\u305d\u308c\u304c\u8868\u793a\u3055\u308c\u3066\u3044\u308b\u3002Message Board\u306b\u306f\u4ed6\u306e\u30e6\u30fc\u30b6\u304c\u6295\u7a3f\u3057\u305f\u30e1\u30c3\u30bb\u30fc\u30b8\u3082\u542b\u3081\u3066\u8868\u793a\u3055\u308c\u3066\u3044\u308b\u3002 \u3053\u308c\u3067\u57fa\u672c\u7684\u306a\u30a2\u30d7\u30ea\u306f\u4f5c\u308a\u7d42\u3048\u305f\u3068\u3059\u308b\u3002\u4eca\u306e\u6240Circle\u306e\u65b0\u898f\u8ffd\u52a0\u753b\u9762\u3084\u30e6\u30fc\u30b6\u3092\u65b0\u898f\u306b\u767b\u9332\u3059\u308b\u753b\u9762\u306fAdmin\u753b\u9762\u306b\u3057\u304b\u306a\u3044\u304c\u3001\u3053\u308c\u306f\u8a8d\u8a3c\u3092Firebase\u3092\u4f7f\u3063\u3066Google\u306a\u3069\u306e\u30bd\u30fc\u30b7\u30e3\u30eb\u30b5\u30fc\u30d3\u30b9\u3068\u306e\u9023\u643a\u3067\u4f5c\u308b\u7df4\u7fd2\u7528\u306e\u524d\u63d0\u306a\u306e\u3067\u3001\u305d\u3053\u3078\u9032\u3080\u3053\u3068\u306b\u3059\u308b\u3002 Firebase\u8a8d\u8a3c\u3092\u5c0e\u5165 \u3053\u306e\u7c21\u5358\u306a\u30a2\u30d7\u30ea\u306bFirebase\u8a8d\u8a3c\u3092\u7d44\u307f\u8fbc\u3093\u3067\u3044\u304f\u300240\u6642\u9593\u304f\u3089\u3044\u8abf\u3079\u307e\u304f\u3063\u3066\u3088\u3046\u3084\u304f\u5927\u4f53\u52d5\u304f\u3088\u3046\u306b\u306a\u3063\u305f\u3002 \u3072\u3068\u307e\u305aFirebase\u306b\u306e\u30a2\u30ab\u30a6\u30f3\u30c8\u3092\u767b\u9332\u3057\u3066\u4ee5\u4e0b\u306e\u753b\u9762\u3067\u3000&lt;\/> \u306eWeb\u3092\u9078\u629e\u3057\u3001\u3042\u308c\u3053\u308c\u307f\u3064\u3064\u306a\u3093\u3068\u306a\u304f\u3053\u306e\u753b\u9762\u307e\u3067\u305f\u3069\u308a\u7740\u304f\u3002 \u30e1\u30fc\u30eb\/\u30d1\u30b9\u30ef\u30fc\u30c9\u8a8d\u8a3c\u3068\u3001Google\u3068Twitter\u3042\u305f\u308a\u3092\u30ed\u30b0\u30aa\u30f3\u65b9\u6cd5\u306b\u306f\u5165\u308c\u3066\u304a\u304d\u305f\u3044\u306e\u3067\u3001\u3053\u3053\u306fWeb\u3067\u8abf\u3079\u306a\u304c\u3089\u5b9f\u65bd\u3002Google\u306f\u7c21\u5358\u3060\u3063\u305f\u6c17\u304c\u3059\u308b\u3051\u3069\u3001Twitter\u306b\u3064\u3044\u3066\u306fElevated Access\u306e\u7533\u8acb\u3068\u3044\u3046\u306e\u304c\u5fc5\u8981\u3067\u5c11\u3057\u624b\u9593\u53d6\u3063\u305f\u3002\u624b\u9806\u306e\u30e1\u30e2\u3092\u3053\u3053\u306f\u6b8b\u3057\u3066\u3044\u306a\u3044\u3002 Firebase\u5074\u304c\u5927\u4f53\u6574\u3063\u305f\u306a\u3089\u3070\u3001\u30a2\u30d7\u30ea\u5074\u3092\u4f5c\u3063\u3066\u3044\u304f\u3002\u307e\u305a\u3001\u5168\u4f53\u7684\u306b\u4ee5\u4e0b\u306e\u69cb\u6210\u3068\u306a\u3063\u3066\u3044\u308b\u3002\u7d50\u69cb\u3084\u3084\u3053\u3057\u3044\u3051\u3069\u6700\u4f4e\u9650\u8a8d\u8a3c\u51fa\u3084\u308a\u305f\u3044\u3053\u3068\u3092\u3084\u3063\u3066\u3044\u304f\u3068\u307b\u307c\u3053\u308c\u304f\u3089\u3044\u306b\u306f\u306a\u308b\u6c17\u304c\u3059\u308b\u3002 Portal Django\u3068\u3057\u3066View\u3092\u4e00\u3064\u5207\u308b\u3002\u3084\u3063\u3066\u3044\u308b\u3053\u3068\u306fFirebase Auth UI\u3092\u307b\u307c\u30de\u30cb\u30e5\u30a2\u30eb\u901a\u308a\u306b\u8868\u793a\u3059\u308b\u3060\u3051\u3002\u3082\u3057\u3059\u3067\u306bDjango\u30a2\u30d7\u30ea\u306b\u8a8d\u8a3c\u6e08\u307f\u3067\u3042\u308c\u3070\u30a2\u30d7\u30ea\u306e\u30c8\u30c3\u30d7\u30da\u30fc\u30b8(circle_board)\u306b\u98db\u3070\u3059\u304c\u3001\u305d\u3046\u3067\u306a\u3051\u308c\u3070portal.html\u3092\u30ec\u30f3\u30c0\u30ea\u30f3\u30b0\u3059\u308b\u3060\u3051\u3002 templates\/portal.html\u306f\u3001\u307b\u307c\u30de\u30cb\u30e5\u30a2\u30eb\u901a\u308a\u306bFirebase Auth UI\u3092\u8868\u793a\u3055\u305b\u308b\u3002\u305f\u3060\u3001firebase\u305d\u306e\u3082\u306e\u306e\u30de\u30cb\u30e5\u30a2\u30eb\u3068\u304b\u3060\u3068firebase-app.js\u3068\u304b\u3092\u4f7f\u308f\u305b\u3088\u3046\u3068\u3057\u304f\u308b\u304c\u3001&#8221;-compat&#8221;\u4ed8\u304d\u306e\u30d5\u30a1\u30a4\u30eb\u3092\u9078\u3076\u3088\u3046\u306b\u6ce8\u610f\u3002\u305d\u3046\u3067\u306a\u3051\u308c\u3070module\u3068\u3057\u3066\u5229\u7528\u3057\u306a\u3051\u308c\u3070\u306a\u3089\u306a\u304f\u306a\u308a\u3001Javascript\u3042\u307e\u308a\u8a73\u3057\u304f\u306a\u3044\u3051\u3069\u3001&lt;script type=&#8221;module&#8221;>\u3063\u3066\u306e\u306b\u306f\u6c17\u3092\u3064\u3051\u306a\u3044\u3068\u6050\u308d\u3057\u3044\u6cbc\u306b\u306f\u307e\u308b\u3002\u3042\u3068config\u306b\u95a2\u3057\u3066\u306f\u74b0\u5883\u3054\u3068\u306b\u3053\u3068\u306a\u308b\u306e\u3067\u8abf\u3079\u3066\u8a2d\u5b9a\u304c\u5fc5\u8981\u3002signInSuccessURL\u3068\u3044\u3046\u306e\u304c\u3001\u6b21\u306eBridge\u3068\u3044\u3046View\u306b\u98db\u3070\u3057\u3066\u3044\u308b\u90e8\u5206\u306b\u306a\u308b\u3002 \u3053\u308c\u3067\u4ee5\u4e0b\u304c\uff08\u305f\u3076\u3093\uff09\u8868\u793a\u3055\u308c\u308b\u3002 &hellip; <\/p>\n<p class=\"link-more\"><a href=\"https:\/\/blog.solong.jp\/?p=226\" class=\"more-link\">Read more<span class=\"screen-reader-text\"> &#8220;Django\u3067\u516c\u958bWeb\u30a2\u30d7\u30ea\u3092Firebase\u8a8d\u8a3c\u3067\u4f5c\u308b&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[7],"tags":[],"class_list":["post-226","post","type-post","status-publish","format-standard","hentry","category-web"],"_links":{"self":[{"href":"https:\/\/blog.solong.jp\/index.php?rest_route=\/wp\/v2\/posts\/226","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.solong.jp\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.solong.jp\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.solong.jp\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.solong.jp\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=226"}],"version-history":[{"count":9,"href":"https:\/\/blog.solong.jp\/index.php?rest_route=\/wp\/v2\/posts\/226\/revisions"}],"predecessor-version":[{"id":255,"href":"https:\/\/blog.solong.jp\/index.php?rest_route=\/wp\/v2\/posts\/226\/revisions\/255"}],"wp:attachment":[{"href":"https:\/\/blog.solong.jp\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=226"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.solong.jp\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=226"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.solong.jp\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=226"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}