VC++のコンパイル警告

昔のVC++プロジェクトを、Visual Studio2019に取り込んだが、古いソースで、最新ではコンパイル警告がいくつか出る。

(コンパイラバージョン別の警告の一覧)

https://docs.microsoft.com/ja-jp/cpp/error-messages/compiler-warnings/compiler-warnings-by-compiler-version?view=msvc-160

だいぶ昔のソースを取り込んだのもありも、VSも以前よりチェック項目が増えていて結構な数の警告が出た。警告は無視しても動くが、警告を直していくことでいい勉強になることもある。

C4589:Constructor of abstract class ‘type’ ignores initializer for virtual base class ‘type’

 抽象クラス  ’VBase2 ’のコンストラクターは仮想基底クラス 'VBase’ を無視します

これは、仮想基底クラスVBaseを継承する抽象VBase2のコンストラクター定義で、書かなくていい VBase の定義を書いていたということ。抽象クラスを継承した抽象クラスだけど、何となく実装クラスのイメージでコンストラクターのコードを書いて警告が出たということでした。

class VBase
{
public:
	VBase(const int param);
	virtual ~VBase() {};
	
	virtual void mustOverrideMethod() = 0;

private:
	int _param;
};

VBase::VBase(const int param)
{
	_param = param;
}

class VBase2 : public virtual VBase
{
public:
	VBase2(const int param);
	virtual ~VBase2() {};

	virtual void mustOverrideMethod2() = 0;
};

VBase2::VBase2(const int param) : VBase(param)  // ← C4589警告
{
}

この抽象クラスVBase2のコンストラクターの実装が以下。

(誤)
VBase2::VBase2( const int param ) : VBase(param )  // ← C4589警告
{
}

(正)
VBase2::VBase2( const int /* param */ ) 
{
}

VBase2自体も抽象クラスで、ここでVBaseのコンストラクターの引数を定義しても意味は無く、実装クラスで定義する必要があるということ。

class ImplVBase2 : public virtual VBase2
{
public:
	ImplVBase2(const int param);
	virtual ~ImplVBase2() {};

	virtual void mustOverrideMethod() {};
	virtual void mustOverrideMethod2() {};
};

ImplVBase2::ImplVBase2(const int param) : VBase2(param), VBase(param)   // ← ※ここでVBase(param) 定義
{
}

VBase2のコンストラクターで引数を持つ必要がそもそもないということになるが、例えばユーザークラスを実装していて、キーがユーザーNoでそれを引数としている場合には、やはり引数があった方が見た目が良いように個人的には思えるので残した。

UserImpl::UserImpl(const int userNo) : UserBaseEx( userNo ), UserBase( userNo )

↓ 

UserBaseEx::UserBaseEx( const int /* userNo */)  ※このクラスだけ、userNoが無いのもなんか違和感が・・・・

↓

UserBase::UserBase( const int /* userNo */)

C4996 :コンパイラの警告(レベル3)

古いソースのため、推奨されない関数を使っているということで、以下のメッセージが出た。

'inet_ntoa': Use inet_ntop() or InetNtop() instead or define _WINSOCK_DEPRECATED_NO_WARNINGS to disable deprecated API warnings

inet_toaが非推奨で、inet_ntop()かInetNtop()を使えとのことで、inet_ntopに変えたが

https://docs.microsoft.com/en-us/windows/win32/api/ws2tcpip/nf-ws2tcpip-inet_ntop

ws2tcpip.hをインクルードしても、「inet_ntopが定義されていない」というエラーが・・・・

ws2tcpip.h の中を見てみると、バージョンチェックではじかれているよう。

https://docs.microsoft.com/ja-jp/cpp/porting/modifying-winver-and-win32-winnt?view=msvc-170

古い古いVSで作ったもので、stdafx.hの中のバージョン定義が古すぎのため、inet_ntopの対象外となっていた。astafx.hの中のバージョン定義を変えることで解決。

