みずラテ

牛乳と水を2対1で。

【Rails】Could not find a JavaScript runtimeとなった時にやったこと

Railsアプリを初めて作成してRails sコマンドを満を辞して打ち込んでみたらしょっぱなからエラーが出て萎えました。
解決したので、以下に記載します。

事象

Rails sコマンドを打つと以下のエラーが出る。

Gem Load Error is: Could not find a JavaScript runtime. See https://github.com/rails/execjs for a list of available runtimes.

解決策

なんでも良いからインストール可能なExecJSランタイムをイントールする。
GitHub - sstephenson/execjs: Run JavaScript code from Ruby

  • therubyracer - Google V8 embedded within Ruby
  • therubyrhino - Mozilla Rhino embedded within JRuby
  • Node.js
  • Apple JavaScriptCore - Included with Mac OS X
  • Microsoft Windows Script Host (JScript)


こちらに記載されているうちのどれかをインストールすればいいみたいです。

というわけで、Node.jsをインストールしてみます。

Installing Node.js via package manager | Node.js

こちらに記載の通り、

curl --silent --location https://rpm.nodesource.com/setup_8.x | sudo bash -
sudo yum -y install nodejs

コマンドはこれだけ。
もう一回、rails sを打ってみたら・・・できた!


Ruby on Rails環境構築ガイド

Ruby on Rails環境構築ガイド

  • 作者:黒田 努
  • 出版社/メーカー: インプレス
  • 発売日: 2013/03/22
  • メディア: 単行本(ソフトカバー)

【Django】staticタグをblockに入れるとTemplateSyntaxErrorが出るのを解決する

base.htmlを使って、共通部分をまとめようとした矢先、個別ページでだけ読み込みたいjsファイルを読み込もうとしたらエラー・・・

その解決策です。

事象

個別ページにてjsファイルを読み込む

{% block extra_js %}
  <script type="text/javascript" src="{% static 'app/js/test.js' %}"></script>
{% endblock extra_js %}

すると・・・

f:id:taris777:20180310225425p:plain

シンタックスエラー!

エラー内容は、staticじゃなくてendblockを期待していますとのこと。僕はstaticを期待していますよ〜。

解決

もちろん先人がいました。
stackoverflow.com


という訳で、staticタグを使いたい場合は、個別ページ内で{% load staticfiles%}を読み込ませる必要があるとのこと。

{% extends "app/base.html" %}
{% load staticfiles%}

1行目がextendsなので、2行目に追記します。
試しに1行目に{% load staticfiles%}入れてみたら、「1行目はextendsを書けや!」ってエラーが出たのでやめておきましょう。

これで無事シンタックスエラーが出ずに意図した動作をするようになりました。


Django2.0でsocial-auth-app-djangoを使用してTwitter認証してみる

Djangoで作成中のアプリで、Twitterからユーザーログインをさせたいと思っており、調べてやってみました。

超参考にさせていただいた記事

いろんな記事を漁りましたが、こちらの記事をほとんどコピペでいけました。
qiita.com

環境

レンタルサーバーを借りており、以下の環境になります。

CentOS Linux release 7.4.1708
Python 3.6.4
Django 2.0.2
Apache 2.4.6

なお、今回Djangoプロジェクトはmysite、アプリ名はappsにしています。

Twitter Appsでアプリ設定

Twitter認証をするためには

  • Consumer Key
  • Consumer Secret

が必要となります。
そのため、https://apps.twitter.com/にアクセスして、Create New Appをクリックします。※当然ですが、ツイッターのアカウントが一つ必要です。
f:id:taris777:20180310203454p:plain

こんな感じに入力しました。後で変更も可能なので、ざっくり入れます。

作成が完了すると、Keys and Access TokensにConsumer KeyとConsumer Secretがありますので、メモしておきましょう。

social-auth-app-djangoのインストール

簡単にTwitter認証を実装できるsocial-auth-app-djangoを使用します。
virtualenvに入った上で、以下のpipコマンドにてインストール

pip install social-auth-app-django

Twitter認証キーの保存

mysite/mysite/configs/twitter.py

SOCIAL_AUTH_TWITTER_KEY = 'XXXXXX'
SOCIAL_AUTH_TWITTER_SECRET = 'XXXXXX'

Settings.py

追加する記述は以下。

mysite/mysite/settings.py

from mysite.configs import twitter

INSTALLED_APPS = [
    :
    'social_django',
]

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        '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',
                'social_django.context_processors.backends',
                'social_django.context_processors.login_redirect',
            ],
        },
    },
]

#ログイン未済の時のリダイレクト先
LOGIN_URL = '/login/'

###twitter認証関連
AUTHENTICATION_BACKENDS = [
    'social_core.backends.twitter.TwitterOAuth',
    'django.contrib.auth.backends.ModelBackend',
]

