-
DjangoにAdminLTEを入れるときのhtmlフォーマット
{% load static %} <!DOCTYPE html> <!-- This is a starter template page. Use this page to start your new project from scratch. This page gets rid of all links and provides the needed markup only. --> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>AdminLTE 3 | Starter</title> <!-- Google Font: Source Sans Pro --> <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,400i,700&display=fallback"> <!-- Font Awesome Icons --> <link rel="stylesheet" href="{% static 'AdminLTE-3.2.0/plugins/fontawesome-free/css/all.min.css' %}"> <!-- Theme style --> <link rel="stylesheet" href="{% static 'AdminLTE-3.2.0/dist/css/adminlte.min.css' %}"> <!-- toastr (AdminLTEの通知用プラグイン) --> <link rel="stylesheet" href="{% static 'AdminLTE-3.2.0/plugins/toastr/toastr.min.css' %}"> </head> <body class="hold-transition sidebar-mini"> <div class="wrapper"> <!-- Navbar --> <nav class="main-header navbar navbar-expand navbar-white navbar-light"> <!-- Left navbar links --> <ul class="navbar-nav"> <li class="nav-item"> <a class="nav-link" data-widget="pushmenu" href="#" role="button"><i class="fas fa-bars"></i></a> </li> <li class="nav-item d-none d-sm-inline-block"> <a href="index3.html" class="nav-link">Home</a> </li> <li class="nav-item d-none d-sm-inline-block"> <a href="#" class="nav-link">Contact</a> </li> </ul> <!-- Right navbar links --> <ul class="navbar-nav ml-auto"> <!-- Navbar Search --> <li class="nav-item"> <a class="nav-link" data-widget="navbar-search" href="#" role="button"> <i class="fas fa-search"></i> </a> <div class="navbar-search-block"> <form class="form-inline"> <div class="input-group input-group-sm"> <input class="form-control form-control-navbar" type="search" placeholder="Search" aria-label="Search"> <div class="input-group-append"> <button class="btn btn-navbar" type="submit"> <i class="fas fa-search"></i> </button> <button class="btn btn-navbar" type="button" data-widget="navbar-search"> <i class="fas fa-times"></i> </button> </div> </div> </form> </div> </li> <!-- Messages Dropdown Menu --> <li class="nav-item dropdown"> <a class="nav-link" data-toggle="dropdown" href="#"> <i class="far fa-comments"></i> <span class="badge badge-danger navbar-badge">3</span> </a> <div class="dropdown-menu dropdown-menu-lg dropdown-menu-right"> <a href="#" class="dropdown-item"> <!-- Message Start --> <div class="media"> <img src="{% static 'AdminLTE-3.2.0/dist/img/user1-128x128.jpg' %}" alt="User Avatar" class="img-size-50 mr-3 img-circle"> <div class="media-body"> <h3 class="dropdown-item-title"> Brad Diesel <span class="float-right text-sm text-danger"><i class="fas fa-star"></i></span> </h3> <p class="text-sm">Call me whenever you can...</p> <p class="text-sm text-muted"><i class="far fa-clock mr-1"></i> 4 Hours Ago</p> </div> </div> <!-- Message End --> </a> <div class="dropdown-divider"></div> <a href="#" class="dropdown-item"> <!-- Message Start --> <div class="media"> <img src="{% static 'AdminLTE-3.2.0/dist/img/user8-128x128.jpg' %}" alt="User Avatar" class="img-size-50 img-circle mr-3"> <div class="media-body"> <h3 class="dropdown-item-title"> John Pierce <span class="float-right text-sm text-muted"><i class="fas fa-star"></i></span> </h3> <p class="text-sm">I got your message bro</p> <p class="text-sm text-muted"><i class="far fa-clock mr-1"></i> 4 Hours Ago</p> </div> </div> <!-- Message End --> </a> <div class="dropdown-divider"></div> <a href="#" class="dropdown-item"> <!-- Message Start --> <div class="media"> <img src="{% static 'AdminLTE-3.2.0/dist/img/user3-128x128.jpg' %}" alt="User Avatar" class="img-size-50 img-circle mr-3"> <div class="media-body"> <h3 class="dropdown-item-title"> Nora Silvester <span class="float-right text-sm text-warning"><i class="fas fa-star"></i></span> </h3> <p class="text-sm">The subject goes here</p> <p class="text-sm text-muted"><i class="far fa-clock mr-1"></i> 4 Hours Ago</p> </div> </div> <!-- Message End --> </a> <div class="dropdown-divider"></div> <a href="#" class="dropdown-item dropdown-footer">See All Messages</a> </div> </li> <!-- Notifications Dropdown Menu --> <li class="nav-item dropdown"> <a class="nav-link" data-toggle="dropdown" href="#"> <i class="far fa-bell"></i> <span class="badge badge-warning navbar-badge">15</span> </a> <div class="dropdown-menu dropdown-menu-lg dropdown-menu-right"> <span class="dropdown-header">15 Notifications</span> <div class="dropdown-divider"></div> <a href="#" class="dropdown-item"> <i class="fas fa-envelope mr-2"></i> 4 new messages <span class="float-right text-muted text-sm">3 mins</span> </a> <div class="dropdown-divider"></div> <a href="#" class="dropdown-item"> <i class="fas fa-users mr-2"></i> 8 friend requests <span class="float-right text-muted text-sm">12 hours</span> </a> <div class="dropdown-divider"></div> <a href="#" class="dropdown-item"> <i class="fas fa-file mr-2"></i> 3 new reports <span class="float-right text-muted text-sm">2 days</span> </a> <div class="dropdown-divider"></div> <a href="#" class="dropdown-item dropdown-footer">See All Notifications</a> </div> </li> <li class="nav-item"> <a class="nav-link" data-widget="fullscreen" href="#" role="button"> <i class="fas fa-expand-arrows-alt"></i> </a> </li> <li class="nav-item"> <a class="nav-link" data-widget="control-sidebar" data-slide="true" href="#" role="button"> <i class="fas fa-th-large"></i> </a> </li> </ul> </nav> <!-- /.navbar --> <!-- Main Sidebar Container --> <aside class="main-sidebar sidebar-dark-primary elevation-4"> <!-- Brand Logo --> <a href="index3.html" class="brand-link"> <img src="{% static 'AdminLTE-3.2.0/dist/img/AdminLTELogo.png' %}" alt="AdminLTE Logo" class="brand-image img-circle elevation-3" style="opacity: .8"> <span class="brand-text font-weight-light">AdminLTE 3</span> </a> <!-- Sidebar --> <div class="sidebar"> <!-- Sidebar user panel (optional) --> <div class="user-panel mt-3 pb-3 mb-3 d-flex"> <div class="image"> <img src="{% static 'AdminLTE-3.2.0/dist/img/user2-160x160.jpg' %}" class="img-circle elevation-2" alt="User Image"> </div> <div class="info"> <a href="#" class="d-block">Alexander Pierce</a> </div> </div> <!-- SidebarSearch Form --> <div class="form-inline"> <div class="input-group" data-widget="sidebar-search"> <input class="form-control form-control-sidebar" type="search" placeholder="Search" aria-label="Search"> <div class="input-group-append"> <button class="btn btn-sidebar"> <i class="fas fa-search fa-fw"></i> </button> </div> </div> </div> <!-- Sidebar Menu --> <nav class="mt-2"> <ul class="nav nav-pills nav-sidebar flex-column" data-widget="treeview" role="menu" data-accordion="false"> <!-- Add icons to the links using the .nav-icon class with font-awesome or any other icon font library --> <li class="nav-item menu-open"> <a href="#" class="nav-link active"> <i class="nav-icon fas fa-tachometer-alt"></i> <p> Starter Pages <i class="right fas fa-angle-left"></i> </p> </a> <ul class="nav nav-treeview"> <li class="nav-item"> <a href="#" class="nav-link active"> <i class="far fa-circle nav-icon"></i> <p>Active Page</p> </a> </li> <li class="nav-item"> <a href="#" class="nav-link"> <i class="far fa-circle nav-icon"></i> <p>Inactive Page</p> </a> </li> </ul> </li> <li class="nav-item"> <a href="#" class="nav-link"> <i class="nav-icon fas fa-th"></i> <p> Simple Link <span class="right badge badge-danger">New</span> </p> </a> </li> </ul> </nav> <!-- /.sidebar-menu --> </div> <!-- /.sidebar --> </aside> <!-- Content Wrapper. Contains page content --> <div class="content-wrapper"> <!-- Content Header (Page header) --> <div class="content-header"> <div class="container-fluid"> <div class="row mb-2"> <div class="col-sm-6"> <h1 class="m-0">Starter Page</h1> </div><!-- /.col --> <div class="col-sm-6"> <ol class="breadcrumb float-sm-right"> <li class="breadcrumb-item"><a href="#">Home</a></li> <li class="breadcrumb-item active">Starter Page</li> </ol> </div><!-- /.col --> </div><!-- /.row --> </div><!-- /.container-fluid --> </div> <!-- /.content-header --> <!-- Main content --> <div class="content"> <div class="container-fluid"> <div class="row"> <div class="col-lg-6"> <div class="card"> <div class="card-body"> <h5 class="card-title">Card title</h5> <p class="card-text"> Some quick example text to build on the card title and make up the bulk of the card's content. </p> <a href="#" class="card-link">Card link</a> <a href="#" class="card-link">Another link</a> </div> </div> <div class="card card-primary card-outline"> <div class="card-body"> <h5 class="card-title">Card title</h5> <p class="card-text"> Some quick example text to build on the card title and make up the bulk of the card's content. </p> <a href="#" class="card-link">Card link</a> <a href="#" class="card-link">Another link</a> </div> </div><!-- /.card --> </div> <!-- /.col-md-6 --> <div class="col-lg-6"> <div class="card"> <div class="card-header"> <h5 class="m-0">Featured</h5> </div> <div class="card-body"> <h6 class="card-title">Special title treatment</h6> <p class="card-text">With supporting text below as a natural lead-in to additional content.</p> <a href="#" class="btn btn-primary">Go somewhere</a> </div> </div> <div class="card card-primary card-outline"> <div class="card-header"> <h5 class="m-0">Featured</h5> </div> <div class="card-body"> <h6 class="card-title">Special title treatment</h6> <p class="card-text">With supporting text below as a natural lead-in to additional content.</p> <a href="#" class="btn btn-primary">Go somewhere</a> </div> </div> </div> <!-- /.col-md-6 --> </div> <!-- /.row --> </div><!-- /.container-fluid --> </div> <!-- /.content --> </div> <!-- /.content-wrapper --> <!-- Control Sidebar --> <aside class="control-sidebar control-sidebar-dark"> <!-- Control sidebar content goes here --> <div class="p-3"> <h5>Title</h5> <p>Sidebar content</p> </div> </aside> <!-- /.control-sidebar --> <!-- Main Footer --> <footer class="main-footer"> <!-- To the right --> <div class="float-right d-none d-sm-inline"> Anything you want </div> <!-- Default to the left --> <strong>Copyright &copy; 2014-2021 <a href="https://adminlte.io">AdminLTE.io</a>.</strong> All rights reserved. </footer> </div> <!-- ./wrapper --> <!-- REQUIRED SCRIPTS --> <!-- jQuery --> <script src="{% static 'AdminLTE-3.2.0/plugins/jquery/jquery.min.js' %}"></script> <!-- Bootstrap 4 --> <script src="{% static 'AdminLTE-3.2.0/plugins/bootstrap/js/bootstrap.bundle.min.js' %}"></script> <!-- AdminLTE App --> <script src="{% static 'AdminLTE-3.2.0/dist/js/adminlte.min.js' %}"></script> <script src="{% static 'AdminLTE-3.2.0/plugins/toastr/toastr.min.js' %}"></script> </body> </html>
-
DjangoにAdminLTEを実装してみた!
どうも!おはこんばにちは!ゆしゅです。今日はDjangoにAdminLTEを実装してみた!ということで、まず簡単に流れをザッと載せていきますDjangoサーバを立ち上げるAdminLTEのjsやcssを一括で公式からダウンロードDjangoサーバのstaticにAdminLTEを丸ごとぶち込むAdminLTEに含まれるstarter.htmlをtemplatesにぶち込む表示したら完成では順番にやっていきたいと思います。まず「1. Djangoサーバを立ち上げる」から。ここはもういつも通り。100万回もやったら忘れないね。まず、VSCodeのエクスプローラー上で右クリック(Macは二本指クリック)でオプション画面みたいなのを表示する。この「ワークスペースにフォルダーを追加」というのを押すとフォルダ画面が出るので、そこで適当な開発用のフォルダを作成し、追加する。そしてterminalを開いて、作業ディレクトリをさっき追加したフォルダにする。おそらく既にpythonもpipも入れているはずなので、virtualenvも入っているはず(これはよく使うので入れておいた方がいい)。このvirtualenvを使ってまず、Djangoサーバ立ち上げのための仮想環境を作ります。とりゃ!どうでしょう?できましたかね。そしたら、そのまま仮想環境も立ち上げちゃいましょう!とりゃ!もう環境は整いました。早いですね〜さすがの早業です。(ゆしゅじゃなきゃ見逃しちゃうね!)続いて、Djangoをpipでインストールします。インストールしたら、以下の流れで作業ディレクトリ内にprojectを立ち上げ、アプリも一つ作っておきます。(今回はhome_app)一応これで「1. Djangoサーバを立ち上げる」はほぼ完了です!ちょっと動作確認ははしょりました。(一応 python manage.py runserverとすると立ち上がります)そして!「2. AdminLTEのjsやcssを一括で公式からダウンロード」に進みます。こちらは以下にアクセスして3.2.0などをダウンロードしておくと良いでしょう。(正直beta版はなんかエラーが入ってそうで怖い)https://github.com/ColorlibHQ/AdminLTE/releasesサクサクいきます!「3. DjangoサーバのstaticにAdminLTEを丸ごとぶち込む」です。VSCode画面上でこんな感じにtemplatesとstaticを作ってください。お!もうできちゃったんですか!さすがですね〜(私ほどではないですが)ここからちょっと難しいです。なので細分化した手順を載せておきます。1. mysite内setteings.pyで以下の加筆修正-加筆修正1import os from django.utils.translation import gettext_lazy as _- 加筆修正2INSTALLED_APPSにhome_app.apps.HomeAppConfigを追加- 加筆修正3TEMPLATESのDIRの値を変える'DIRS': ['templates'],- 加筆修正4日本の日時に合わせる(これはもう以下のサイトを参考にしてください。。。)https://www.tohoho-web.com/django/settings.html- 加筆修正5STATIC_URLという変数があるのでその下にでも置いておきましょう。STATICFILES_DIRS = [ os.path.join(BASE_DIR, 'static') ]正直もう疲れましたよね。。。でもまだまだあるんです泣2. home_app/views.pyで以下を書き込む# Create your views here. from django.views.generic import TemplateView # Create your views here. class HomeIndexView(TemplateView): template_name = "index.html"3. home_appにurls.pyを作る4. home_app/urls.pyに以下を書き込むfrom django.urls import path from . import views app_name = "home" urlpatterns = [ path("", views.HomeIndexView.as_view(), name=""), ]ここのapp_nameはあってもなくても。この変数を使うのはテンプレートタグの中でくらいです。5. mysite/urls.pyに以下を書き込むfrom django.contrib import admin from django.urls import path, include urlpatterns = [ path('admin/', admin.site.urls), path('', include('home_app.urls')), ]もうそろそろ終わりかな?と思ったそこのあなた!!そうです!もうすぐです!6. staticにAdminLTEを丸ごとぶち込むcssやiconは分かりやすいように同じ階層で入れるんだよ〜って例として入れました。7. templatesにstarter.htmlをぶち込むこれについては、今後のためにbase.htmlとindex.htmlに分けておくと良いことを示しておきます。基本的にDjangoではbase.htmlでhtmlのベースとなるページを作っておきます。なので、後々開発を進めていくのであれば、starter.htmlのベースに使えそうな部分だけ抜き取ってbase.htmlに入れておくと良いです。今回はめんどくさいのでindex.htmlにstarter.htmlの中身をコピペしました。(そのため「2. home_app/views.pyで以下を書き込む」ではindex.htmlとしていました)8. index.htmlをDjango用にカスタマイズする最後の仕上げです!結構めんどくさいと思うのでコピペできるのを用意しました!(最初からそうしろよ)この投稿の次の投稿を見てください!!これでもう本当に最後ですね。「5. 表示したら完成」ですterminal上でpython manage.py runserverと打ち込み、ブラウザ上でlocalhost:8000と打ち込んでみてください。表示結果はぜひ自分の目で確かめてみてください。できてからのお楽しみです^^ではでは〜!
-
イギリス旅行計画
こんにちは。お久しぶりです。初めましての方もいるかも。。。はい、そんなことはさておいて、最近読書をたくさんしているはずなのにどんどん日本語がうまく書けなくなっているゆしゅです。実は来年あたりにイギリス旅行に行きたいなーと考えています。きっかけは「ストーンサークルの殺人」というM.W クレイヴンさんによって書かれた作品を読んだことでした。彼のこの作品、ワシントン・ポー刑事シリーズは現在5作ほど日本で翻訳されていますが、どれも非常に面白いので、とてもオススメです!!(絶対に読んでください)そして、どの作品でもイギリス愛に溢れており、情景描写の至る所にイギリスの魅力が詰まっています。それをずっと目にしているとどうしても自分の目で見たいという欲に駆られ、イギリスの歴史や文化などを勉強するようになりました。ま、実はまだ1冊しか読んでないんですけどね!(イギリス関係の本はもう6冊くらい蓄えてます)まあこれから読んでいくとして、その1冊で知った情報を記録しておこうと思います。まず歴史から。イギリスのメインの歴史は11世紀から始まります。紀元前も一応はあるのですが、多国籍文化と一言で語られることが多いそう。一応下に11世紀以前の民族比較表を記載しておきます(ChatGPTで生成したので真偽不明) 特徴 アングロサクソン人 ローマ人 ケルト人 イングランド人 起源 ゲルマン系(アングル人、サクソン人、ジュート人) ラテン系(ローマ市発祥) インド・ヨーロッパ語族のケルト系 アングロサクソン+ノルマン人+ケルト+デーン人(混成) 主な活動地域 5〜11世紀のブリテン島 紀元前1世紀〜5世紀のローマ帝国 紀元前5世紀〜西欧全域(特にブリテン・ガリア) 11世紀以降のイングランド地域 言語 古英語(ゲルマン語派) ラテン語 ケルト語派(ブリソン語、ゲール語など) 中英語 → 近代英語(アングロサクソン語+ノルマン語+ラテン語起源) 宗教 ゲルマン多神教 → キリスト教 ローマ神話 → キリスト教 ケルト多神教(ドルイド)→ キリスト教 キリスト教(カトリック→英国国教会) 社会制度 部族王国制 → 封建制の始まり 共和政 → 帝政 → ローマ法 部族連合・酋長制 封建制 → 王政 → 立憲君主制 文化 武勇・戦士文化、英雄叙事詩(ベーオウルフ) 都市文明、ローマ法、インフラ 口承文化、詩・神話、装飾美術 法律(コモンロー)、議会政治、英語文学、海洋文化 建築 木造建築中心 石造都市建築 木造・土造の集落、ケアン 城・教会建築、都市インフラ 関係性 ローマ撤退後にブリテンへ侵入 ケルト人を征服、ローマ化 ローマ・アングロサクソンに圧迫されつつ残存 アングロサクソン、ノルマン、ケルト文化の融合体 流れで言うとまず、紀元前28世紀ごろにストーンヘンジ(ストーンサークル)を作る先住民(先住民の民族名は不明)がいて、そこに紀元前20世紀ごろまでの間に青銅器を持ったビーカー人が占領してくる。紀元前6世紀になると鉄器を持ったケルト人がやってきて、島でのんびりスヤスヤしていたら紀元前43年にローマ人が征服してくる。しかし、5世紀の始まり、やっぱ無理かもってなり、アングロ・サクソン人というゲルマン系の移民が征服してきてくる中で徐々に支配制度が確立されてきたっていう流れですかね。先住民 > ビーカー人 > ケルト人 > ローマ人 = アングロ・サクソン人 > イングランド人一番長かったのは先住民で、次に長かったのはビーカー人、ケルト人、ローマ人 and アングロ・サクソン人の順になりそうです。(イングランド人の定義が曖昧なので歴史の長さの比較では省きました)その後アングロ・サクソン人の王朝が崩壊したのですが、皇帝の子孫が若過ぎたため適当な伯爵家の子孫を王位につけていたらその隙をついてノルマン人に攻められ、勝利を収めた初代ノルマン人イングランド王のウィリアム1世がノルマン王朝を立ち上げ、イングランド島の歴史が始まったのかな。実はこのアングロ・サクソンに支配されていた時の歴史とそれ以降の王朝の歴史が膨大だったので結構はしょりました。今後暇な時にアングロ・サクソンによる支配の歴史と各王朝の歴史をまとめていきたいと思います。- アングロ・サクソンによる支配の歴史- イングランドの歴史
-
タスクスケジュール画面でのGUI操作によるタスクの時間延長
結論、以下のような画面に簡単にできます。こちらはDjangoとJavascriptの連携が必須になります。
-
今日以前から今日以降のデータを取得したいとき
例えば、タスクスケジューリングなどで取りたいデータが11/24日だった場合、11/25 0:00より前の開始時間で、11/24 0:00以降の終了時間のデータを取れる。つまり、11/25 0:00が開始時間のデータを取らないようにしている。以下のようにして取得ができる tasks = ScheduledTask.objects.filter(start_time__lt=date.today()+ timedelta(days=1), end_time__gte=date.today())
-
初!開発サーバを公開します!〜USB レンタルサーバ〜
djangoを用いてUSBなどのデバイスを気軽にレンタルできるサーバの開発をしました。そのレポジトリは以下になります。https://github.com/k-masahiro116/USB_Rental_ServerDjangoの勉強にもぜひ使ってみてください。使い方は簡単で、requirement.txtをインストールし、python manage.py runserverを実行してもらえば動くはずです。感想お待ちしております〜
-
今日から再スタート!!
やっとPCが買えた!!一応8年前くらいに買ったデスクトップPCもあるけど重たくて重たくて。。。それがついに!!Mac book Airに!!!きゃーーーー!!!!これしかもM3チップだからなかなか速い(*´▷`)しばらくは適当な内容になるかもしれないけどご了承ください🙇Djangoを使ったweb開発はまた余裕ができたら始めるかな〜最近会社でもweb開発をやらせてもろてて、ちょっと自分の開発にも活かせそうな知識も身につけられたので、それをぜひ自分のにも実装したいなと最後に余談、会社の売店でYamazakiのお茶をずっと買ってて、だいたいほうじ茶かルイボスティーか烏龍茶を買うんだけど、今日はほうじ茶でした。
-
最近流行っている劇症型溶血性レンサ球菌感染症(人食いバクテリア)について調べてみた
積極的治療を行ったとしても死亡率は30~70%と高く、患部の切断だけで済むのはまだ良い方だとされる。30代以降で発症しやすく、致死率は子供よりも大人の方が高い。打撲や普通の怪我と診断されることが多く、いつもと違う症状であったら違う病院にも行ってみること。感染状況2021年から徐々に増えてきていることから注意が必要主な感染経路飛沫感染、接触感染少しの傷、特に足の傷から感染冬の乾燥している時期だと乾燥肌を掻いて、その傷口からも感染する可能性症状患部の痛みとその周辺の赤みのある腫れ。ひどいと紫色になる。熱、40度近くまで上がる。感染対策足を大事にすること?傷がある状態で素足での出歩きはなるべく控える。プールや温泉といった素足になる場面が多いところでは注意。常に衛生に気を配り、手洗いやうがいを心がける。
-
能登半島地震へ寄付してみた!!
寄付は初めてだったので、手続きが面倒だったらやめようかなと最初は思っていましたでも、いざやってみたら意外と簡単だったので手順を紹介したいと思いますまず、yahooの寄付サイトを開きます(url: https://donation.yahoo.co.jp/detail/1630064)そこで、「寄付する」というボタンを押していただき、yahooのアカウントでログインしますその後、クレカの登録を行い、プライバシー関連を認証すれば最初に入力した金額が寄付されます🙆石川には縁があり、大切な場所だったので被害に遭ってしまったこと、大変心苦しいです。私はまだ学生の身分なので少しの額ですが、寄付させていただきました。これで少しでも多くの方が救われることを願っています。
-
Wi-Fiに繋がらない問題の解決
Wi-Fiに繋がらなくて悩んだことないですか?Wi-Fiに繋がらなくなってしまう要因はいくつかありますが、私がよく経験するものをここにまとめておきたいと思います。まず大きく分けて2つのパターンがありますお店のWi-Fiに繋がらないおうちのWi-Fiに繋がらない1. お店のWi-Fiに繋がらないこれはログインが必要な場合に起こりがちですこれの解決方法はログインしてしまえばいいということですが、問題はどのようにしてログインすればいいの?ということでしょう大体の場合、Wi-Fiに繋げた瞬間にログイン画面が出ますが、出ない時もあります。そのような時は以下手順でまずIPアドレスを調べます。(Macの場合)手順1. システム設定 => Wi-Fi => 詳細の順に進んでいくすると一番下にIPアドレスを見つけることができますそこで、IPアドレスの一桁目が3であることが確認できると思います。これは自分に割り当てられたアドレスの番地を表しており、このIPアドレスを利用することでIPアドレスを割り当てているWi-FiルータにアクセスすることができますWi-Fiルータにアクセスするためにはデフォルトゲートウェイというアドレスに確認しにいく必要があります。こちらは大体一桁目を1にすることで確認することができますつまり、この場合は192.168.1.1にアクセスすればWi-Fiルータを見にいくことができますアクセスの方法は、シンプルにブラウザの検索バーに打ち込むだけです。このようにして、Wi-Fiルータにアクセスをすれば、お店のWi-Fiにもログインをすることができます。※ Windowsの場合はコマンドプロンプトでipconfigと打てば出てくると思います2. おうちのWi-Fiに繋がらないまず前提として、普段は繋がるのに急に繋がらなくなった場合を想定していますこちらはDHCPが失敗、もしくはセキュリティによる一時的な停止などが挙げられますDHCPが失敗した場合の対処法は至って簡単で、自分でIPアドレスを割り当ててしまえば良いですDHCPとはIPアドレスを自動的に割り当ててくれるサービスで、集団で使うとたまにバグります。そういう時は自分で割り当ててしまうのが一番早く対処できます。これは先ほどのWi-Fiの設定画面で、TCP/IPを選択し、IPv4の構成から手動を選択してIPアドレスを手入力することで設定ができます。また、サブネットマスクが255.255.255.0のようになっている場合は、手動のIPアドレスでも1桁目しか触ることができないので注意しましょう。上記の図の場合だと192.168.1.2~192.168.1.254が自由に設定できるIPアドレスとなります。(255はブロードキャストアドレスと言って別の用途があります)また、この設定はルータごとに決める必要があり、他のWi-Fiに繋げた時に繋げなくなってしまうこともあるので、その時にはDHCPに戻してあげると良いでしょう。セキュリティによって一時的に停止されてしまった場合は、1日置くことで直ります。
-
djangoをさくらのVPSにデプロイ!〜VPSにSSH〜
本ブログに掲載している内容を順番にあげています。また、本ページではドメインの取得法について説明をします。VPSのレンタルドメインの取得 VPSにSSH <- ここ環境変数やコマンドの設定アプリケーションのデプロイuwsgiの設定nginxの設定VPSにSSH今回はVPSにSSH接続するための手順について説明します。(sshでアクセスせずに、コンソール画面からVPSを触るよって人は必要ないです。)これも方法はシンプルで以下の5つのステップに沿って行うことですぐにできますSSHキーの作成(公開鍵と秘密鍵をRSA暗号を用いて作成)公開鍵を登録しているVPSにコピペ1. SSHキーの作成(参考)まず、SSHキーを作成し、置いておく場所をカレントディレクトリとするため、移動をします$cd ~/.sshそしてSSHキーを発行するためのコマンドを打ちますここではファイル名とパスフレーズの入力を求められますが、筆者はfugaというファイル名でパスフレーズを無しにして発行をしています。また、このファイル名についても無しにすることができます。パスフレーズは秘密鍵にアクセスするためのパスワードになっており、登録すればさらにセキュリティを上げることができます。$ssh-keygen Generating public/private rsa key pair. Enter file in which to save the key (/Users/ユーザ名/.ssh/id_rsa): fuga Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in fuga Your public key has been saved in fuga.pub The key fingerprint is: SHA256:NIKUL9Ezccft2pl9mxg+IHS7RH0PxucSrl+Xbxlb The key's randomart image is: +---[RSA 3072]----+ | .o...... | | .o.+. .. . | | .o.oo ... | | . .o o o..=..| | . S oo.*.=.| | ..++.+.*| | o +.++@| | ..E B+| | o=..| +----[SHA256]-----+$ls fuga fuga.pub $chmod 600 fuga左のfugaが秘密鍵で、右のfuga.pubが公開鍵になります。また、chmod 600で秘密鍵のfugaの閲覧権限を上げています。他のユーザーからアクセスできる状態であると使えないためです。これでssh-keyの作成は完了です。2. 公開鍵を登録しているVPSにコピペ続いて公開鍵を自分が登録しているVPSに渡します。渡す方法は至って簡単で、まずさくらのVPSにログインし、SSHキー管理というところに遷移しますすると右上の方にSSHキー登録というボタンがあるのでそこを押しますそうすると以下のような画面が現れてくると思います名前は適当な名前にして頂いて、公開鍵には先ほど作成した.pubの方の中身をコピペします方法としては、catコマンドを打つと全部出てくるのでそれらを全部コピーして公開鍵の枠の中に貼ります$sudo cat fuga.pub ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC1/HXtHJYcspkTfGN2zt8+q8YcQzlfiHHbhXK2wdoY749fN8ZXyD5eb/kgJXNkpzUqpAWvXNHMdk+JTzJHLe3erzUSUQ/Gm90SaEOdcyJPxlBjRWrW/xCTjM8Xi6tZdfyv6AI8lczfMj0OietdW0ERquZ/hn0ktMbvD5BbdGlhfTQYvUa4QwlMmLQ2LQfU9hM5NOStCdG5UpmTZhDzY+aoNPmGDsvwfTNR3DsVoutekTis+dKeeP/sYsdJT+WIvQSFqyyADPP0/nii+nmn+Pjt1XSJGQBl0j1hIs7mw4beyDq5a5NfLkfwvHdiRLb5Xs/zy3AgkI+ls9XZdBJYzbl32/kiLPnd6fIgyJCNjiIzSvbXpSAyGXGomEDohaz2YahBoyT52XULPojlVLxTZ5u5H1NnT5e6ntc8kZ7a94LyArbsHiADcQJGlFO8gufHvXq5I9jk+o+a8EA7vRNXKQGqVNeHG67s8FDo4woOXqAZL5mfこれで完了です余談実際に繋げるときは複数の方法があります1. 秘密鍵だけでssh接続する方法この場合は、VPSのsshのサービスコンフィグを開き、パスワード認証をオフにする必要があります。参考(url: https://qiita.com/kazokmr/items/754169cfa996b24fcbf5)2. 秘密鍵とパスワードで接続する方法こちらは、先ほど作成した秘密鍵を用いるコマンドを付与するだけで問題ないです $ssh -i fuga [リモートユーザー]@[リモートサーバーのホスト名]ですが、わざわざユーザやホスト名を書くのが面倒な場合もあります。その場合は、~/.ssh/configを変更することで可能になりますHost [エイリアス] HostName [リモートサーバーのホスト名] User [リモートユーザー] IdentityFile ~/.ssh/fuga上記のように変更すると$ssh [エイリアス]で繋げられます秘密鍵のパスフレーズを求められたときはそのままEnterで大丈夫です
-
djangoをさくらのVPSにデプロイ!〜ドメインの取得編〜
本ブログに掲載している内容を順番にあげています。また、本ページではドメインの取得法について説明をします。VPSのレンタルドメインの取得 <- ここVPSにSSH環境変数やコマンドの設定アプリケーションのデプロイuwsgiの設定nginxの設定ドメインの取得は結構簡単です。私はさくらのVPSでVPSをレンタルしたので、さくらのVPSでのやり方について説明します。まずこちらにアクセスし、取りたいドメインが使われていないか検索します。すると次のような画面に移り、取れるドメインと取れないドメインの一覧が現れます。この場合だとfugafuga.infoが最も安くレンタルできるドメインであることが分かります最後に、登録者の情報として取得年数や名前、支払い方法などを入力すればドメインのレンタルは完了です。続いてドメインとIPアドレスを関連づける作業に移ります。まず、さくらのドメインコントロールパネルの画面を開きます開くと以下のようなコントロールパネルが現れ、自分が登録したドメインが確認できますここで、ゾーンという部分をクリックし、レコード設定を編集していきます。登録した際にも同じ画面が現れた人もいるかもしれません。もう一度確認をしておきましょうこちらのタイプというカラムにあるAがIPアドレスを記述する欄になりますTXTについてはgoogleサーチコンソールを導入した際に付け加えました以上がドメインの取得の流れになります。いかがだったでしょうか?全てGUIで操作できるのでとても簡単だったと思いますこちらで登録したドメインはもう使えるようになっているので、VPSのコントロールパネルから逆引きホスト名として登録することもできるようになっていると思います
-
Googleアナリティクスを導入する!
作成したdjangoサーバの検索状況やアクセス状況を見るため、google アナリティクスを導入参考にしたサイトはこちら(URL: https://cotodama.co/google-analytics/まず参考サイト通りにアカウントを作っていきますアカウント作成後、作成されたサイトがwordpressなどのCMSで作成されていない場合(自分のようにdjangoなどで作っている人)は、アナリティクスのソフトが入っていないので測定IDをコピペするという手段はできませんそこで、google アナリティクスの画面からプロパティ設定=>データの収集と修正=>データストリームとタブを進めていくと自分のサイトが既に登録されていることを確認できます。そこをクリックして画面を開くと一番上に実装手順というボタンがあるのでそこをクリックするとgoogle アナリティクスを実装するための手法が大きく分けて二つ提供されていることがわかります。手動でインストールするウェブサイト作成ツールまたは CMS を使用してインストールする手動によるインストール本サイトでは手動でインストールするものについて説明します。手動の場合は以下のようにscriptが貼られていると思います。このscriptを自分のサイトの大元となるbase.htmlに貼ってください。<!-- Google tag (gtag.js) --> <script async="" src="https://www.googletagmanager.com/gtag/js?id=G-EXW99DWK78"></script> <script> window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('js', new Date()); gtag('config', 'G-EXW99DWK78'); </script> 数時間後に確認をすると、「データ収集は、過去 48 時間有効になっています。」というような文字が現れるので、これで完了です。これで自分のサイトを閲覧した人の人数や収益などを管理することができますこのほかにも人気コンテンツや検索状況の改善などを確認したい場合は、Googleサーチコンソールへの登録もしておきましょう
-
djangoをさくらのVPSにデプロイ!〜VPSレンタル編〜
ある程度djangoサーバの開発が済んだので、本番環境へのデプロイに挑戦しました使ったツールDjangonginxuwsgiさくらのVPSやったことVPSのレンタルドメインの取得VPSにSSH環境変数やコマンドの設定アプリケーションのデプロイuwsgiの設定nginxの設定上記の順に徐々にpostしていく予定です。なかなか大変だったのでいろいろ抜けているとは思いますが、気づいたら筆者がその都度修正していきます。〜VPSレンタル編〜筆者は何も知らないアホなweb開発初心者だと言うことをまず知っておいてください何も知らない私は「クラウドサーバにアップするぞ!」とまず最初に意気込み、つまづきました結局、いくら頑張ってもAWSに全然アップできず、必死に悩んで調べ、月5kと言う金を払ってアップできませんでした(勉強代)まず、前提としてサーバにはいくつか種類があります。(参考)レンタルサーバ(共有サーバ)VPS(Virtual Private Server: 仮想専用サーバ)専用サーバクラウドサーバいろいろ調べた結果、個人用webサイトを作るのに適しているのはレンタルサーバかVPSであると言うことを知りましたそして、レンタルサーバにチャレンジをしたところ、ここでまたつまづきましたレンタルサーバは管理者によって、インストールできるモジュールに制限されていたり、環境変数やDBの設定が自由にできないようにされていたりすることから、djangoサーバには不適だったそうですここでいざVPSのレンタル(参考: https://i-fc.jp/web/vps-rentalserver/#xservervps今調べてみたらXserverが一番お得そう汗他のサイトを見た時に一番出てきたので検索にヒットしやすいさくらのVPSを選びました初心者はやっぱり先導者が多いところがいいかもしれませんまず、CentOSを選択し、1Gのプランを選択(プランは後から変えられないみたいなので注意)次にパスワードと公開鍵の設定公開鍵の設定は検索するとすぐ出てきますが一応(参考)ssh-keygenで作成したxxx.pubの中身を全てコピーして空いているとこに貼り付ければok(これも今考えればGithub.comからインストールした方が楽だった...)スタートアップスクリプトなどもあるようで、これを入れればletsencriptも楽になったかもしれませんね...自分は手動でやっちゃったのでそれについて後ほど説明したいと思います契約が完了したら起動できるようになっているので、サーバ画面を開いて電源操作から起動を押してくださいこれでVPSのレンタルは完了です。
-
本番環境でdjangoのadminのcssが反映されなかった件について
やっとdjangoのサーバを本番環境にアップしたと思ったらadminのcssが読み込まれないエラーその他エラー$sn.summernote is not a functionこれがどうやらwidget(adminやsummernote)は通信しながら静的ファイルを反映させていたようで、collectstaticが必要だったそうまずsettings.pyの修正 # collectstaticなどを行った際にファイルを設置するstaticフォルダの場所を記述(開発の際は必要ないのでコメントアウトしておく) STATIC_ROOT = os.path.join(BASE_DIR, 'static/') # htmlファイルなどから読み込むstaticフォルダの場所を記述 # STATICFILES_DIRS = [ # os.path.join(BASE_DIR, 'static/') # ]ここでcollect$python3 manage.py collectstatic以下のサイトも参考にしましたが、1と2のどちらの条件も満たさずにcssが読み込まれたので、単純にcollectstaticが問題だったhttps://qiita.com/yumenomatayume/items/c9786298ffb9c1a7f444
-
Djangoで全てのページに共通のコンテンツ・表示を作る
天気の情報をスクレイピングして表示したい!と考えた筆者しかし、スクレイピングしたとて一つのページでしか表示ができず、残念に思っていた今日この頃ある日、全てのページに共通させてカテゴリ一覧を表示するという神機能を知ったURL: https://blog.narito.ninja/detail/150これを参考に作ってみたBlogのアプリがあったので、その下にcontext_processors.pyを作成し、中身を書き書き def common_weather(request): context = {} url_forecast = 'https://tenki.jp/forecast/3/16/4410/13208/' fdict = scrape_weather(url_forecast) forecast = fdict["today"]["forecasts"][0] context["weather"] = "天気: "+forecast["weather"] context["temp_high"] = "最高気温: "+forecast["high_temp"] context["temp_low"] = "最低気温: "+forecast["low_temp"] context["rain_probability"] = "降水確率: " context["rain_probability_0006"] = "00-06: "+forecast["rain_probability"]['00-06'] context["rain_probability_0612"] = "06-12: "+ forecast["rain_probability"]['06-12'] context["rain_probability_1218"] = "12-18: "+ forecast["rain_probability"]['12-18'] context["rain_probability_1824"] = "18-24: "+ forecast["rain_probability"]['18-24'] return context 天気の情報はtenki.jpからスクレイピングしているscrape_weatherの中身は本題ではないのでスルーそしてこの関数をsettings.pyに追加した TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': ['templates'], 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', 'blog.context_processors.common', 'blog.context_processors.common_weather', ], }, }, ] 実際に表示してみると。。。できた!!!
-
web上音声対話システムをどう実装するか?
現在実装済みのweb上対話システムは、対話が進むたびに画面がリロードされてしまうこれだと音声対話を実装したいと考えたとき、リロード後の先頭の対話内容を音声合成させる必要があるしかし、リロードを検出する関数はjavascriptやdjangoには用意されていないので対処法がないそこで、ここでは時間差を計算することで音声対話を実装した最後の対話を生成した時間とリロードが完了した時間差が3秒以内だった場合に、音声合成を行い、発話するように設定このlast_dateに対話を生成した日時を入れています。モデルはDateTimeFieldです。window.onload = function() { var str = {{ last_post|safe }}; const uttr = new SpeechSynthesisUtterance(str); if (Math.abs(Number("{% now 'His'%}")-Number("{{ last_date|date:'His' }}"))<3){ speechSynthesis.speak(uttr); }; console.log(uttr); }; 成功しました!!🙌実際どんなふうにweb上で音声対話を実装しているの?と気になる方はお問合せからご連絡ください。もし要望があれば詳しく載せていきたいと思います。
-
音声認識・音声合成の実装
対話システムを実装したので、それを音声で操作できるようにしたいと考え、実装を試みたまず見栄えのために、マイクのイラストを探した(参考)しかし、コピペしたところ、CSSがズレてしまったので、音声認識のタイミングだけ起動するようにした.volume-viewer-volume { z-index: -1; opacity: 0;}.volume-viewer-volume.open-ring { width: 40px; height: 40px; text-align: center; position: absolute; border-radius: 50%; border: 4px solid #888; top: -10px; left: -10px; z-index: 2; opacity: 1;}上記の場合、.open-ringというのを音声認識のタイミングでaddClass()を用いることで起動できる。また、もう一度押すことでremoveClass()で元に戻すことも可。また、AudioManagerは自然に起動しないことに注意window.onloadでは起動できないという注意がコンソールに流れてきたので、ボタンで起動するように変更音声認識はそのままコードを引用(参考)最終的なコードは以下のようになった<form id="post_form" action="https://xxx.com" method="POST"> <input name="text" id="text" class="textbox" value="" /> <button type="submit">POST</button></th></form><script> _volume = $('.volume-viewer-volume'); var manager = ""; document.querySelector('.fa-microphone').addEventListener('click', function() { _volume.addClass('open-ring'); manager = new AudioManager({ useMicrophone: true, onEnterFrame: function() { var volume = Utils.sum(this.analysers.mic.getByteFrequencyData()); var size = (140 + volume/1000); // 1000は適当(小さくすると円が大きくなる) var adj = (128-size)/2 - 4; // 4はborderの大きさ $('.volume-viewer-volume') .css('height', size + 'px') .css('width', size + 'px') .css('top', adj + 'px') .css('left', adj + 'px') } }).init(); SpeechRecognition = webkitSpeechRecognition || SpeechRecognition; const recognition = new SpeechRecognition(); recognition.interimResults = true; recognition.onresult = (event) => { if (event.results[0].isFinal){ _volume.removeClass('open-ring'); post_text(event.results[0][0].transcript); }; }; recognition.start(); }); function post_text(text){ var form = document.getElementById("post_form"); var input = document.getElementById("text"); input.value = text; form.submit(); };</script>post_formはformタグのidで、inputに音声認識で受け取ったテキストを渡したのち、formを用いてsubmitすることでテキストデータをpostしている。最終的な画面を見てみると...?できた!!
-
柴崎で見つけた美味しいカレー屋さん
いつも通っている教習の帰り道偶然通りかかり、外観で決めて入ったカレー屋さん、Campick内装も非常におしゃれで古風な木造の建物のようになっている木目のブラウンとカラフルな店内が非常にマッチしていた店主は気さくな方で、笑顔から優しさが滲み出た、少しもじゃもじゃのお兄さんだったメニューは三種類のカレーで、その中から好きな組み合わせを選べるその時私はキーマカレーを食べたかったので、そのような説明がなされていたカタカナのカレーと少し辛めの海老カレーの2種類を選択したコップは紙コップでセルフで注ぐ感じで、よく行くラーメン屋を想起させた5分ほど待つと想像以上に美味しそうなカレーが出てきたまさかターメリックライスまで食べれるとは思っておらず、大歓喜カレー以外にも何か乗っており、酸味の効いたナスとラッシーで和えたような野菜などが添えられていたそして実際に食べてみたところ、カレー自体も非常に美味しいが、周りに添えらえたものも混ぜて食べることで味に深みが増し、最後まで楽しんで食べることができたこのカレーは日替わりのようなので、また是非行きたい
-
Djangoでサイドバーを追加してみた
Djangoでサイドバーを追加する方法を調べてみたが、同じアプリ内でしかviews.pyからgetができないことがわかった(参考)そこで、サイドバーを特定のアプリ内で表示(cssでvisibility: hidden;)した状態で、base.htmlでスクレイピングしてみた1. まず、スクレイピングのため、jqueryのgetでurlを指定$.get("{% url 'blog' %}")2. 続いてdone()関数を用いて、スクレイピングした値を引数として受け取る$.get("{% url 'blog' %}") .done(function(data) { })3. dataは文字列なのでDOMParser()を用いてHTMLにキャストする$.get("{% url 'blog' %}") .done(function(data) { let parser = new DOMParser(); let doc = parser.parseFromString(data, "text/html"); })4. data内におけるスクレイピングしたい要素をHTMLのままelementに代入$.get("{% url 'blog' %}") .done(function(data) { let parser = new DOMParser(); let doc = parser.parseFromString(data, "text/html"); let element = doc.getElementsByClassName("xxx")[0].innerHTML })5. あとはdocumentに入れるだけ。insertAdjacentHTMLの引数のafterendは色々変えられるみたいなので代入したい場所に応じて変えると良い(参考)$.get("{% url 'blog' %}") .done(function(data) { let parser = new DOMParser(); let doc = parser.parseFromString(data, "text/html"); let element = doc.getElementsByClassName("xxx") appendText(element[0].innerHTML); function appendText ( text ) { let element = document.getElementById( "yyy" ) element.insertAdjacentHTML("afterend", text ) ; }; })ちょっと色々試行錯誤して大変だった
-
DBにカラムを追加したよ!
ここを参照(リンク)DBに新しくカラムを追加したいと考え、試しに適当にフィールドを追加class Post(models.Model): title = models.CharField('タイトル', max_length=200) category = models.CharField('カテゴリ', max_length=200) text = models.TextField('本文') date = models.DateTimeField('日付', default=timezone.now) redate = models.DateTimeField('更新日時', auto_now=True)しかし、エラー出てしまうIt is impossible to add a non-nullable field 'category' to post without specifying a default. This is because the database needs something to populate existing rows. Please select a fix: 1) Provide a one-off default now (will be set on all existing rows with a null value for this column) 2) Quit and manually define a default value in models.py.どうやらnullにできないカラムは追加できないそうそこでnullでも良いカラムとして追加class Post(models.Model): title = models.CharField('タイトル', max_length=200) category = models.CharField('カテゴリ', max_length=200, null = True) text = models.TextField('本文') date = models.DateTimeField('日付', default=timezone.now) redate = models.DateTimeField('更新日時', auto_now=True) % python3 manage.py makemigrations 1.24.1 Migrations for 'blog': blog/migrations/0006_post_category.py - Add field category to post成功!!!
-
作成日時と更新日時を分けたよ!
ここに参照リンクclass BaseModel(models.Model): # auto_now_add はインスタンスの作成(DBにINSERT)する度に更新 created_at = models.DateTimeField('作成日時', auto_now_add=True) # # auto_now=Trueの場合はモデルインスタンスを保存する度に現在の時間で更新 updated_at = models.DateTimeField('更新日時', auto_now=True) deleted_at = models.DateTimeField('削除日時', blank=True, null=True) objects = BaseManager() all_objects = BaseManager(alive_only=False)上記のコードのようにDateTimeFieldの引数であるauto_now_addをTrueとすることで作成した日時を登録し、auto_nowをTrueとすることで更新日時を登録することができるようになったさらにフォントアイコンでカレンダーと更新を絵文字で表している
-
次にやりたいこと!
やりたいことリストブログの表示を変えたいカレンダーとブログを連携させたい(できそうにない)幅を制限してスクロールバーに連絡先をサイドバーにadminログインしてないとブログ投稿できないようにするスクロールと同時にフェードインサイドバーに人気記事を配置1. スクロールと同時にフェードイン=> 主にプロフィールのコンテンツをいくつかに分けたい=> ジャンルをポストするとジャンルのブログにリダイレクト制作物お気に入りの本、映画、ゲーム作った and 食べた料理時事ネタや最近気になったことなどの本当の呟き今後は各コンテンツのためのページを作っていく予定それぞれブログのジャンルにリンクを繋げてもいいし、そのためのページを新たに作ってもいい2. サイドバーに人気記事を配置サイドバーが現在寂しい状態になっているので充実させたいジャンル問わず、アクセス数の多い記事を表示する3. コンテンツの充実まだ本サイトが案内できるコンテンツが少なすぎる以下作ってみたいWebサイト家計簿商品紹介ゲーム
-
ちょっと画像のポストしてみる!
ここからテキストこれが見出しこれは中央揃えこれがリスト一つ目二つ目三つ目編集してみた
-
ついにエディタを実装した!!
これはサメです
-
DjangoのBlogを作成
BlogのメニューバーからTopとPostに遷移ができる仕様にした Top画面でBlogのリストを新しい順に見れるようにした。また、Postから新しく投稿できるようにした。 さらに、Top画面でblogの詳細、編集、削除が可能になっている UIも見やすい形に変更