Debug版のプロジェクト設定の問題

古いプロジェクトから自動移行した場合に、以下の警告が出るので設定変更が必要。

LNK4075:リンカー ツールの警告

/EDITANDCONTINUE は /SAFESEH の指定によって無視されます

追加になったデバッグ用の設定が自動でされていないため、プロジェクトの[プロパティ]-[詳細]で、[デバッグ ライブラリの使用]を「はい」に設定。

D9305:コマンド ラインの警告カー ツールの警告

オプション 'Gm' の使用は現在推奨されていません。今後のバージョンからは削除されます。

プロジェクトの[プロパティ]-[C/C++]-[コード生成]で、[最小リビルドを有効にする]を「いいえ」に設定。

その他

アプリケーションの画面

作成されたアプリケーションの画面サイズが小さくなってしまうので、 プロジェクトの[プロパティ]-[マニフェストツール]-[入出力]で、[DPI認識]を「なし」に設定。

DjangoのTips

自分のためのメモ。リンクは、基本的にDjangoの3.1ドキュメント。

(Django公式)

Django3.1 ドキュメント

Django3.1 APIリファレンス

(Djangoソース)

https://github.com/django/django/tree/master/django

(DBに関してはこっち)

1.テンプレート

1.1 include

テンプレートの中から、テンプレートを呼び出せる。

https://docs.djangoproject.com/ja/3.1/ref/templates/builtins/#include

方針としては、templates/app/commonというようなフォルダを作って共通のテンプレート部品を置いて、includeして利用する。

1.2 オーバライドしたblockで、基底の呼び出し

https://docs.djangoproject.com/ja/3.1/howto/overriding-templates/#extending-an-overridden-template

以下を呼び出せばいい。注意点として基底側で、「static」を使っている場合、「load static」を呼ばないとエラーになる。

{{ block.super }}

1.3 改行のBRタグへの変更

「linebreaksbr」というフィルタを使えばいい。

https://docs.djangoproject.com/ja/3.1/ref/templates/builtins/#linebreaksbr

{{ value|linebreaksbr }}

1.4 フィルタ

「|」は、テンプレート言語のフィルタというもの。

https://docs.djangoproject.com/ja/3.1/ref/templates/language/#filters

組み込みフィルタリファレンス

自分でフィルタを登録することもできるらしい。

https://docs.djangoproject.com/ja/3.1/howto/custom-template-tags/#writing-custom-template-filters

Djangoのアドオンのhumanizeも使える。

https://docs.djangoproject.com/ja/3.1/ref/contrib/humanize/

桁区切りを入れる、intcommaだが、自分のアプリではうまくいかずにソースを見たところ、言語設定の関係がうまく動作しなかったよう。とりあぜう、第二引数をFalseを設定して回避できた。

1.5 footerのコピーライトの年号

Visual Studioのサンプルだと、ビューで年を変数にしてテンプレートに渡しているが、テンプレートの「now」を使えばわざわざ渡す必要は無くなる。

https://docs.djangoproject.com/ja/3.1/ref/templates/builtins/#now

コピーライト部分は、以下のような感じで書けばいい。

<p class="text-center">
 &copy; gijutsu.com 2019-{% now "Y" %}
</p>

1.6 メニューのアクティブ制御

共通メニューの、ページ毎での”active”制御を、どう実装するか。以下の回答が参考になる。

https://stackoverflow.com/questions/46617375/how-do-i-show-an-active-link-in-a-django-navigation-bar-dropdown-list?answertab=votes#tab-top

ドキュメントはこちら。

ResolverMatch

urls.pyのurlpatternsで定義したnameでチェックすることで実現。

    {% with request.resolver_match.url_name as url_name %}
      <ul class="navbar-nav mr-auto">
        <li class="nav-item {% if url_name == 'home' %}active{% endif %}">
          <a class="nav-link" href="{% url 'home' %}">Home</a>
        </li>
        <li class="nav-item {% if url_name == 'contact' %}active{% endif %}">
          <a class="nav-link" href="{% url 'contact' %}">お問合せ</a>
        </li>
      </ul>
    {% endwith %}