#Twitter認証のConsumer Keyなど
SOCIAL_AUTH_TWITTER_KEY = twitter.SOCIAL_AUTH_TWITTER_KEY
SOCIAL_AUTH_TWITTER_SECRET = twitter.SOCIAL_AUTH_TWITTER_SECRET

#OAuth認証後のリダイレクト先 トップページとか
SOCIAL_AUTH_LOGIN_REDIRECT_URL = '/top/'

トップページ、ログインページ、ログアウトページを作成

トップページはtemplates内に、index.html(url petternでtopという名前で後で呼び出す。)を作成。
同じくtemplates内にlogin.htmlと、logout.htmlを作成

/mysite/apps/templates/apps/index.html

<!DOCTYPE html>
<html lang="ja-jp">
<head>
  <title>Twitter認証</title>
</head>
<body>
  <br></br>
  <p>{{ user }}</p>
  <br></br>
</body>
</html>

userは認証後のTwitter IDを返します。 (views.pyに記述要、下に書きます。)

/mysite/apps/templates/apps/login.html

<!DOCTYPE html>
<html lang="ja-jp">
<head>
  <title>Rankin5</title>
</head>
<body>
  <button type="button" onclick="location.href='{% url 'social:begin' 'twitter' %}'">Twitter</button>
</body>
</html>

/mysite/apps/templates/apps/logout.html

<!DOCTYPE html>
<html>
<head>
 <title>ログアウト</title>
</head>
<body>
  <div>
    <p>
      ログアウトしました。
    </p>
    <p>
      <a href="/login"><button type="button" >ログインページへ</button></a>
    </p>
  </div>
</body>
</html>

login.html、logout.htmlは超適当です。

urls.pyの編集

/mysite/mysite/urls.py

from django.contrib import admin
from django.urls import include, path
from apps import views
import django.contrib.auth.views

urlpatterns = [
    path('', include('social_django.urls', namespace = 'social')),
    path('top/', views.index, name='index'),
    path('admin/', admin.site.urls),
    path('login/', django.contrib.auth.views.login, {'template_name': 'apps/login.html'}, name='login'),
    path('logout/', django.contrib.auth.views.logout, {'template_name': 'apps/logout.html'}, name='logout'),
]

views.pyの編集

/mysite/apps/views.py

from django.shortcuts import render,
from django.http import HttpResponse
from django.contrib.auth.decorators import login_required
from social_django.models import UserSocialAuth

# Create your views here.
@login_required
def index(request):
    user = UserSocialAuth.objects.get(user_id=request.user.id)
    pageDic = { 'user':user }
    return render(request, 'apps/index.html', pageDic)

user.idにはTwitterのIDが格納されており、これをindex.htmlで表示してみます。

migrate

social-auth-app-djangoをインストールした後、migrateしてDBに反映させる必要があります。
コマンドラインにて

python manage.py migrate

確認!

これで大丈夫なはずです。いろんな記事をみてようやくできるようになりました。

いろんなサービスで導入されているTwitterログインがちゃんと動くとなんかワクワクしますね〜

ちなみに、adminでユーザーテーブルをみてみるとログインしたTwitterアカウントの情報が登録されていました。

退屈なことはPythonにやらせよう ―ノンプログラマーにもできる自動化処理プログラミング

退屈なことはPythonにやらせよう ―ノンプログラマーにもできる自動化処理プログラミング

  • 作者:Al Sweigart
  • 出版社/メーカー: オライリージャパン
  • 発売日: 2017/06/03
  • メディア: 単行本(ソフトカバー)

【Django】Apatchを使ったらadmin画面のcssが読み込まれないを解決

Djangoの勉強用にレンタルサーバーを借りてデプロイしてみたものの、cssが読まれなかった時にやったこと。

環境

CentOS Linux release 7.4.1708
Python 3.6.4
Django 2.0.2
Apache 2.4.6

やったこと

静的ファイル(cssとかjsとか画像)の格納フォルダをsettings.pyに記述する。

末尾に以下を追記。

STATIC_URL = '/static/'

STATIC_ROOT = os.path.join(BASE_DIR, "static")

adminで使用されているcssを取得する

コマンドラインにて

python manage.py collectstatic

これにより、adminで使用されているcssが/static/admin/cssにまとめられます。

こんな感じ。

├── autocomplete.css
├── base.css
├── changelists.css
├── dashboard.css
├── fonts.css
├── forms.css
├── login.css
├── responsive.css
├── responsive_rtl.css
├── rtl.css
├── vendor
│   └── select2
│       ├── LICENSE-SELECT2.md
│       ├── select2.css
│       └── select2.min.css
└── widgets.css

admin画面では、ソースをみてみると、base.cssだったり、login.cssが使用されている模様。

追記2018/03/10 httpd.confにaliasを設定する

aliasの設定が必要みたい

末尾に以下を追記しました。
staticのフォルダがある場所を適宜指定してください。

/etc/httpd/conf/httpd.conf

###Alias###
Alias /static/ /var/www/environments/mysite/static/

