django モデル リレーション

ポイント1 親モデルにリレーションを記載する

ER図

親のAK_wordが子モデルの、JP_wordsを持っている

f:id:happy_teeth_ago:20200322001328p:plain

Modelには小モデルを先に記載する

models.ForeignKey(User, unique=True)

この例は、Userの1レコードに対して1つの拡張レコードを対応付けています。 つまり、ユーザID(主キー)が確定すると、ひとつのレコードが決定することを意味します。

models.ForeignKey(User)

この例は、Userの1レコードに対して、複数の拡張レコードが対応付けられます。 つまり、ユーザID(主キー)が確定すると、複数のレコードが抽出されます。

models.ManyToManyField(User)

この例は、複数のUserレコードそれぞれに対して、複数の拡張レコードが対応付けられます

記載例 親Model のAK_words

class AK_words(models.Model):
    jp_word =  models.ForeignKey(JP_words, on_delete=models.CASCADE, null=True)
    en_word = models.ForeignKey(EN_words, on_delete=models.CASCADE,null=True)
    ak_word = models.CharField(max_length=255, null=False)
    renketu = models.BooleanField(null=True)
    pronounce = models.CharField(max_length=255, null=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
  
    def __str__(self):
        return self.ak_word
    class Meta:
        verbose_name_plural = "AK_word"   

Model記載例 子モデルのJP_words,EN_words

class JP_words(models.Model):
    jp_word = models.CharField(max_length=255, null=False)
    
    def __str__(self):
        return self.jp_word
    class Meta:
        verbose_name_plural = "JP_word"

class EN_words(models.Model):
    en_word = models.CharField(max_length=255, null=False)
    
    def __str__(self):
        return self.en_word
    class Meta:
        verbose_name_plural = "EN_word"  

View 記載例 index_akha.html

ループの場所だけ

    {% for ak_word in ak_words %}    
      <div class="word-card">
        <div class="word-container container p-4">
          <ul class="word-container-left">
            <li class="word"><a href="{% url 'show_akha_word' ak_word.id %}">{{ ak_word.ak_word }}</a></li>
            <li class="pronounsation">{{ ak_word.pronounce }}</li>
          </ul>        
          <ul class="word-container-right">

//モデルのリレーションが完了しているので、ak_word.ak_word で取り出せる
            <li class="word-meaning-japanese">{{ ak_word.jp_word }}</li>
            <li class="word-meaning-english">{{ ak_word.en_word }}</li>
          </ul>
        </div>
        <hr class="container">
      </div>      
    {% endfor %}   

当たり前のことだけど、日本語の記事が少なかったので書きました。

めでたし、めでたし

Swift UIImageViewにタップ判定を付ける(ボタン化)

このセルの丸印のイメージをクリックしたら、処理を書きたい

f:id:happy_teeth_ago:20200312172249p:plain

UITapGestureRecognizerのインスタンスを生成し、セットするだけ

//isUserInteractionEnabledをtrueにする StoryBoardからも設定できるが、間違いのもとなので、ソースでできるものはソースで設定する
        circleImage.isUserInteractionEnabled = true
        
//UITapGestureRecognizerのインスタンスを生成
        let tap = UITapGestureRecognizer(target: self, action: #selector(circleImageTapped))

//セットするだけ
        circleImage.addGestureRecognizer(tap)

このときの#selector(circleImageTapped))の関数を書いてあげる

//selectorで呼ぶ関数には@objcをつけること ob

    @objc func circleImageTapped(){

//ここはデリゲートのメソッドを利用している。
//好きなように記載して良い
        delegate?.circleImagetapped(todo: self.todo)
    }

めでたし、めでたし

firebase delete サブコレクション

firebaseのdeleteについての記事がなかったのでまとめ

まず、Firebaseはdeleteする際、サブコレクションがあっても、firebaseはカスケードしない。(小モデルも同時に削除しない)

よって、サブコレクションを削除し、その上で、コレクションを削除する必要がある。

まずdeleteの処理をみてみる

    //サブコレクションを含めたdelete処理 引数のcollectionにはサブコレクションを渡す
    func delete(collection: CollectionReference, batchSize: Int = 100, completion: @escaping (Error?) -> ()){
        collection.limit(to: batchSize).getDocuments{ (docset, error) in
            //error occured
            guard let docset = docset else {
                completion(error)
                return
            }
            guard docset.count > 0 else {
                completion(nil)
                return
            }
            //batchはトランザクションのようなもの
            let batch = collection.firestore.batch()
            //batchをforEachで回して、削除する
            docset.documents.forEach{
                //forEachの中では$0でアクセスする
                batch.deleteDocument($0.reference)
                }
            //batchをコミットして保存
            batch.commit { (batchError) in
                if let batchError = batchError {
                    completion(batchError)
                }else {
                    //commit時にエラーがなければ deleteを実行
                    self.delete(collection: collection, batchSize: batchSize, completion: completion)
                }
            }
        }
    }

この上で、親コレクション削除時に、このメソッドを呼び出す

下記の場合は、アラートでdeleteを選択したときに deleteを呼び出す処理

    //delete
        let deleteAction = UIAlertAction(title: "Delete", style: .default) { (action) in
            self.delete(collection: Firestore.firestore().collection(THOUGHTS_REF).document(thought.documentId).collection(COMMENT_REF), completion:  { (error) in
                if let err = error{
                    debugPrint(err.localizedDescription)
                }else{                    Firestore.firestore().collection(THOUGHTS_REF).document(thought.documentId).delete(completion: { (error) in
                        if let error = error {
                            debugPrint(error)
                        }else{
                            alert.dismiss(animated: true, completion: nil)
                        }
                    })
                }
            })
        }

Nosqlは, コレクションとドキュメントで成り立っていることがわかります。
この記事のなかで、わかりにくい点は、コメントいただけると助かります。 必ず修正します。

JAVA 格闘記-1

PrintWriterメソッドを利用するには、ライブラリーを読み込んでおく必要がある

/// import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; ///

そもそも、お前はなにをしているのか教えてほしい  Printwriter型とは? PrintWriter writer = response.getWriter();

で調べてみると オブジェクトの書式付き表現をテキスト出力ストリームに出力します。 らしい。 サーブレットでget postの時のレスポンス、リクエストをすべて書かないといけないようだ ?? コード量がRailsの10倍?

確かに疎結合になっていて、大規模開発にむいているとはいえ、?? 大企業以外では使わないとおもいつつ、そんなことはいまは関係なく、与えられた仕事をこなすのみ。

サーブレットを作成して、tomcatでみるとエラー utf-8 知らないって? ひどくない?

The method setCharacterEncording(String) is undefined for the type HttpServletResponse

でこの記事をみて ワークスペース全体をuft-8に変更

itsakura.com

今度はこんなエラー

javax.servlet.ServletException: Servlet execution threw an exception org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) で調査してみると、ビルドパスが2つあったようだ。 修正する。 ありがとうstackOverFlow みんなの血と汗が流れているんだね。

stackoverflow.com

ちなみに、スタックとは 「スタック車」の意味は雪やぬかるみなどに車輪を取られて動けなくなっている(立ち往生している)状況の車を指す言い方のこと オーバーフローとは オーバーフローとは、あふれ(る)、あふれ出たもの、という意味の英単語。ITの分野では、数値の計算結果がその格納領域に収まる範囲を超えること(算術オーバーフロー/桁あふれ)や、与えられたデータが多すぎて指定の領域に収まりきらないこと

つまり、問題にぶつかって、立ち往生して、動けなくなって、汗や涙があふれ出ることを言う。

その汗や涙のかたまりが、あのサイトなのね。と妙に納得してしまう。 だからうそだって、、、

f:id:happy_teeth_ago:20200309204811p:plain

f:id:happy_teeth_ago:20200309204823p:plain

ちなみに、内容を修正するとtomcat管理画面の再ロード ボタンを押す必要があるようだ。 f:id:happy_teeth_ago:20200309205132p:plain

かなり書く量が多いと思うJAVAでした。

WSGI互換アプリとは Python

WSGI互換アプリとは

Web Server Gateway Interface (WSGI; ウィスキー)の略です。 PythonとWEBサーバーをつなぐための、ソフトウエアです。

PHPはWEBサーバーのApachのモジュールです。 つまり発展型なので、そのままHTMLに組み込んで動きます。 f:id:happy_teeth_ago:20200307131715p:plain

それで昔はPHPは人気でした。

でもPythonはそうではありません。

WEBサーバーの上で動かさなくては、WEB上で見ることができません。

でPythonにはいろんなフレームワークがあります

DjangoやFlaskといったところが有名ですね。他にもたくさんあります。 で、そのたびにWEBサーバーとのやり取りをFastCGIやmod_pythonやAPIを使ってつなげてました。

f:id:happy_teeth_ago:20200307131940p:plain

めんどくさいね! となって、WEBサーバーとの共通のやり取りを決めたのが、WSGI(ウイスキー)です。

これがPythonのフレームワークとサーバーとの仲立ちをしてくれるのです。

おおまかな、ながれはこんなイメージ

1-ネットにつないでいるクライアントから、サーバーがリクエストを受け取る

2-サーバーはWSGIにオブジェクトを渡す

3-アプリケーションはWSGIから受け取った情報をもとに、レスポンスを返す

4-サーバーはWSGIから受け取ったレスポンスから、ネットに接続している クライアントにレスポンスを返す。

これが良かったので、Rubyとかでも似たような仕組みが提供されるようになりました。

Rack (Ruby Web Server Interface)と呼ばれています

ではまた

Docker まとめ

ここから読んでいくべし、コツコツだね knowledge.sakura.ad.jp

docker-composeとdockerの違いについて

docker-composeとは複数の環境をまとめて作るときに使う

マイクロサービスだね

docker-compose.yml ファイルに記載する

記載例

//version: 3と記載するのがポイント
version: '3'
services:
  web:
    build: .
    ports:
    - "5000:5000"
    volumes:
    - .:/code
    - logvolume01:/var/log
    links:
    - redis

//redis(NoSQL)のDBと一緒に利用することがわかる
  redis:
    image: redis
volumes:
  logvolume01: {}

もし docker-comoseで記載しないと、 docker run で2つ起動して上げれば良い

これは WordPress の例

docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:5.7
docker run --name some-wordpress -e WORDPRESS_DB_PASSWORD=my-secret-pw --link some-mysql:mysql -d -p 8080:80 wordpress

docker runはこのように書く optionイメージ を指定する必要がある。

docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

imageの一覧は

docker images

REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
python              latest              efdecc2e377a        2 weeks ago         933MB
mariadb             latest              1f9cfa8dc305        3 weeks ago         356MB
voting-app          latest              f8d9398120d6        2 months ago        74.7MB
<none>              <none>              fde4aa84a5d5        2 months ago        951MB
redis               latest              dcf9ec9265e0        2 months ago        98.2MB

ということは mariadbをrunしたいときは

--name はイメージに自分の名前をつけた わかり易い名前が推奨されている

docker run --name my_mariadb mariadb

しかしエラー

 You need to specify one of MYSQL_ROOT_PASSWORD, MYSQL_ALLOW_EMPTY_PASSWORD and MYSQL_RANDOM_ROOT_PASSWORD

パスワードをセットしなさいと言われる

docker run --name my_mariadb mariadb -e MYSQL_ROOT_PASSWORD=xxxxxx -d mariadb:3.1

しかしエラー 同じ名前のコンテナがあるよ。削除するかリネームしなさいと言われる Conflict. The container name "/my_mariadb" is already in use by container "36d38d69c7a7bf803a27916aca45f458d531e1a4a14770416343df330ff295c8". You have to remove (or rename) that container to be able to reuse that name.

コンテナ削除する まずはdockerのコンテナの確認

$ docker ps -a

CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                      PORTS               NAMES
36d38d69c7a7        mariadb             "docker-entrypoint.s…"   12 minutes ago      Exited (1) 12 minutes ago                       my_mariadb
3b70100d7faa        python:3.7.3        "/bin/bash"              29 hours ago        Exited (127) 29 hours ago                       suspicious_cerf
298c4e99003e        python:3.7.3        "python3"                29 hours ago        Exited (0) 29 hours ago                         objective_golick
1ad46aeb98e1        34a                 "python3"                29 hours ago        Exited (0) 29 hours ago                         strange_haslett
e61049880c06        python:3.7.3        "/bin/bash"              30 hours ago        Exited (0) 29 hours ago                         optimistic_brown
52051b32155e        python              "-i -t python:3.7.3 …"   30 hours ago        Created    

このID 36d.....を削除したい

docker rm 36d

これでなくなったので再度挑戦

エラー 基本に戻り dockerの本のチュートリアルをする

dockerを起動 名前はwebserver デーモンで ポートはホストが80 コンテナのポートは80 webserber はeNginX
$ docker run --name webserver -d -p 80:80 nginx

エラー docker: Error response from daemon: Ports are not available: listen tcp 0.0.0.0:80: bind: address already in use.

調べてみると -p オプションの左側がホストのポート 右側がコンテナのポート(ローカルPCで接続するところ)らしい

でもって、Nginxのコンテナ側のポートを変更する。

エラー コンテナのwebserverという名前は使われているらしい docker: Error response from daemon: Conflict. The container name "/webserver" is already in use by container "08cb6a6c8097d57d955fa664d7e979efd6ce1f72507888e4131fdfd99520121b". You have to remove (or rename) that container to be able to reuse that name.

確認してみる コンテナはps -a で確認できる

$ docker ps -a

CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                      PORTS               NAMES
08cb6a6c8097        nginx               "nginx -g 'daemon of…"   10 minutes ago      Created                                         webserver
8f01129608e1        mariadb             "docker-entrypoint.s…"   32 minutes ago      Exited (1) 32 minutes ago                       my_mariadb
3b70100d7faa        python:3.7.3   

あった、ということは container runは一発でコマンドを決めないと行けないらしい buildはしなくてよいのか?という疑問がのこる また run と container runの違いは?

調べたら同じだった。 dockerのバージョンによって、同じものになったようだ
現在では docker run を利用する

公式サイトの日本語訳ドキュメント

docs.docker.jp

このあたりが難しいところ 削除して// id は 08c

$ docker rm 08c

これで成功

$ docker run --name webserver -d -p 8080:8080 nginx

プロセスが動いているか確認 -d でデーモンオプションをつけたので、動いているので、確認できるはず

$ docker ps

動いていた!

CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                            NAMES
6108bcbd3f4a        nginx               "nginx -g 'daemon of…"   28 seconds ago      Up 27 seconds       80/tcp, 0.0.0.0:8080->8080/tcp   webserver

詳細を確認 statsと打たないといけない 統一してほしい!

$ docker stats webserver

stats — Docker-docs-ja 17.06 ドキュメント

CTR + C で抜けれる

CONTAINER ID        NAME                CPU %               MEM USAGE / LIMIT    MEM %               NET I/O             BLOCK I/O           PIDS
6108bcbd3f4a        webserver           0.00%               1.93MiB / 1.943GiB   0.10%               1.05kB / 0B         8.19kB / 0B         2

プロセスの停止

docker stop webserver

コンテナを再度削除して作り直す 成功!

$ docker run --name webserver -d -p 80:80 nginx

localhost:80でnginxが表示される

f:id:happy_teeth_ago:20200221010937p:plain 原因はMAMPが動いていたから

詳細はinspectで確認できる mariadbのバージョンが知りたかったので助かった。

docker image inspect mariadb

 "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
                "GOSU_VERSION=1.10",
                "GPG_KEYS=177F4010FE56CA3336300305F1656F24C74CD1D8",
                "MARIADB_MAJOR=10.4",

とりあえずここまで

WordPress nav 縦並び

こうしたい f:id:happy_teeth_ago:20200218160032p:plain

でもWordPressが出力するnavにはいろんなクラスが当てられる それがuser-agentという、ブラウザのデフォルト値に関係してしまうので、 CSSがうまく当たらない

WordPressにはこれだけ

    <div class="nav-menu">
      <div class="nav-sns">
        <a class="sns-link fa" href=""></a>
      </div>
      <?php wp_nav_menu(); ?>
    </div>

でHTMLを確認すると、いろんなクラスが出力されている

f:id:happy_teeth_ago:20200218160430p:plain

それに対してすべてCSSを当てていく

desiplay: flexで対応

もともとは

display: list-itemがあたっていた

@media screen and (max-width:600px) {
    .nav-menu {
        display: flex;
        width: 70%;
        height: 600%;
        background-color: #F49F0D;
        top: 78px;
        right: 0;
        opacity: 0.9;
    }
    .menu-main-container ul {
        display: flex;
        flex-direction: column;
    }
    .menu-main-container ul li {
        text-align: left;
        width: 100%;
        display: flex;
        flex-direction: column;
        z-index: 999;
    }
}