2.セッション

https://docs.djangoproject.com/ja/3.1/topics/http/sessions/

具体的なViewでの使い方は、以下。

ビューでセッションを使う

3.モデル

https://gijutsu.com/2021/01/12/django-db/

バリデータの設定は以下に

https://docs.djangoproject.com/ja/3.2/ref/validators/

4.ビュー

ビルトインのクラスベースビュー API

1)ログインが必要なページ

ログインが必要なページについては、以下でログインしていない場合、ログイン画面にリダイレクトさせる。

login_required デコレータ

クラスビューを使っている場合は、MixInを使う。

LoginRequired mixin

5.フォーム

https://docs.djangoproject.com/en/3.1/topics/forms/

Form fields

ビルトインの Field クラス

モデルからフォームを作成する

6.役に立つパッケージ

※国内限定なら以下で十分

https://qiita.com/xKxAxKx/items/86bdf0bc4c7dc9ee65d9

7.ログ

https://docs.djangoproject.com/ja/3.1/topics/logging/#examples

8.URL ディスパッチャ

https://docs.djangoproject.com/ja/3.1/topics/http/urls/

コントローラの中で、URLを取り出す場合は、reverseを使う。

https://docs.djangoproject.com/ja/3.1/topics/http/urls/#reverse-resolution-of-urls

from django.urls import reverse

:

return HttpResponseRedirect(reverse('news-year-archive', args=(year,)))

9.メッセージ

https://docs.djangoproject.com/ja/3.1/ref/contrib/messages/

10.リクエストとレスポンスのオブジェクト

https://docs.djangoproject.com/ja/3.1/ref/request-response/

(処理後に呼び出しページに戻る例)

    return HttpResponseRedirect(request.META['HTTP_REFERER'])

同じnameの入力値を配列で受け取るのは以下。

https://docs.djangoproject.com/ja/3.1/ref/request-response/#django.http.QueryDict.getlist

Django開発ではまったこと

はじめてのDjango開発で、ひっかかったところ、はまったところの記録。

1)拡張テンプレート側のstaticのロードエラー

ベース側で「{% load static %}」しているので、なんとなく拡張側は要らないような気でいたら、以下エラーが出た。

Invalid block tag on line **: 'static', expected 'endblock'. Did you forget to register or load this tag?

拡張ファイル側でも「static」を使う場合は、「{% load static %}」する必要がある。

※「{{ block.super() }} 」した場合に、その中で「static」を使われている場合も、「{% load static %}」する必要がある。

2)Django Debug Toolbarが表示されない

Visual Studio からDjangoの開発用サーバーで実行すると、ツールバーが表示されない。Chromeのエラーを見ると、toolbar.jsの読み込みがはじかれている。

Failed to load module script: The server responded with a non-JavaScript MIME type of "text/plain".

とりあえず、setting.pyに以下を追加することで解決。

# For Debug Toolbar
if DEBUG:
    import mimetypes
    mimetypes.add_type("text/javascript", ".js", True)

3)Visual Studioのサンプルの文字コード

サンプルのDjangoのWebアプリのテンプレートの文字コードがSJISのようで、修正しながら、テンプレート内に日本語を書くと、実行時にエラーになった。他のエディタで一度UTF-8で一度保存してから修正する必要あり。

4)アドオンhumanizeのintcomma

自分のプロジェクトの言語設定の問題か、桁区切りをつけるintcommaがうまく動作しなかった。

https://docs.djangoproject.com/ja/3.1/ref/contrib/humanize/#intcomma

ソースを見ると、第二引数で言語設定を無視できるよう。

(GitHubソース)contrib/humanize/templatetags/humanize.py

