diadia

興味があることをやってみる。自分のメモを残しておきます。

ノードを追加する

ベース記事

DOM操作について
Javascriptメモ

ノードを追加するやり方

やりたいイメージ:例えばカラの

<ul></ul>

があるとする。ここにリストタグを追加するということをやりたい。リストタグはエレメントというノードの一つである。
だからノードを操作するコードが分かれば追加することも当然できる。

参考例文

<!DOCTYPE html>
<html lang="utf-8">
<head>
	<meta charset="utf-8">
	<title>ノード追加</title>
</head>
<body>
	<!--ノードを追加するプログラムを書く-->
	<ul id="blank_list">
	</ul>

	<input type="button" value="追加" onclick="adding();">

	<script>
		function adding(){
			var content_list = document.createElement("li");
                        var text = document.createTextNode("やさいおいしい");
			content_list.appendChild(text);
			blank_list.appendChild(content_list);				
	}

 	</script>
</body>
</html>

ノード追加に必要なメソッド

  1. createElement()
  2. createTextNode()
  3. appendChild()

ForeignKeyフィールドのcreate

ベース記事

インスタンスのForeignKeyフィールドにNoneデータ入力しcreateするとき

foreignkeyにdjangoオリジナルのUserモデルを登録して、views.pyにてインスタンスを作成するコードを書いてみた。このとき困ったことを書く。

models.pyにて

class Hoge(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE, blank=True, null=True)

views.pyにて

def yeah(requesrt):
    if request.user.is_authenticated and request.user is not None:
        hoge_obj = Hoge.objects.create(user = request.user )
    else:
        hoge_obj = Hoge.objects.create(user = None )
    render(request, home.html)

このようなものを書く。

この状態だとエラーが出てしまう。原因がオリジナルのモデルにあるのか、Hogeモデルにあるのかわからなかったが、結論はHogeモデルに原因があった。ForeignKeyフィールドでnullの情報を入力するには、CASCADEではなくSET_NULLにしなければならない。これで hoge_obj = Hoge.objects.create(user = None )が問題なく動く。
https://docs.djangoproject.com/ja/2.1/ref/models/fields/#arguments

ForeignKeyのSET_NULLを使うときのメモ

products = models.ForeignKey(Product, on_delete=models.SET_NULL)としてmakemigrationsしてもうまく行かなかった。エラーの詳細は以下のようになっていた。

ERRORS:
product_sets.Set.products: (fields.E320) Field specifies on_delete=SET_NULL, but cannot be null.
	HINT: Set null=True argument on the field, or change the on_delete rule.

null=Trueにすれば大丈夫とのことだったので、外部キーのすべてのフィールドにnull=Trueしてみた。それでも同じエラーが出てしまった。
どうやらこれはForeignKey(on_delete=models.SET_NULL)としているところに、null=Trueを追加でセットすればエラーを解消することができる。

tagをキーに要素を取得する

