Make組ブログ

Python、Webアプリや製品・サービス開発についてhirokikyが書きます。

Djangoでdjango-hijack-adminをカスタムユーザーモデルと使うときのハマりポイント

django-hijack-adminDjangoのカスタムユーザーを併せて使うとき、Adminサイトへの登録でハマるので書いておきます。

django-hijackとは、Admin画面から別ユーザーのセッションを乗っ取れるライブラリーです。 個別のユーザーで問題が発生しているときに状態を確認したり、ローカルで動作確認するときに複数アカウントを切り替えやすくなったりで便利になります。

github.com

django-hijack-adminはdjango-hijackの機能をAdmin画面から使いやすくしてくれるものです。 かなり小さい実装なので、ライブラリー自体は参考実装にして自分で書いてしまっても十分なものです。

カスタムユーザーをAdminに登録するときにハマる

カスタムユーザーモデルを作って拡張したModelAdminを登録しようとするときに、django-hijack-adminをINSTALLED_APPに入れているとハマります。 具体的にはカスタムユーザーモデル用のModelAdminの内容がAdmin画面に反映されなくなります。

from django.contrib import admin
from django.contrib.auth.admin import UserAdmin as AuthAdmin

from . import models


@admin.register(models.User)
class UserAdmin(AuthAdmin):
    # デフォルトのUserAdminに独自の拡張をする
    fieldsets = AuthAdmin.fieldsets + (("Additional", {"fields": ("icon",)}),)

ここでは fieldsetsicon というフィールドを追加していますが、Admin画面に反映されなくなります。

django-hijack-adminは独自のUserAdminを登録する

原因は django-hijack-admin も独自のUserAdminを登録しようとすることです。 django-hijack-adminは「Hijack」するためのボタンを追加するために、 auth.admin.UserAdmin を拡張したクラスをAdminに登録します。 Userモデルに対応するModelAdminをunregisterして登録するので、カスタムユーザー用に自身のUserAdminを登録しても無駄になります。

if hijack_admin_settings.HIJACK_REGISTER_ADMIN:
    UserModel = get_user_model()
    admin.site.unregister(UserModel)
    admin.site.register(UserModel, HijackUserAdmin)

github.com

解決策

以下の用に3つ設定します

  1. settingsに HIJACK_REGISTER_ADMIN = False を設定する
  2. UserAdminでHijackUserAdminMixin をMixinする
  3. list_displayに 'hijack_field' を足す

このようになります。

from hijack_admin.admin import HijackUserAdminMixin


@admin.register(models.User)
class UserAdmin(AuthAdmin):
    ...
    list_display = AuthAdmin.list_display + ('hijack_field',)

カスタムユーザーを使うときの設定方法は READMEに書かれています 。 ですがdjango-hijack-adminがデフォルトで、元の動作を音もなく書き換えるので少し気づきにくいと思います。

もしdjango-hijack-adminを使っていて「おかしいな」というときは疑ってみてください。

他のおすすめ記事

blog.hirokiky.org

Vue.js+VueRouterでページの離脱、再読込、別ルートへの移動時に警告を表示する

ページの離脱時に警告を表示するには、 beforeunload イベントを使えば簡単にできます。 ですが、Vue.jsでVueRouterを使っている場合、ページの移動で beforeunload イベントは発生しません。 理由はブラウザーの画面自体が切り替わっていないからです(ページの遷移はVueRouter, つまりJavaScriptが同一の画面内で制御している)。

WordPressやDropboxPaperも、ページ離脱時には confirm() やモーダル表示を使ってページ遷移時に警告を表示しています (もちろんbeforeunload時の警告も併用しています)。

Vue.js + VueRouterでページ離脱、再読込時に警告を表示する

以下のように beforeunload を使えば良いです(クロスブラウザー対応どうこうはうまく書き換えてください)。

  methods: {
    handler (event) {
      event.returnValue = "Data you've inputted won't be synced"
    }
  },
  created () {
    window.addEventListener("beforeunload", this.handler)
  },
  destroyed () {
    window.removeEventListener("beforeunload", this.handler)
  }