以下のように、Falseを設定することで回避できた。

<div class="text-right>{{ report.count_visit|intcomma:False }}</div>

Visual StudioでDjango

Visual Studio Community 2019 で、Djangoで開発を始めたので、作業メモ。とりあえず、Microsoftのドキュメントからチュートリアルを参考に。

(MS公式)チュートリアル: Visual Studio での Django Web フレームワークの概要

チュートリアルは前の2017バージョンだけど参考に、軽く動かしながら、実際に作りたいものに変えていく。

【主な変更作業】

Webプロジェクト テンプレートから、自分用に変更していく。

(MSサイト)手順 4: Django Web プロジェクト テンプレートを使用する

1 Viewの変更

まずは見た目からということで、自分の作りたいページ構成に変えていく。

  • app/templates/layout.html:タイトル、メニュー、フッター等を修正
  • app/views.py:templateの中で表示するデータを修正

2 DB変更

DBを、業務で使っているPostgreSQLに変更する。使うドライバとしては、以下のPsycopgがよく使われているらしいので、それを使うことにする。

(Psycopg公式)Psycopg – PostgreSQL database adapter for Python

1)ドライバのインストール

psycopg2パッケージをインストールする。インストール方法は以下ページを参考に。

(MS公式)[Python 環境] ウィンドウ タブ リファレンス

ソリューションエクスプローラーの[Python環境]>[Env]を右クリックして[Pythonパッケージの管理]からも行ける。

2)DB接続の設定

以下ページを参考に、settings.pyのDATABAESを修正。

(django公式)djangoドキュメント – Settings -DATABASES

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'mydatabase',
        'USER': 'mydatabaseuser',
        'PASSWORD': 'mypassword',
        'HOST': '111.111.111.1111',
        'PORT': '', # 空白の場合はデフォルト
    }
}

3)既存の業務DBの定義を取り込む

以下を参考に、models.pyに既存DBの定義を追加する。

(Djangoi公式)レガシーなデータベースと Django の統合

ソリューションエクスプローラーから[Python環境] を右クリックして、[すべてのPython環境を表示]して、実行環境を選択して、下の[PowerShell で開く]。

PowerShellで、以下コマンドを実行。

$ python manage.py inspectdb

以下のエラーが出て、うまく定義を作成できないよう。

Unable to inspect table 'XXXXXXXXXX'
The error was: syntax error at or near "WITH ORDINALITY"
LINE 6: FROM unnest(c.conkey) WITH ORDINALITY co…

PostgreSQLがVer9.2と古くて対応していないので、いい機会なのでバージョンアップすることに。

PostreSQLをバージョン13にしたら、問題なくinspectdbができたので、models.pyに定義を追加する。

4)DBのマイグレーション

PostgreSQLにadmin関係のテーブルを作成する。Microsoftのドキュメントの手順をい参考に。

(MS公式)手順 6-1:プロジェクトを作成し、データベースを初期化する

ソリューションエクスプローラーで、プロジェクトを右クリックして、[Python]>[Django で移行を実行する]を行う。その後、[Django でスーパーユーザーを作成する]を実行。

3.setting.pyの修正

日本語設定等を行う。

(Django公式)設定 | Django ドキュメント

とりあえず、変えたところは以下。

LANGUAGE_CODE = 'ja'
TIME_ZONE = 'Asia/Tokyo'

【アプリ作成】

Django公式のチュートリアルを参考に、仕組みを勉強しながら作業。

4.Djangoのバージョンアップ

Visual Studio 2019 のプロジェクトテンプレートは、Django2.2なので、最新のDjango3.1に変更した。

プロジェクトフォルダ直下のrequirement.txtのバージョンを修正する。

django~=3.1

Python環境の実行環境(ディフォルトならenv)を選択して、[パッケージ(PyPI)]を選択して、表示されている「Django2.2.*」の横の上矢印でバージョンアップするか、プロジェクトを再読み込みすれば画面上部にメッセージが出るのでクリックしてバージョンアップ。