ベース

  • Javascriptメモ

  • DOM操作について

  • 基本的な使い方

    idをキーにする場合にはgetElementById()を使っていたけど、tagをキーにする場合は少し違う。ただほぼ同じ。getElementsByTagNameを使う。elementsでsが必要なこと、Nameを加えることに注意して記述したい。あとはこいつの戻り値はHTMLCollectionというもので配列(pythonでいえばlist)のようなものだ。要素を表示させるにはfor構文を使う必要がある。

    この点はBeautifulSoup4とは違う点だと思う。

    例文

    <body>
    	<!--divタグを取得するプログラムを書く-->
    	<div>要素1</div>
      <p>要素2</p>
      <div>要素3</div>
      <span>要素4</span>
      <div>要素5</div>
    
      <input type="button" value="取得" onclick="print();">
    	<script>
    
      function print(){
        var tags = document.getElementsByTagName("div");
        console.log(tags);
        for (var i=0; i < tags.length ; i++){
          console.log(tags[i].innerText);
              }
         }
    
      </script>
    </body>
    

    プロパティについて

    javascriptではプロパティがある。上記で言えばlengthがプロパティだ。

    lengthを使う際にlistA.length()とやってしまったのだけれども、正しくはlistA.lengthだ。

    このプロパティにはinnerTextもある(上記参照)。なんかよくわかんないけどInnerTextではないらしい。

    javascriptの法則がまだつかめない。。。

    idをキーに要素を取得する

    ベース記事

  • DOM操作について

  • Javascriptメモ

  • 本題

    例文

    <p id="test">この要素を取得したい</p>
    <input type="button" onclick="print();">
    
    <script>
    function print(){
        var ele = document.getElementById("test");
        console.log(ele);
        console.log(ele.innerText);
    }
    </script>
    

    まず最初にonclickってのがあるけど、これはhtmlのものなのか、それともjavascriptのものなのかって疑問。これはどうやらjavascriptのもの。
    じゃあonclickはなんなのかってことだけど、イベントハンドラーの一つらしい。イベントハンドラーとは、イベントが起きたときに何らかの処理をさせるもの。

    onclik="print();"

    onclickがイベントで、""で囲まれたものが処理になる。この場合クリックというイベントが起きたとき、print()という処理を起こす。

     var ele = document.getElementById("test");

    documentはhtmlをオブジェクト化するためのものだと思われる。そのオブジェクトのメソッドがgetElementById()。

    セミコロンについて

    ベース記事

    Javascriptメモ

    一体どんなときに必要なのか?

    javascriptを勉強していると;を文末に書くことが度々ある。
    これは必ず文末で必要となるわけでもないらしい。
    頭がごちゃごちゃする

    ルール(仮説)

    原則として文の終わりにセミコロンを付す。
    例外は制御構文で文末はセミコロンを必要としない。
    例外の例外でdo...while文末では必要とする。
    ただまだ文を定義していない。。。

    条件分岐

    ベース記事

    Javascriptメモ

    種類

    • if/else if/else
    • switch

    if/else if/else

    構文

    if(条件式){
    条件式がTrueのときの処理
    }else if(条件式){
    条件式がTrueのときの処理
    }else{
    上記に当てはまらないのときの処理
    }

    if文のみの場合、while文に似ている気がする。条件式が成立したときに行う処理をループさせるか否かの違いだけで構文はほぼ同じ(条件式にも;を必要としていない点も類似している。)。ifをwhileに書き換えるだけ。else ifについてはpythonとは異なる。pythonの場合はelifを使う。

    switch

    同値演算向けの条件分岐構文。同値演算によって複数の条件分岐がある構造を作る際にelse if を多用する方法だと、ごちゃごちゃして読みづらい。それをすっきりさせ、読みやすくなるのがswich構文である。

    構文

    switch(値){
    case 値候補その1:
     実行文;
     break;
    case 値候補その2:
     実行文;
     break;
    default:
     実行文;
     Break;
    }

    switch(値)の値が値候補に合致しているか照らし合わせ、合致していたら何かしらの処理が行われる。break;は他の値候補を照らし合わせる条件と区別するために必要になる。

    例文

    switch(値){
    case "きゅうり" :
     console.log(”値段は80円”);
     break;
    case "トマト":
     console.log(”値段は300円”);
     break;
    default:
    console.log(”値段は確認してください”);
     Break;
    }
    
    

    繰り返し処理

    種類

    1. for文
    2. while文
    3. do while文

    for文

    構文

    for (初期化文; ループ継続条件; 増減式){
     繰り返し実行したい処理
          }

    増減式には;を必要としない。書いたらunexpected token ; のエラーが出てしまうので注意。

    変数iの値を1から3まで出力するプログラム

    for (var i=1; i<=3; i++){
    console.log(i);
          }

    while文

    構文

    while (条件式){
     条件式がTrueのとき実行したい処理
          }

    注意すべき点は条件式の中に;は不要だということ。for構文とは全然似ていないこと。while構文は繰り返しのfor構文とは構造が似ていないけど、条件分岐のif構文と似た構造である。参考:条件分岐

    変数iの値を1から3まで出力するプログラム

    var i = 1 ;
    while (i <= 3){
    console.log(i);
     i++;
          }

    do while文

    構文

    do{
    条件式がTrueのとき実行したい処理
    }while (条件式)
    

    注意すべき点は条件式の括弧外に;を要すること。相違点として最低でも一回は処理を実行し、実行後条件式に照らし処理が行われるか分岐する

    変数tの値を1から3まで出力するプログラム

    var t = 1 ;
    do{
    	console.log(t);
    	t++;
    }while(t <= 3);

    webアプリケーション作成の整理

    求められるもの

    webアプリケーション作成に求められることはなにか?まずウェブアプリにどのような機能があるか知っていること。次にその機能を実現するにはどうすればいいか分かっていること。djangoのドキュメントを読むと知識は少しづつついてくるけど、実際どんな知識がどのように組み合わさって使うのか理解しづらい。知識の運用という側面からあ整理することは必要なので、機能とその実現方法を軸にまとめる。また抽象度を高めた状態にすることも求められる。

    機能と実現方法

    カスタムマネージャーとカスタムクエリについて

    models.query.QuerySetの継承の意義

    クエリセットをマネージャを継承したものでクエリセットを設定することができる。この場合に定義した関数は重ねて使用することが出来ない。

    イメージで言えば、Blog.objects.filter(active=True).filter(featured=True)

    これが出来ない。
    カスタムマネージャで定義した関数を重ねて使用できない。重ねて使用するためにカスタムクエリという手続きがある。これはmodels.query.QuerySetを継承することで重ねて使用することができるようになる。

    pythonのgetとdjangoのgetは異なる

    pythonのgetとdjangoのgetは異なるので注意

    よく使われるgetにdjangopythonで別物だと気づいたのでメモしておく。

    とりあえずドキュメントをそれぞれ置いておく。

    get() を用いて1つのオブジェクトを取得する

    https://docs.python.jp/3/library/stdtypes.html#dict.get

    簡単に違いを説明すると、自分が慣れ親しんだdjangoのManagerのget()メソッドは、getの対象が一つに絞れないとき、または対象が存在しないときにはエラーが返されます。

    一方pythonのget()も辞書型データのメソッドだけれども、getの対象が存在しないときにはエラーは返されない。返されるのはNoneか自分で設定したもの。メソッドgetはManagerか辞書型データかによって異なる。思い返してみればManagerを使うとdict型のようなものが返される、といった表現をdjangoドキュメントで読んだ記憶がある。これは辞書型と言い切ってしまうと、Managerのメソッドではなくなってしまう問題を回避するためだと納得した。

    クエリセットやデータオブジェクトをいじる際にNoneが返されたり、デフォルトの値が出て来るような状況だとデータはごちゃごちゃになってしまうから。
    うまくできているなあと思う。

    データベースとクエリセット間の操作手続き

    関連記事

    データベースとクエリセット間の操作手続き

    データベース、クエリセット、データオブジェクトの3要素が登場する。
    そしてデータベースとクエリセット間の操作手続きとクエリセットとデータオブジェクト間の操作手続きが存在する。
    データベースから望んだ条件でフィルターをかけた結果がクエリセット。
    クエリセットはデータオブジェクト(レコード、row)の集まりともいえる。

    データベースとクエリセット間の操作手続きを焦点にメモしてみる。
    ドキュメントでは以下になる。
    QuerySet API reference | Django documentation | Django


    noneについて

    効果と用途

    none() は、何のオブジェクトも返さないクエリセットを生成し、結果にアクセスしたときに何のクエリも実行されなくなります。qs.none() クエリセットは EmptyQuerySet のインスタンスです。

    >>> Entry.objects.none()
    <QuerySet []>
    >>> from django.db.models.query import EmptyQuerySet
    >>> isinstance(Entry.objects.none(), EmptyQuerySet)
    True

    webアプリケーションから検索をかけた結果、一致するものがなかったときにnoneを使うと良い

    templateまとめ

    関連記事

    本題

    どうなったらtemplateが読み込めるのか

    作業中にテンプレートの読み込みエラーが出ることが多い。エラーが出るのは作業中のコードと記述しなければならないコードに乖離が生じているからである。エラーコードをすばやく対処するにはあるべきコードとエラーが出たコードとの乖離を見つけなければならない。それはどのような原理で動いているか知っておくことが重要である。

    templateが動く仕組み(仮説)

    どうなったら読み込みができるのか

    1. どのテンプレートを使うか規定しているか?
    2. 規定したテンプレートを探すための環境が設定されているか?

    1.どのテンプレートを使うか規定しているか?

    使用するテンプレートは、views.pyにて規定する。renderを使う場合にはreturn renderの第2引数で規定する。renderを使わない場合にはListViewやDetailViewを使う場合で、template_nameによって規定する。


    2.規定したテンプレートを探すための環境が設定されているか?(仮説)

    すべて理解しているわけでもないし、理解していることをすべて書く余裕が無いので根本的な仕組みについて書く。

    適切にテンプレートエンジンを設定しているか?

    テンプレートエンジン設定

    どのテンプレートを使うかは1で規定する。規定されたテンプレートはプロジェクト内のファイルから探し出す必要がある。このテンプレートファイルを探し出すものをどうやらテンプレートエンジンと呼んでいるようだ。このテンプレートエンジンは'BACKEND'で規定されている。ではどこからテンプレートを探させるかを設定するのが、'DIRS': と'APP_DIRS': Trueである。HOWの部分である。

    この2つは別物であって両方を設定することも、片方だけを設定することもできる。
    'DIRS':
    にディレクトリを記述することでそのディレクトリから探してテンプレートを見つける。'APP_DIRS': Trueと設定されている場合、アプリケーションからテンプレートを探すように動いてくれる。'APP_DIRS': Trueの場合アプリケーション内にテンプレートを探し出されない場合がある。それはsettings.pyにアプリケーションとして登録していないアプリケーションからテンプレートを探す場合である。アプリケーションとして登録していないところからテンプレートを探すのは不可能なので、その場合はアプリケーションであることを登録すること。それはINSTALLED_APPSに記述すれば良い。