<Directory /var/www/environments/mysite/static>
    Require all granted
</Directory>

これで大丈夫なはずです。

【Django】Apatchのhttpd.confの設定をしてみる

レンタルサーバーやクラウドサーバーにデプロイする際、wsgiを使ってDjangoとApatchを繋げる必要がある。

環境

CentOS Linux release 7.4.1708
Python 3.6.4
Django 2.0.2
Apache 2.4.6

wsgi_moduleの格納場所を把握しておく

私の場合は、virtualenv (今回はmyenv)上にpython3.6をインストールしていますので、

$ find ~~/myenv -name 'mod_*.so'

で.so拡張子のファイルのパスを探しておきます。

httpd.confの設定

私の環境では、/etc/httpd/conf/httpd.confに格納されていました。

末尾に以下を追記

###Django settings###
#Load Module 先ほど探した.so拡張子のファイルを指定
LoadModule wsgi_module /var/www/environments/myenv/lib/python3.6/site-packages/mod_wsgi/server/mod_wsgi-py36.cpython-36m-x86_64-linux-gnu.so

#WSGI settings
WSGIPythonHome /var/www/environments/myenv
WSGIScriptAlias / /var/www/environments/mysite/mysite/wsgi.py
WSGIPythonPath /var/www/environments/mysite:/var/www/environments/myenv/lib/python3.6/site-packages

Apatchの再起動を忘れずに。

$ sudo systemctl restart httpd.service

これで無事設定ができ、Djangoのサイトが表示されました。



1日で理解するDjango超基礎入門

1日で理解するDjango超基礎入門

JavaScriptでチェックボックスのチェックされた順番を取得してみる

CheckBoxのチェックされた順番を使用してやりたいことがあったので、JavaScriptを勉強してみました。

ちなみに今回初めてJavaScriptに触れた超初心者なので、悪戦苦闘でした。

しかも全然情報が出てこないので、困りました。

備考

画面上には取得した順番は表示されませんが、HTMLソースをみるとチェックボックスのclassが変化します。

また、参考にさせて頂いた元のソースでは、一度チェックしてしまうとclassの中身が消えないようだったので、ちゃんと消えるようにアレンジしてみました。

勉強用にコメントも付与しています。

JavaScriptソース

(function() {//無名関数 bodyの一番下で読み込まないとエラー
    var input = document.querySelectorAll(".items input");
    var orders = [];
    addSelectedOrder (input, orders);
})();

function addSelectedOrder (input, orders) {

  //チェックされたチェックボックスを全部消すButton(Class btnClearAll)を用意
  var tgt = document.querySelector(".btnClearAll");
  tgt.addEventListener("click", function() {
    orders = [];
    for(var i = 0; i < input.length; i++) {
      input[i].checked = false;
    }
    tgt.disabled = "disabled";
  },false);

  //ここからチェックボックスの処理
  for(var i=0; i< input.length; i++) {//object一つ一つにEventListenerを付与
    input[i].addEventListener("change", function(e){
      if(e.target.checked) {
        orders.push(e.target.id);//クリックされたらorderの末尾に追加
      } else {
        //チェックが外れたら外れたものをordersから削除
        for (var k = 0; k < orders.length; k ++) {
          if(orders[k] == e.target.id) {
            orders.splice(k, 1);
          }
        }
      }

      //最新化されたordersを元にclassの中身を変更
      if (orders.length == 0){//ordersに何も入っていなければclassを全て削除
        for(var f =0; f <input.length; f++){
          input[f].className = "";
        }
      }else{//入っていればinputを全部舐めてclassを追加・削除[f:id:taris777:20180303002410p:plain]
        for(var l =0; l <input.length; l++) {
          for(var j=0; j< orders.length; j++) {
            if (input[l].id == orders[j]) {
              input[l].className = "order" + (j + 1);
            }else{
              input[l].classList.remove("order" + (j + 1))
            }
          }
        }
      }

      //ordersのlengthがinputのオブジェクト数と同じであればenabled,それ以外はdisabled
      if (orders.length == input.length){
        tgt.disabled = "";
      }else{
        tgt.disabled = "disabled";
      }

    }, false);
  }
}

HTML側

<button type="submit" class="btnClearAll" disabled>Clear</button>

<div class="items">
    <input type="checkbox" id="ck01">
    <input type="checkbox" id="ck02">
    <input type="checkbox" id="ck03">
    <input type="checkbox" id="ck04">
    <input type="checkbox" id="ck05">
</div>

いちばんやさしいJavaScriptの教本 人気講師が教えるWebプログラミング入門(「いちばんやさしい教本」シリーズ)

いちばんやさしいJavaScriptの教本 人気講師が教えるWebプログラミング入門(「いちばんやさしい教本」シリーズ)

  • 作者:岩田宇史
  • 出版社/メーカー: インプレス
  • 発売日: 2017/03/27
  • メディア: 単行本(ソフトカバー)