テンプレートファイルの、staticsfilesの読み込みが、エラーになるので、テンプレートファイルを修正する。

【旧】{% load staticfiles %}
↓
【新】{% load static %}

5.テストについて

https://docs.microsoft.com/ja-jp/visualstudio/python/unit-testing-python-in-visual-studio?view=vs-2019

CentOSサーバーにGit

GitHubにソースを置きたくないので(一応、4月から無料でもprivateにできるが)、自前のサーバーにGitを立てることにした。Gitの公式ドキュメントは以下。

Gitドキュメント(日本語)

とりあえず、Gitサーバー立てるのは、以下を参考に。

4.4 Gitサーバー – サーバーのセットアップ

0)方針

  • 個人の開発端末のVisual Studio 2019のローカルレポジトリーのバックアップ用。
  • 端末は複数(自宅、外)あるので、共有とする。
  • 公開サーバー上に置くので、アクセスはポート変更済みのSSHで鍵認証。
  • ユーザーはgit操作しかできないユーザーとする。

1)Gitインストール

$ yum install git

2)Gitユーザー作成

git用のユーザーを作成する。この時、ログインシェルをgitに制限したものgit-shellを指定。

$ adduser --shell=/usr/bin/git-shell git

3)SSH公開鍵の登録

クライアント側の公開鍵を登録するために、gitユーザーにsuする。

$ su -s /bin/bash - git

クライアント側(開発PC端末)のSSH公開鍵(/tmp/id_rsa.john.pub)を登録する。※公開鍵が未作成の場合は、以下手順(5-1)で作成した公開鍵を登録。

$ mkdir .ssh && chmod 700 .ssh
$ touch .ssh/authorized_keys && chmod 600 .ssh/authorized_keys
$ cat /tmp/id_rsa.john.pub >> ~/.ssh/authorized_keys
 ※viで編集するでもOK

4)プロジェクトの初期化

空の共有のhogeプロジェクトを作成。

$ cd
$ mkdir hoge.git
$ cd hoge.git
$ git init --bare --shared
 ※gitユーザーでしか使わないのが、後の為、一応、shared

5)Windows側のSSH設定

Windows PowerShellを起動して、SSHの設定を行う。ちなみに、Visual Studio 2019のGitで使うSSHコマンドは以下に入っている

C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\IDE\CommonExtensions\Microsoft\TeamFoundation\Team Explorer\Git\usr\bin

5-1)SSH公開鍵の作成

ssh-keygenコマンドで、鍵を作成する。鍵を作成したら、公開鍵(端末側の、~/.ssh/id_rsa.pub)を、サーバー側の~/.ssh/authoraized_keysに追加登録する。※上記手順3にて

4.3 Gitサーバー – SSH 公開鍵の作成

$ ssh-keygen

5-2)既知ホストの追加&接続確認

Gitサーバー(xxx.gijutsu.comで、SSHポートが9999の場合)に接続して、クライアント側の既知ホストに登録する。

$ ssh -p 9999 -l git xxx.gijutsu.com

この時、既知ホストに追加するか聞いてくるので、yesを入力。その後は、以下のシェルエラーとなればOK。

Last login: Tue Dec 1 10:13:25 2020
fatal: Interactive git shell is not enabled.
hint: ~/git-shell-commands should exist and have read and execute access.
Connection to xxx.gijutsu.com closed.

6)Visual StudioからのPush

作成したGitサーバーのhogeプロジェクトにプッシュする場合は、リモートURLは以下を指定。

ssh://git@xxx.gijutsu.com:9999/~/hoge.git

Visual Studio 2019では、「Git 」から「Gitレポジトリの作成」で、「既存のリモート」を選択して、上記のリモートURLを入力する。

Visual Studio 2019 - Gitレポジトリの作成