vue-prevent-unload というライブラリーもありますが、小さすぎる実装なので参考にするだけで良いでしょう。 必要なコンポーネントに処理を書くか、独自のvue-prevent-unloadのようなコンポーネントをプロジェクト以下に置いておけば十分です。 例えば以下のようなVueコンポーネントStopUnload.js としておくなどです(あくまで参考実装です)。

export default {
  name: 'StopUnload',
  props: ["stop"],
  render: () => null,
  methods: {
    handler (event) {
      if (this.stop) {
        event.returnValue = "Data you've inputted won't be synced"
      }
    }
  },
  created () {
    window.addEventListener("beforeunload", this.handler)
  },
  destroyed () {
    window.removeEventListener("beforeunload", this.handler)
  }
}

ページ遷移時にも警告をする

ただこれだけではVueRouterによるページの遷移時に警告が表示されません。 以下のようにVueコンポーネント内に beforeRouteLeave を書けばVueRouterでのページ移動を検知できます。

beforeRouteLeave (to, from, next) {
  let answer = window.confirm("Data you've inputted won't be synced, OK?")
  if (answer) {
    next()
  } else {
    next(false)
  }
}

router.vuejs.org

ただしこの場合、VueRouterの routes に登録されているVueコンポーネントに上記の処理を書いてください(Viewとしてのコンポーネントに書く)。 VueRouterに直接関係しないコンポーネントでは beforeRouteLeave は呼び出されません。なので上記で例示したStopUnoadコンポーネントbeforeRouteLeave を書いても機能しません。

windowのbeforeunloadと、beforeRouteLeaveを使うことで、Vue.js+VueRouterでSPAを作っているときもページの離脱時に警告を表示できます。

他のオススメ記事

blog.hirokiky.org

Vue.jsでAPIにないフィールドはモデルにも作らないプラクティス - モデルとViewModelの区別の仕方

前回の記事はこちらです。先に読まれておくことをオススメします。

blog.hirokiky.org

モデルに置く値、ViewModelに置く値の区別をつけよう

Vue.jsで開発するときに、モデルに置くべき値とViewModelに置くべき値を区別できればかなりキレイに設計できます。 区別の判断は少し難しいですが、「バックエンドのAPIで保存・読み込みする値のみモデルで管理する」と考えてみると勘所が分かりやすいです。 バックエンドのAPIなどが無い場合は、例えばlocalStorageに保存する値をモデルとすると良いでしょう。

前提: 記事の読み込み、保存する画面で説明します

説明のためのプロジェクトの説明をします。

記事(Post)の編集をする画面をVue.jsで作り、バックエンドのAPIからデータを取得、保存するとしましょう。 ここではAPIから以下のレスポンスがあると想定します。

{
    "id": 1,
    "title": "タイトル",
    "body": "本文"
}

この場合、APIのレスポンスはモデルで管理すべきです(参考: JavaScript (ES6) でAPIから受け取ったデータをモデルに入れるプラクティス - Make組ブログ

export class Post {
  constructor (id, title, body="") {
    this.id = id
    this.title = title
    this.body = body
  }
}

読み込み、保存する処理は以下のようにします

import axios from 'axios'

import { Post } from './api'


export async function getPost (id) {
  let res = axios.get(`/posts/${id}/`)
  return new Post(res.data.id, res.data.title, res.data.body)
}


export async function patchPost (post) {
  let res = axios.patch(`/posts/${post.id}/`, {body: post.body})
  post.body = res.data.body
  return post}

単純にVueコンポーネントを作る

さて、ここでどのようにVueコンポーネントを書くべきでしょうか? 一番単純に作ると以下のようになります。

<template>
  <div v-if="post">
    <textarea v-model="post.body"></textarea>
    <button @click="save">Save</button>
  </div>
</template>

<script>
import * as api from './api'


export default {
  name: 'Post',
  data () { return {
    post: null
  } },
  methods: {
    async save () {
      await api.patchPost(this.post)
    }
  },
  async mounted () {
    this.post = await api.getPost(1)
  }
}
</script>

モデルに書く?

ここで「値が変更されていないときは Save ボタンを disabled にしたい」としましょう。 この場合、値が変更されたことを検知するのはどこが良いでしょうか?

せっかくJavaScriptclass が使えるので、以下のように getter, setter で書くとカッコイイ気がします。 が、結論から言うとあまりオススメしません。

export class Post {
  constructor (id, title, body="") {
    this.id = id
    this.title = title
    this._body = body
    this.changed = false
  }

  get body  () {
    return this._body
  }

  set body (value) {
    this._body = value
    this.changed = true 
  }
}

この場合、Vueコンポーネントは以下のようになるでしょう。 changed = false にする処理や、 :disabled="!post.changed" が足されています。

<template>
  <div v-if="post">
    <textarea v-model="post.body"></textarea>
    <button @click="save" :disabled="!post.changed">Save</button>
  </div>
</template>

<script>
import * as api from './api'


export default {
  name: 'Post',
  data () { return {
    post: null
  } },
  methods: {
    async save () {
      await api.patchPost(this.post)
      post.changed = false
    }
  },
  async mounted () {
    this.post = await api.getPost(1)
  }
}
</script>

この程度ではあまり問題になりませんが、 1つのコンポーネントでしか使わないような処理や状態をモデルに入れるとモデルが肥大化していきます 。 変更の検知をする部分はVueコンポーネントに書くほうが良いです。

changedAPI(データの読み込み・保存)には関係しない。モデルに書くべきでは無いかも?」と考えてみてください。

Vueコンポーネントに書こう

モデルの定義は元に戻して(getter, setterを消して)、Vueコンポーネントを以下のように書いてみましょう。 「変更されたかどうか」という状態をVueコンポーネントに持つようになっています。

<template>
  <div v-if="post">
    <textarea v-model="body"></textarea>
    <button @click="save" :disabled="!changed">Save</button>
  </div>
</template>

<script>
import * as api from './api'


export default {
  name: 'Post',
  data () { return {
    post: null,
    body: ""
  } },
  methods: {
    async save () {
      this.post.body = body
      await api.patchPost(this.post)
    }
  },
  computed: {
    changed () {
      return this.body != this.post.body
    }
  },
  async mounted () {
    this.post = await api.getPost(1)
    this.body = this.post.body
  }
}
</script>

textarea ではVueコンポーネントbody を編集するようにして、 post.body は触れないようにしています。 「変更されたかどうか」は changed というcomputedで計算しています。

changeddata で管理するフラグにしても良いです。

  methods: {
    update (value) {
      this.body = value
      this.changed = true
    }
  }

こう変更することで、モデルとしたPostクラスでは changed という実装が無くなりました。 「記事」として管理すべき値はモデルに、「編集する」という責任範囲で管理すべき値はコンポーネントに置きましょう。 そうすることで、モデルの実装を減らして、細かく分けられたVueコンポーネントに実装を分散できます。

もし複数コンポーネントで状態を共有するのであれば、Vuexを使えば済みます。 もちろん今回の説明も「こっちが正解」というわけではありません。ですが、「全てモデルに書く」、「全てViewコンポーネントに書く」のでなく、適宜コンポーネントを分離して値を管理する場所を分けることで、より良い設計が自然とできるようになるでしょう。

他のオススメ記事

blog.hirokiky.org

ここ1年以上同じ服を着たので服装まとめ

f:id:hirokiky:20190819140615j:plain
クローゼットの中

この1年半ほど、自分の服装を固定化しています。 平たく言うと、毎日同じものを着るということです。 ミニマリストしぶ という人に影響を受けてやり始めたんですが、、意外とかなり快適で長いこと続いています。 極端に全く同じというわけではなくて、基本的なプリセットを用意しておこうという程度の話です。

同じ服を着るにあたって「自分にとって最高のもの」をまず見つけるのに苦労したので、今ようやく落ち着いてきたのでまとめておきます。

追記

もうこの服装が3年続いています。 靴だけAllbirdsになったし、ワイシャツはあんまり着ていないけど。

Tシャツ

ヘインズのプレミアムジャパンフィットが一番コスパ最強だった

検討した無地Tシャツ

無地Tシャツは他にもヘインズBEEFY、ヘインズジャパンフィット、ZOZOのTシャツ、 THREE DOTSのジョシュ を試したが、プレミアムジャパンフィットが最強。 品質でいうならTHREE DOTSのジョシュをオススメしたいけど、1枚で1万円もするので2枚しかもっていない。

ズボン

ジーパンをはくならEDWINが一番良い(と昔から思っている)。 買うときはジーンズメイトにでも行って、裾上げしてもらうことを強くオススメします。

手頃な値段でシッカリしていて、かつ日本人的にはきやすいのでとても良い。 僕は細身なのでスリムなモデルを選んでいるが、それでもダボつくくらいなのでこれがちょうど良い。 EDWINの402を3本買って回しています。

ZOZOジーパン、ユニクロジーパンを試したけど、生地がチープであまり好きになれなかった。

ワイシャツ

とはいえTシャツ以外のときもあります。

最近試しに買ってみたのだけど、 ワイシャツにおいて鎌倉シャツは本当に一番コスパが良かった 。 ワイシャツ着るときはVネックの白いシャツを着るか、素肌にそのまま着ています。

www.shirt.co.jp

リネンとかオックスフォード地だとジーパンにもあわせられるので良い。 鎌倉シャツ、買いな!(鷹宮リオン風)

上着

上着は基本的に好きなものを着ている。 three dots か、 nano universe か、無印か、ユニクロのジャケットかパーカーを着ている。

f:id:hirokiky:20190819140706j:plain
ジャケット

無印のパーカーは着心地も良いのに安いので一番オススメしたい。

f:id:hirokiky:20190819140645j:plain
無印のパーカー最強

靴下

大したこだわりはないけど、安い中ではこれが一番良かった。

少し薄手なので、シッカリした靴下をはきたい人には向いていない。 僕は、薄いくらいのほうがゴワゴワしなくて好きなのでこれにしている。

オススメあれば教えてください

下着

試した中では一番良かった。

無印で売っている綿のボクサーも良い。 でもAmazonでポチれるのはやはり便利なのでコレが良い。

オススメあれば教えてください

履きやすさではNewBalanceのMRL996が一番良かった。

とはいえMRL996は店頭のみのモデルを買った(茶色のスウェード地のモデルは店頭にしかなかった)。

あとは NIKEのタンジュンを最近買ったのだけど、コスパ面ではタンジュンが単純に最高すぎるのでオススメしたい 。 作りはかなりチープだけど、5000円とは思えない履き心地。

サンダルの場合はビルケンシュトックが一番良い。 ビルケンシュトックは元BeProud CTOのshinにオススメしてもらって買った。

もともと合成皮のモデルを買っていたが、履きつぶしたときに本皮のモデルにした。

時計

僕は時計が好きなので色々な種類を持ってつけていたい。 機械式でコスパ最強で使いやすいのはこのSEIKO SARB033だった。

クォーツならこれがオススメ

個人的に一番好きなのはCA-53W

理想を言えば欲しい時計はゴマンとある。ムーンウォッチかモナコポルトギーゼかカラトラバがほしいです。

完成イメージ図

この写真の一番右の人。

blog.hirokiky.org

無印のパーカーを愛する人。 自分の全身が映っている写真ってなかなかなかったので、ギターの練習用に自分の姿を撮ったものです。

f:id:hirokiky:20190819144005p:plain
誰かさん

頑張って練習してますが、少し覗き込みすぎで姿勢が良くないです。

まとめ

  • 無地Tシャツはヘインズのプレミアムジャパンフィットが良い
  • EDWINは良い
  • 無印のパーカーは良い
  • 鎌倉シャツは良い
  • NIKEタンジュンは良い

靴下とか下着とか、まだ完璧に満足してるわけではないので、似たことやってる人は情報ください

他のオススメ記事

blog.hirokiky.org

JavaScript (ES6) でAPIから受け取ったデータをモデルに入れるプラクティス

フロントエンドのJavaScriptで、バックエンドのAPIからの結果をモデルに入れるプラクティスについてまとめます (より良い方法があったら教えてください)。

まず、以下のようなレスポンスがAPIからあると想定します。

{
    "id": 1,
    "username": "hirokiky",
    "last_name": "Kiyohara",
    "first_name": "Hiroki"
}

データをそのまま使いまわすのはイマイチ

このデータを受け取ったままの状態でJavaScript上で使うのはイマイチです。

import axios from 'axios'

async function initialize () {
  let res = await axios.get("/user")
  let user = res.data

  ...  // 以降、userを使いまわす
}

理由としてはいくつかあります。

  • APIが snake_case で返すと、JavaScript内でも user.last_name とかく必要がある
    • user.lastName のように camelCase にしたい
  • APIの実装が変わるとアプリケーションの深い部分で影響を受けることがある
    • データを受け取った段階で検知したい
  • user などのデータに振る舞いを持たせられない
    • user.fullName のような処理を持たせたい

モデルを定義する

モデルを定義しておくと良いでしょう。 一旦、このように定義しました(models.js に書く想定です)。

export class User {
  constructor (id, username, lastName="", firstName="") {
    this.id = id
    this.username = username
    this.lastName = lastName
    this.firstName = firstName
  }

  get fullName () {
    return this.lastName + this.firstName
  }
}

これをAPIからデータを受け取ったときに使います。 ついでに、APIアクセスをまとめたJavaScriptファイルにまとめておいたほうが良いです (api.js に書く想定です。バックエンドのAPIの名前が明確ならその名前でも良いでしょう)。

import axios from 'axios'

import { User } from '@/models'

export async function getAuth () {
  let res = await axios.get("/user")
  return new User(
    id=res.data.id,
    username=res.data.username,
    lastName=res.data.last_name,
    firstName=res.data.first_name
  )
}

元の処理では上記の getAuth を使うと良いです。

import { getAuth } from '@/api'

async function initialize () {
  let user = await getAuth()

  ...  // 以下 user を使いまわす
}

ここで少し面倒な点がいくつかあります

  • new User(...) 時に、APIからのレスポンスを1つ1つ入れるのが面倒
  • constructor の定義が面倒くさい
    • Pythonのdataclassのように書きたい

簡単にモデルを書けるようにする

実験的な実装なので信用しないでください

以下のようにモデルの基底クラスを定義しておきます。

class Model {
  static  fields () { return {} }

  constructor(options={}) {
    var v
    for (let [key, value] of Object.entries(this.constructor.fields())) {
      if (options.hasOwnProperty(key)) {
        v = options[key]
      } else {
        v = value
      }
      this[key] = v
    }
  }
}

各モデルのクラスでは以下のように使います。 fields メソッドには各フィールドの定義を書きます。

export class User {
  static fields () {
    return {
      id: null,
      username: "",
      lastName: "",
      firstName: ""
    }
  }
}

fields からは {フィールド名: デフォルト値} というオブジェクトを返します。 fields がstaticメソッドなのは、ES6にはクラス変数が無いから、仕方なくこう定義しています。

User は以下のように作ります。

new User({id: 1, username: "hirokiky"})

APIのデータからモデルを作る

ここで、 Model にメソッドを追加して、APIから受け取ったデータを使ってインスタンスを簡単に作れるようにしましょう。

function makeSnake (s) {
  return s.replace(/(?:^|\.?)([A-Z])/g, function (x,y){return "_" + y.toLowerCase()}).replace(/^_/, "")
}

function copyFields (fromObj, toObj, fields, fromSnake=false, toSnake=false) {
  for (var field of fields) {
    var value, fromFieldName

    if (fromSnake) {
      fromFieldName = makeSnake(field)
    } else {
      fromFieldName = field
    }

    if (fromObj.hasOwnProperty(fromFieldName)) {
      value = fromObj[fromFieldName]
    } else {
      value = null
    }

    if (toSnake) {
      toObj[makeSnake(field)] = value
    } else {
      toObj[field] = value
    }
  }
  return toObj
}


class Model {
  // ...

  static fromAPIData (options, initial={}) {
    return new this(copyFields(options, initial, Object.keys(this.fields()), true, false))
  }
}

こうしておくと、以下のように snake_case でUserのインスタンスを作成できます。

User.fromAPIData({id: 1, username: "hirokiky", 'last_name': "Kiyohara"})

API呼び出し時にも簡単にインスタンスを作れるようになりました。

import axios from 'axios'

import { User } from '@/models'

export async function getAuth () {
  let res = await axios.get("/user")
  return User.fromAPIData(res.data)
}

まぁ、 getAuth 関数内で snake_case から camelCase に変換して new User(toCamelCase(res.data)) としたほうが良いかもしれませんが。

まとめ

  • フロントエンドのJavaScriptを書くときもモデルを定義したほうが良いよ
  • モデルの定義を毎度書くのは面倒だから、楽できると良いよね

今後、各ModelクラスをJsonSchemaから定義したり、バリデーションを追加できるようにすると良さそうです。 でもそこまでいくとライブラリーがありそうなので探すと良さそうです。良いのがあったら教えてください。

他のオススメ記事

blog.hirokiky.org

blog.hirokiky.org

なぜ「やりたいことが見つからない」のか?単に「見つけ方」を知らないから

f:id:hirokiky:20190816171318p:plain

ちょっと、大きなテーマを扱います (大げさな話しなので間違いがあれば教えてください)。

  • 「やりたいことが見つからない」
  • 「自分は何をやっても中途半端になる」
  • 「好きなことも、すぐに飽きてしまう。楽しくなくなる」

そういった悩みは、僕を含めて、多くの人が持っていると思います。 でもそう思う理由は「やりたいことの見つけ方」を知らないからです。

僕は最初から「やりたいこと」なんて無かった

僕について少し自己紹介かねて個人的な話をします。

僕は今、BeProudという会社でプログラミング、プロダクト開発を仕事にしています。 PyQ というWebサービスを4人の小さいチームでゼロから企画して、今も開発をしています(最初はharu、kamekoと僕で企画を練って、僕が開発でした。初期はちょいちょいshinが関わってくれて、4人で作りました)。

僕は12歳のときからプログラミングをしているので、周りからは「子供のときから好きなことを見つけられた人」と言われたりします。 でも12歳のときから今のように「Webサービスを作るのは本当に楽しい」、「Webサービスで良いものを作りたい」とは思っていませんでした。

さいころの僕は「新テーマパーク」や「デザエモン」、「RPGツクール」という「何かを作るゲーム」が好きでした。その延長線上で、C言語でプログラミングを初めたのがキッカケでした。 最初は分からないことがたくさんあって「そこまで楽しくないな」、「イライラするな」と思ったのを覚えています。でも確かにあったのは「知りたい」という気持ちでした。

その後もたくさんのことがあって、僕は自然と「やりたいことの見つけ方」を見つけて生きてこれたように思います。ですが、単にラッキーだっただけだと思います。

というわけで、今日は、その「やりたいことの見つけ方」を話します。

まず「やりたいこと」とは何か

多くの人や世間の常識は「やりたいことを見つけなさい」、「自分が楽しいことをしていれば自然と成功する」と言います。

そう言われると「いや、僕にはそこまでやりたいことがないな」と思ってしまいます。 でも落ち込む前に聞いてください。これはまず 「やりたいこと」という語の定義が曖昧なのが問題です

まず、「やりたいこと」の定義を分割して考えましょう。「やりたいと思う」という「動機」には3つの種類があると僕は考えています。

  • レベル1: 外部から自分に向かう動機(アウトサイドイン)
    • 何かを知りたい
    • 何かをできるようになりたい
    • こんな人になりたい
    • これはできそうだな
  • レベル2: 自分から自分に向かう動機(インサイドイン)
    • この行為をしていると純粋に楽しい
    • 自分の喜ぶことをしたい
  • レベル3: 自分から外部に向かう動機(インサイドアウト
    • 誰かのためになろう
    • 世の中をこう変えよう
    • みんなで一緒に楽しもう

これを やりたいことの3レベル と呼びましょう。

世の中でよく言われる「やりたいことを見つけなさい」という場合は、やりたいことの3レベルのうち、レベル2の「インサイドイン」の動機を指していることが多いです。ですがこの レベル2やレベル3の動機を初めから持つことは難しいです

動機は、以下のようにレベル1からレベル3に積み上がっていくものと思ってください。

f:id:hirokiky:20190816171318p:plain
やりたいことの3レベル

下のレベルほうが、「やりたいこと」の中では親しみやすいものです。

まずレベル1の動機を見つけよう

f:id:hirokiky:20190816171348p:plain
やりたいことレベル1

多くの「やりたいことなんて全く無いよ」という人は、要するに初めから「レベル2の動機が心に存在しなければならない!」と勘違いしている人です。

やりたいことが見つからない人は、まずは「知りたい」、「できるようになりたい」 ことから始めましょう。

  • 何か知りたいことはありませんか?
    • プログラミングって何か気になるなぁ
    • イギリスにいってみたいなぁ
    • 喋るのは割とできるな
  • 何かなりたい姿はありますか?
    • プログラミングができるってカッコイイな
    • 英語がしゃべれるようになりたいな
    • YouTuberっていいなぁ

「やりたいこと」というと難しいですが、「知りたい」「なりたい」は誰にでもあるはずです(英会話スクール、ファッション雑誌、旅行ガイドが巷に溢れているということは、誰しもが持っている感情というのは明らかです)。

その 知りたいこと、なってみたいことを具体的にやってください 。「まず初めてみる」ことは絶対に可能です。プロになろうといきなりしないでください。純粋に、自分の知的好奇心や憧れを満たすためにまずやってみましょう。

でも感情というのはロウソクの炎のようなもので、大切にしないとすぐにかき消えてしまいます。 例えば他人からの否定、自分自身での否定、常識やマナーといった横風に吹かれてすぐに消えてしまいます。

「知りたいな」「なりたいな」「ワンチャンできそうだな」と思ったら、その炎を守ってください。そして消えてしまう前にすぐに行動してください。今すぐに。そして小さい成功体験を味わってください。

動機の炎をレベル2に大きくする

f:id:hirokiky:20190816171406p:plain
やりたいことレベル2

もしレベル1の動機があれば、ぜひ何も考えずにそれに打ち込んでください。 今の世の中、情報は腐るほどあります。知れないということは絶対にありません。

何かをしている間に、「なるほどコツを掴んだぞ」、「何だかできるようになってきたぞ」という発見があるでしょう。これが身になる瞬間(レベル2になれる瞬間)です。 ここで初めて、あぁ、これが「やりたいこと」、「好きなこと」、「楽しいこと」なんだなと気づけます。 やるだけで自分の楽しい範囲でうまくいくので、とても楽しいです。

ですが「身になる瞬間までは、ぶっちゃけ楽しくない」と思っていたほうが安心です。多くの人はここを誤解していて 「自分に向いていることなら何をどうやっても快楽的に楽しいんだろう」と思いすぎ です。 でもやってればいつか「身になる瞬間」がきます。身になれば、あとは自然とこなしているだけで楽しくなります。例えばギターである程度の曲を引けるようになった段階や、多少の英会話ができるようになった段階、プログラミングで思ったプログラムをある程度書けるようになった瞬間です。楽しいですよ。

僕が12歳からプログラミングを初めて、「僕はプログラミングが好きなんだ」とちゃんと思えるようになったのは18歳か、19歳あたりだと思います。

やりたいことを人生(レベル3)にする

f:id:hirokiky:20190816171419p:plain
やりたいことレベル3

ここまでくれば自分の「やりたいこと」を使って、他の人に価値を提供したり、自己表現ができるようになります。 もし何かを生み出したい、役に立ちたい、驚きを与えたい、誰かを笑わせたい、一緒に楽しいことをしたい、世の中を変えたいと思えるなら、それがあなたの本当に好きなことです。

例えば「こんなWebサービスを作って、多くの人にプログラミング言語Pythonを学んで欲しい」と思ったり、「こんな新しい音楽を作って、世の中の人をあっと言わてやる」と思ったり、「この旧来以前の業界を変えるような会社を作ってやろう」と思ったり、「みんなでこのトピックで集まって楽しいことをしたい」と思ったりです(単に「世界を変える人間になってやるぞー」と思っているのは、レベル1の動機です。具体的に、公約としてコミットメントできるレベルの動機と思ってください)。

今までやってきたことがレベル3の動機に繋がれば、本当にラッキーです。 「好きなことをしていたら、お金は後からついてくる」という人の「好きなこと」とはこのレベル3の動機のことです。 自分の好きなことを通して、人々に価値や喜びを提供したり、信頼関係を気づいていける状態のことです。

今の僕はPyQを作ったり、 dig-en を作ったり、 DjangoCongress JP を主催したり、さらに新しいプロジェクトを立ち上げていたりします。学生のころからSinboon、PushosuやKarmaidなどを作ってきましたが、本当の本当に人に喜ばれるプロダクト・サービスを作れるようになったのはごく最近のことです。PyQを始めたのは25歳か26歳のころなので、12歳にプログラミングを始めてから15年近く経ちました。

やりたいことを見つけよう

やりたいことが見つからないなら、まず気になること、知りたいこと、なりたいことから初めてみましょう。

最近は情報が多すぎるので、「やりたいこと」のハードルが高すぎる気がしています。まず気になることを何でもやるのが良いと思います。

その「動機」の炎をゆっくり育てていけばいいと思います。

これが僕なりの「やりたいことの見つけ方」です。ぜひ何か気になることから始めてみましょう。

何か聞きたいこと、知りたいこと、ツッコミたいことがあれば、何でもはてブブコメか、 @hirokiky へのリプライに書いてください。 僕もたくさんの意見を聴きたいので、ぜひ書いてください。

他のオススメ記事

blog.hirokiky.org

雑談: (昔の僕の)非モテの僻みは、たまに優しいヤンキーと同じ思想だった?

僕は高専卒のわりと非モテ系な人間なので、学生のころは「外見ばかりで判断しやがって中身が大事なんだ」とよく思っていた。

でも、そうやって「外見は汚くても自分の心はキレイだ」という思想は、「たまに優しいと全肯定されるヤンキー」の存在を良しとしてしまうんじゃないかと考えた。

そして、モテ・非モテって二元論はバカでしかないので、及第点を目指せば良いんだと思うようになった。

たまに優しいヤンキーなぜか全肯定される

いつも人を困らせて素行の悪いヤンキーがいるとしよう。でもそのヤンキーがたまに良いことをすると異常に評価されることはないだろうか。平たく言うと映画版ジャイアンだ。正直、僕は好きではない。ガラの悪い人が道端の猫に話しかけているとか、そういうのもズルい。 だって、ズルくないですか?その数%だけで全体が良い人だと評価されるなんて!(むしろ積極的に活用していきたい)

でも例えば、見た目が不潔でヨレた着こなしをして、顔とか眉毛の手入れとかを全くしない人がいたとしよう。 その人がキレイな心だけで100%良い人だと評価されたいと願うのは、たまに良いことするヤンキーの振る舞いを是とするのと同じことだと思う。 まぁ、たまに優しいヤンキーが良いと思うなら良いが、映画版ジャイアンを「ズルい」と思うなら、真の心の良さだけで評価されようとしている僕もズルいということになる。

コスパが良い

僕もあるとき「見た目をある程度整えるのは、信頼が買えてコスパが良いな」と思うようになった。

及第点で良いんだなとやっとわかった。たぶんモテ・非モテ論争は誰かが得するための仕組みなんじゃないかな? 僕はそこから眉毛を整え、顔の髭を剃り、産毛を剃り、風呂に入り、サッパリしたそれなりな身だしなみに切り替えた。その後は、ついでに服を考えるのが面倒なのでほぼ同じ服を着るようにした。

一つ言うと、オシャレしようとすると逆にダサくなる。やめとこう。 ここで「『それなりな身だしなみ』が難しいんじゃないか!」と怒る人は安心していただきたい。ぜひ、MBさんのファッションを参考にしてほしい。 ユニクロから始められる、「詰まったヒット」くらいを打てるようになる方法が学べる。

www.neqwsnet-japan.info

それで総額でかかるのはいくらだろう。たかだか1万円かくらいだ。ブルーレイを少し我慢すれば済むんだから安いものだ。 「ブサメンだからそもそもダメ」というのは違うと思う。それなりにキレイにして、真摯さが伝われば十分だと思う。モテる必要は全然ないし、普通になろう。あとは好きなもの着ればそれで良い。

まぁいきなり大きく変わる必要はないけど、ちょっとキレイにするくらい安いものなので、ぜひやってみるとどうだろう? (でもぶっちゃけクラッチバッグは僕はダサいと思うぞ、MBさん)。

この本を買ってください。僕も読みました。 ここから買ってくれると僕のRedbull代になります。