Django 1.11 モデルの追加とマイグレーション | Django 入門

Python独学ならTech-Joho TOP > django入門/ > Django 1.11 モデルの追加とマイグレーション

Djangoでモデルを追加する

 

こちらのDjango公式チュートリアル (バージョン1.11用)をやってみます。

https://docs.djangoproject.com/ja/1.11/intro/tutorial02/

そのままやっても意味がないので、モデル名を変えてみます。

初心者の方は、両方を見比べることで、どのようにモデルを作ればいいのかがわかると思います。

基本的に、こちらの記事の続きです。

Windows 10 でDjango入門

設定

アプリ名は

“djangoTestApp”

だとします。

データベース名は

“django_test_app”

です。

データベース設定

mysqlにログインして

CREATE DATABASE django_test_app;

djangoTestApp2/settings.py

DATABASES = {
  'default': {
    #'ENGINE': 'django.db.backends.sqlite3',# もともとの設定
    'ENGINE': 'django.db.backends.mysql',
    #'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), # もともとの設定
    'NAME': 'django_test_app',
    'USER': 'xxxx',
    'PASSWORD': 'xxxx',
    'HOST': '127.0.0.1'
  }
}

上記のような書き方は、settings.pyの一部を表す。
例えば、上の例は76行目付近だった。
settings.pyを開いて、DATABASES等で検索して該当箇所まで移動して修正すること。

もしくは、設定ファイルを別に用意して使う
参考

https://docs.djangoproject.com/ja/1.11/ref/databases/#mysql-notes

djangoで使えるmysqlのアダプタはいくつかある

python3で推奨されているmysqlclient にする
参考

コンソール

> pip3 install mysqlclient

コンソールというのは、windows power shellや、コマンドプロンプトのこと
>の行の内容を入力する

ついでに、タイムゾーンと言語設定

djangoTestApp/settings.py

#LANGUAGE_CODE = 'en-us'
LANGUAGE_CODE = 'ja-jp'
#TIME_ZONE = 'UTC'
TIME_ZONE = 'Asia/Tokyo'

タイムゾーンのリスト
https://en.wikipedia.org/wiki/List_of_tz_database_time_zones

マイグレーション実行の方法

コンソール

> python manage.py migrate

Operations to perform:
  Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  Applying admin.0002_logentry_remove_auto_add... OK
  Applying contenttypes.0002_remove_content_type_name... OK
  Applying auth.0002_alter_permission_name_max_length... OK
  Applying auth.0003_alter_user_email_max_length... OK
  Applying auth.0004_alter_user_username_opts... OK
  Applying auth.0005_alter_user_last_login_null... OK
  Applying auth.0006_require_contenttypes_0002... OK
  Applying auth.0007_alter_validators_add_error_messages... OK
  Applying auth.0008_alter_user_username_max_length... OK
  Applying sessions.0001_initial... OK

こんな感じの表示が出たら成功

 

モデル作成

もともとのチュートリアルは投票アプリケーションらしく、
Question(投票項目)とChoice(選択肢)という2つのモデルを定義する

同じ例ではつまらないので、はてなブックマークのようなソーシャルブックマークサービスを想定する
Article(記事)とBookmark(ブックマーク)
ブックマークにはstar(スター)をつける

アプリ作成からやりなおす

>  python manage.py startapp bookmaker

bookmaker/urls.py
をつくり
djangoTestApp/urls.pyを修正する

仮のER図はこちらです。
ER図(articleとbookmark)

djangoのDB変更は3ステップ

  • models.pyを変更
  • python manage.py makemigrations でマイグレーションファイルを作成
  • python manage.py migrate でマイグレーション実行

djangoTestApp/models.py

rom django.db import models


class Article(models.Model):
"""記事"""
summary = models.CharField(max_length=200)
published = models.DateTimeField('date published')


class Bookmark(models.Model):
"""ブックマーク"""
article = models.ForeignKey(Article, on_delete=models.CASCADE)
comment = models.CharField(max_length=200)
stars = models.IntegerField(default=0)

djangoTestApp/settings.py

INSTALLED_APPS = [
  'bookmarker.apps.BookmarkerConfig',
  'django.contrib.admin',
  'django.contrib.auth',
  'django.contrib.contenttypes',
  'django.contrib.sessions',
  'django.contrib.messages',
  'django.contrib.staticfiles',
]

モデルを確認して、マイグレーションファイルを作成する

> python manage.py makemigrations bookmarker
Migrations for 'bookmarker':
  bookmarker\migrations\0001_initial.py
    - Create model Article
    - Create model Bookmark

0001というマイグレーションができた

できたマイグレーションの内容を確認

> python manage.py sqlmigrate bookmarker 0001
BEGIN;
--
-- Create model Article
--
CREATE TABLE `bookmarker_article` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `summary` varchar(200) NOT NULL, `published` datetime(6) NOT NULL);
--
-- Create model Bookmark
--
CREATE TABLE `bookmarker_bookmark` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `comment` varchar(200) NOT NULL, `stars` integer NOT NULL, `article_id` integer NOT NULL);
ALTER TABLE `bookmarker_bookmark` ADD CONSTRAINT `bookmarker_bookmark_article_id_8c3fd859_fk_bookmarker_article_id` FOREIGN KEY (`article_id`) REFERENCES `bookmarker_article` (`id`);
COMMIT;

CREATE TABLEのSQL文がふたつ

> python manage.py migrate

実行された

 

Shellでモデルの使い方の確認

シェル起動

> python manage.py shell

いろいろなメソッドを使ってみる

>>> from bookmarker.models import  Article
>>> Article.objects.all()

>>>
>>> from django.utils import timezone
>>> a = Article(summary='This is the first article.', published=timezone.now())
>>> a.save()
>>> a.id
1
>>> a.summary
'This is the first article.'
>>> a.published
datetime.datetime(2017, 10, 11, 4, 11, 25, 212888, tzinfo=)
>>> Article.objects.all()
]>

モデル一覧を見てみたが、(Article.objects.all())中身がぜんぜんわからないので、表示設定をする

 

モデルに表示設定など追加
models.py

import datetime
from django.db import models
from django.utils import timezone

class Article(models.Model):
  """記事"""
  summary = models.CharField(max_length=200)
  published = models.DateTimeField('date published')

  def __str__(self):
    return self.summary

  def was_published_recently(self):
    return self.published >= timezone.now() - datetime.timedelta(days=1)

  class Bookmark(models.Model):
  """ブックマーク"""
  article = models.ForeignKey(Article, on_delete=models.CASCADE)
  comment = models.CharField(max_length=200)
  stars = models.IntegerField(default=0)

  def __str__(self):
    return self.comment

__str__というメソッドをそれぞれ追加した。

もう一回シェルを立ち上げて確認する

> python manage.py shell

モデルのいろいろな使い方を確認してみる
検索、取得、作成、削除など..

>>> from bookmarker.models import  Article
>>> Article.objects.all()
]>
>>> Article.objects.filter(id=1)
]>
>>> Article.objects.filter(summary__startswith='This')
]>
>>> from django.utils import timezone
>>> current_year = timezone.now().year
>>> Article.objects.get(published__year=current_year)

>>> Article.objects.filter(id=2)

>>> Article.objects.get(id=2)
Traceback (most recent call last):
  File "", line 1, in 
 略
    self.model._meta.object_name
bookmarker.models.DoesNotExist: Article matching query does not exist.

>>> a1 = Article.objects.get(pk=1)
>>> a1.was_published_recently()
True
>>> a1.bookmark_set.all()

>>> a1.bookmark_set.create(comment='good!', stars=0)

>>> a1.bookmark_set.create(comment='bad', stars=10)

>>> b3 = a1.bookmark_set.create(comment='???', stars=2)
>>> b3.comment
'???'

>>> Bookmark.objects.filter(article__published__year=current_year)
, , ]>

>>> b3.delete()
(1, {'bookmarker.Bookmark': 1})
>>> Bookmark.objects.filter(article__published__year=current_year)
, ]>

 

管理画面

管理ユーザ作成

> python manage.py createsuperuser
Username (leave blank to use 'xxxx'): admin
Email address: admin@example.com
Password:
Password (again):
This password is too short. It must contain at least 8 characters.
This password is too common.
Password:
Password (again):
Superuser created successfully.

最初passにしようとしたらtoo short too commonと怒られた。
passpassにしたら通った。これでいいのか?

アプリ起動

> python manage.py runserver

http://localhost:8000/admin
にアクセス
Django管理サイトのログイン画面

ログイン後
Django管理サイトログイン後

追加したモデルを管理対象にする

bookmaker/admin.py

from django.contrib import admin

# Register your models here.
from .models import Article, Bookmark

admin.site.register(Article)
admin.site.register(Bookmark)

もう一回アクセス
管理対象のモデル一覧

Articlesをクリック
Article一覧

This is the first article.をクリック

Article管理

ちゃんとタイムゾーンで指定した通り、日本時間で表示されている

MySQLのDB内を直接のぞくと、UTCになっている

DBの中身

ちなみに、MySQL Workbenchを使っている
https://www.mysql.com/jp/products/workbench/

20日に変更して保存
Article20日に日付変更

これでチュートリアル2は終わり

 

おまけ: Herokumへのデプロイ

デプロイの手順の記事

Django 1.11 Herokuでデプロイ

Python独学ならTech-Joho TOP > django入門/ > Django 1.11 Herokuでデプロイ

Herokuは無料枠もあるPaasです。
Djangoで作ったWebアプリケーションを無料で公開できます。

Ruby on Railsではよく使っていましたが、Djangoは初めてだったので試してみました。

参考
https://qiita.com/Shitimi_613/items/6627d0ce042d38b86893

アプリはこちらのやつ
Django 1.11 モデルの追加とマイグレーション

windows上で開発しているので、関連箇所あり。

> pip install django-toolbelt

Procfileを作成

web: gunicorn djangoTestApp2.wsgi --log-file -

runtime.txtを作成

python-3.6.2

requirements.txtを作成

pip freeze > requirements.txt

この後、pywin23の行を削除する
そのほか、pipにいらないパッケージがあった場合も削除
いるものだけ書けばよい

settings.py に追記

STATICFILES_DIRS = (
  os.path.join(BASE_DIR, 'static'),
)
# DATABASES~の下あたりに追記
import dj_database_url
db_from_env = dj_database_url.config(conn_max_age=400)
DATABASES['default'].update(db_from_env)

djangoTestApp/wsgi.pyを変更

import os

from dj_static import Cling # これ追記
from django.core.wsgi import get_wsgi_application

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "djangoTestApp.settings")

application = Cling(get_wsgi_application()) # ここ変更

Herokuのツールのインストール
https://devcenter.heroku.com/articles/heroku-cli

herokuでログイン

> heroku login
Enter your Heroku credentials:
Email: xxxx@xxxxx.net
Password: ************
Logged in as xxxx@xxxx.net

herokuのプロジェクト作成

> heroku create
Creating app... done, xxxx-xxxx-xxxx
https://xxxx-xxxx-xxxx.herokuapp.com/ | https://git.heroku.com/xxxx-xxxx-xxxx.git

注意!! 以下のようにすれば後々のビルドパックの指定がいらなかった

> heroku create --buildpack heroku/python

ここででてきたアプリのホストを、settings.pyに追加

ALLOWED_HOSTS = [
    'xxxx-xxxx-xxxx.herokuapp.com'
]

よくわからない設定(静的ファイル関係だと思うけど)

heroku config:set DISABLE_COLLECTSTATIC=1

デプロイ

git push heroku master

エラー出た

> git push heroku master
Counting objects: 19, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (17/17), done.
Writing objects: 100% (19/19), 4.91 KiB | 1005.00 KiB/s, done.
Total 19 (delta 0), reused 0 (delta 0)
remote: Compressing source files... done.
remote: Building source:
remote:
remote:  !     No default language could be detected for this app.
remote:                         HINT: This occurs when Heroku cannot detect the buildpack to use for this application automatically.
remote:                         See https://devcenter.heroku.com/articles/buildpacks
remote:
remote:  !     Push failed
remote: Verifying deploy...
remote:
remote: !       Push rejected to salty-river-85500.
remote:
To https://git.heroku.com/xxxx-xxxx-xxxx.git
! [remote rejected] master -> master (pre-receive hook declined)
error: failed to push some refs to 'https://git.heroku.com/xxxx-xxxx-xxxx.git';


webのほうで、Pythonのビルドパックを追加した

Herokuのアプリ管理

ビルドパック追加

再度

git push heroku master

マイグレーション

> heroku run python manage.py migrate


アプリを開く

> heroku open


Pythonのandとor

Python独学ならTech-Joho TOP > Python用語辞典 >Pythonのandとor

andとor

and や orは、TrueやFalse(真偽値)と合わせて、論理演算、ブール演算とはで使う演算子です。
主に、if文の条件を指定する場合に使います。
複数の条件が同時に成り立つ場合(and)や、いずれかしか成り立たない場合(or)を指定することができます。

例えば、「xが1より大きく3より小さい」は下のようになります。

>>> 1 < x and x < 3

別の例だと、「xが10以下、もしくは20以上」は下のようになります。

>>> x <=  10 and 20 <= x 

Pythonのブール演算は少し違う

Pythonのブール演算は、他のプログラミング言語と比べると変わったところがあります。

簡単に箇条書きすると、下のようになります。

  • 数学の記号のように複数条件をつなげて書くことができる。
  • bool型の値(True/False)以外の値を返す

比較をつなげることができる

参考
Python3の公式リファレンス6.10. 比較

説明するより、下の例を見て下さい。

先程あげた、「xが1より大きく3より小さい」という例は、下のものでした。

>>> 1 < x and x < 3

これと、同じ意味の書き方がもう一つあります。

>>> 1 < x < 3

2つのxとandが消えています。
数学のように、「 1 < x < 3」は「xが1より大きく3より小さい」の意味になっています。 xに2など、適当な数字を代入して、下の黒い欄で実行してみてください。 もう一つの例、「xが10以下、もしくは20以上」は1つの書き方しかありません。

>>> x <=  10 and 20 <= x 

bool型以外の値を返す

参考
Python3の公式リファレンス 6.11. ブール演算 (boolean operation)

これは上の内容をそのまま転記します。

式 x and y は、まず x を評価します; x が偽なら x の値を返します; それ以外の場合には、 y の値を評価し、その結果を返します。

式 x or y は、まず x を評価します; x が真なら x の値を返します; それ以外の場合には、 y の値を評価し、その結果を返します。

例を上げて説明しましょう。
「10 or False」がどのように計算され、どのような値を返すか考えてみます。
まず、左の10は、真偽値を判定すると、真になります。
orは、その左の値が真なら左の値を返します。
つまり、この時点で、10は真なので、10が返ることになります。
orの右にあるFalseは、真偽が判定されることもありません。

>>> 10 or False
10

次に、「-1 and 10 > 2」がどのように計算され、どのような値を返すか考えてみます。
まず、左の-1は、真偽値を判定すると、偽になります。
andは、その左の値が偽なら左の値を返します。
つまり、この時点で、-1は偽なので、-1が返ることになります。
abdの右にある10 > 2は、真偽が判定されることもありません。

>>> -1 and 10 > 2
0

場合によって処理を分ける | Python独学ならTech-Joho(10)

Python独学ならTech-Joho TOP > Python入門カリキュラム > 場合によって処理を分ける

If文とは

>や<といった演算子を使ってPythonに式を渡すと、与えられた条件式が成り立つときはTrue(真)、成立しないときはFalse(偽)が返ってきます。
if文は、この診断結果によって、プログラムの流れを変化させることができるものです。

例えば、変数suujiが2より大きいと’2より大きい’、小さいと’2より小さい’と表示するプログラムは以下になります。(下の黒い欄に1行ずついれてみてください。)

>>> suuji = 1
>>> if suuji > 2:
...   print('2より大きい')
... else:
...   print('2より小さい')
... 
'2より小さい'

if suuji > 2:を入れると、>>>となっていたところが…と変化します。
最後の(‘2より小さい’)の行のあとは、1行何もいれないままエンターキーを押して改行してください。

suujiは1なので、常に’2より小さい’が表示されるはずです。

ifの練習1

上の例で、suujiを2, 3, 4, 5にして実行してみてください。何が表示されますか?

値がその都度変わるものを使わないと、if文のありがたさはわかりません。
ユーザの入力を受け付けるinput関数を使う例をみてみましょう。

input関数の使い方はこちらに書いてあります。

>>> nyuuryoku = input('数字を入力して下さい')
>>> suuji = int(nyuuryoku)
>>> if suuji > 2:
...   print('2より大きい')
... else:
...   print('2より小さい')
... 

 


else

if のあとに書く、条件が成立しなかった時に、別の処理が実行させるようにするのが、elseです。
上と同じ例ですが、もう一度見て下さい。

>>> suuji = 1
>>> if suuji > 2:
...   print('2より大きい')
... else:
...   print('2より小さい')
... 
'2より小さい'

suujiという変数に代入されたのは、1です。
ifの後にある条件は、「suujiが2より大きい」です。

すると、ifのあとの条件は成立していません。
その場合、
ifのすぐ下に書いた内容ではなく、ifに続いて書いたelseの後の下に書いた内容が実行されます。

 


elif

elifという、elseとifをくっつけたような文もあります。

上の例を少し変えて、elifという文が真ん中辺りに増えています。
elifの下の部分が実行される条件を日本語にすると、「suujiが2以下で、もし1より大きければ」となります。

>>> suuji = 2
>>> if suuji > 2:
...   print('2より大きい')
... elif suuji > 1:
...   print('1より大きい')
... else:
...   print('1以下')
'2より小さい'

elifは、もし上に書いてある条件が当てはまらかなったら、右に書いてある条件をチェックする、という意味です。
下の例のように、elifをたくさん書くこともできます。

>>> suuji = -2
>>> if suuji > 2:  # 最初の条件
...   print('2より大きい')  
... elif suuji > 1: # 最初の条件が当てはまらかなったらチェックする条件
...   print('1より大きい')
... elif suuji > 0: # 次の条件が当てはまらかなったらチェックする条件
...   print('0より大きい')
... else:  # 上に書いてある条件が全て当ては余らなかったら
...   print('0以下')
'0以下'

この例だと、まず、suujiが2より大きいかをチェックします。(最初の条件)

当てはまらかなったら、suujiが1より大きいかをチェックします。(最初の条件が当てはまらかなったらチェックする条件)

さらに、これも当てはまらかなったら、suujiが0より大きいかをチェックします。(次の条件が当てはまらかなったらチェックする条件)

さらに、これも当てはまらかなったらelseの下に書いてある内容が実行されます。

 

どんどん下の条件に流れていく感じです。


ifの練習2

下の条件を満たすif、elif、elseを使ったコードを黒い欄で実行してみて下さい。

  • input関数を使ってユーザに数字入力させる
  • ユーザが入力した数字をint関数でint型に変換する
  • 変数suujiに、int型に変換した数字を代入する
  • suujiが10より大きかったら’10より大きい’と表示
  • suujiが10以下で、5より大きかったら’5より大きい’と表示
  • suujiが5以下だったら’小さい!!!’と表示

 


andとor

ifの後には、andとorで2つの条件を書くこともできます。

>>> suuji = -2
>>> if suuji > 2 and suuji < 5 :
...   print('5と2の間') 
... else: 
...   print('5以上か、2以下')
'0以下'

くわしくはこちら(執筆中….)で解説する予定です。

 



<< 前へ 第9回 たくさんのデータを1つにまとめる

>> 次へ 第11回 たくさんのデータで同じ処理を繰り返す


input関数|Python用語辞典

Python独学ならTech-Joho TOP > Python用語辞典 > inputで入力を受け付ける

inputで入力を受け付ける

input関数は、その名の通り、ユーザからの入力(input)を受け付ける関数です。
まず、文字で説明するより使ったほうが理解しやすいと思います。
下の黒い欄に、”suuji = input(‘数字を入力して下さい’)”と入力してください。

>>> suuji = input('数字を入力して下さい')

すると、こんな風に、’数字を入力して下さい’と書いたウインドウがでてきます。

Brythonによる入力ダイアログ

入力欄に’1’か何か、数字を入力してOKを押して下さい。
すると、ウインドウが閉じます。

実は、この時点で、suujiという変数に今入力した数値が代入されています。
下のように、print(suuji)と入力してエンターキーを押して下さい。

>>> suuji = input('数字を入力して下さい')
>>> print(suuji)
1

先程入力した数値が表示されます。

input関数の引数

input関数は人間(ユーザ)に入力をさせて、その値を返す関数です。
inputの引数は、入力させるときに表示する文言です。

こうすれば、’何か入力して下さい’と表示されます。

>>> input('何か入力して下さい')

input何か入力して下さい。

こうすれば、’ああああ’と表示されます。

>>> input('ああああ')

inputあああ

下の黒い欄で自分で試してみてください。

inputの引数の練習

ユーザに’アルファベットを入力!!’と表示する、input関数の引数を考えて実行してください。

input関数の戻り値

繰り返しになりますが、input関数は人間(ユーザ)に入力をさせて、その値を返す関数です。
inputの戻り値は、人間が入力した関数です。

下のコードでは、my_inputに、ユーザが入力した値を代入します。

>>> my_input = input('何か入力して下さい')
>>> print(my_input)

なので、my_inputをprintすると、ユーザが入力した文字列が表示されます。

ちなみに、input関数の戻り値は常に文字列になります。
なので、数字を入力しても、数値の文字列になってしまいます。

‘1’ * 5 は 5ではなく、文字列’1’を5こくっつけた’11111’になります。

>>> my_input = input('何か入力して下さい') # 1を入力する
>>> print(my_input * 5)
'11111'

数値として計算したいときは、int関数やfloat関数で、文字列を数値に変換しましょう。

>>> my_input = input('何か入力して下さい') # 1を入力する
>>> int(my_input) * 5
5 

intやfloat等、変数の型についてはこちらをみてください。
変数の型について/

inputの戻り値の練習

ユーザに数値を入力してもらい、それを100倍して表示するプログラムを実行してください。

ふつうのPythonだとウインドウはでてこない

なお、これまで、input関数を実行するとウインドウがでてきましたが、それはこのサイト上でPythonを実行しているときだけの話です。(正確に言うとBrythonをつかっているときだけ)

自分のPCにPythonをインストールして使っている場合、ウインドウはでず、単にinputの引数にしたメッセージが表示されるので、そのまま黒い画面に入力できます。こんな感じです。

>>> message = input('please input!! : ')
please input!! : はーい
>>> print(message)
'はーい'

Pythonで、MySQL5.7のJSON型にツイートを保存してみる

Python独学ならTech-Joho TOP > いろいろやってみた > Pythonで、MySQL5.7のJSON型にツイートを保存してみる

取得したツイートを保存したい

前回、ツイッターから特定のキーワードで検索したツイートを取得するPythonプログラムをつくりました。

Twitterで特定のフレーズで検索して結果を表示する

このままだと、検索したツイートは目でみて確認するだけで終わりで、あとで分析することもできません。ツイートを保存する仕組みが必要です。

MySQLのJSON型を使ってみたい

保存するにはデータベースを使います。しかし、データベースを言ってもいろいろな候補があります。

候補1: MongoDB

取得できるツイートはJSON形式で、リツイートの具合などによって構造は微妙に変わります。こういうときはNoSQLで、MongoDBが最初に思い浮かびました。

ただ、MongoDBは、あまりたくさんのデータを保存するのに向いていないところがあります。やたら容量をくって、えらい目にあった経験があり、余り使いたくありません。

他にもCouchDB、Cassandraなんかもちょっと考えましたが、よく知らないのと調べるのが面倒くさかったのでやめました。

参考

候補2: MySQL

しっかりと、列の構造を決めて、ふつうにMySQLに保存するというのも考えました。しかし、モデルを作るのがめんどくさくてやめました。

JSON型

そこで思い出したのですが、MySQLの列のデータ型で、JSON型というのがあります。

単に一つの文字列型の列にJSON文字列を突っ込むように使えますが、検索などの際、JSONのキーで検索できるようです。

一度使ってみたかったのでこれにします。

MySQL5.6の後半から使えるようになったみたいです。

参考

https://www.webprofessional.jp/use-json-data-fields-mysql-databases/
https://www.s-style.co.jp/blog/2017/06/420/

CRATE文

こうなりました。

CREATE TABLE `tweets` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `content` json NOT NULL,
  `created` datetime DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

datetime型でも、DEFAULT CURRENT_TIMESTAMPで作成時間を入れられるようになったみたいです。
http://dekokun.github.io/posts/2014-05-31.html

MySQLは5.7.21にしました。

Pythonのコード

こうなりました。

from twython import TwythonStreamer, TwythonError
import json
import config
import mysql.connector
import sys


conn = mysql.connector.connect(
    host='localhost',
    port=3306,
    user=config.MYSQL_USER,
    password=config.MYSQL_PASS,
    database='twitter_app'
)

if not conn.is_connected():
    print('could not connect to db')
    sys.exit()
conn.ping(reconnect=True)
cur = conn.cursor()


class MyStreamer(TwythonStreamer):
    def on_success(self, data):
        json_text = json.dumps(data)

        try:
            sql = "insert into tweets (content) values (%s);"
            cur.execute(sql, (json_text,))
            conn.commit()
        except Exception as err:
            conn.rollback()
            print('could not commit inserting:', json_text)
            print('error:', err)
        if 'text' in data:
            print(data['text'])

    def on_error(self, status_code, data):
        print(status_code)


try:
    stream = MyStreamer(config.APP_KEY, config.APP_SECRET, config.ACCESS_TOKEN, config.ACCESS_TOKEN_SECRET)
    stream.statuses.filter(track='AKB')

except TwythonError as e:
    print(e)

configモジュールに、MySQLのパスワードなどいろいろな定数を入れています。

使っているライブラリはmysql-connector-python-rfになりました。mysql-pythonにしようとしたら、変なエラーがでてインストールできませんでした。

$ pip install mysql-connector-python-rf
https://stackoverflow.com/questions/37092125/cant-install-mysql-python-version-1-2-5-in-windows

ツイートの本文だけ取り出す

SELECT
  id,
  content->"$.text" AS `text`
FROM sport_twitter_dev.tweets;

便利です。

Twitterで特定のフレーズで検索して結果を表示するアプリ

Python独学ならTech-Joho TOP > いろいろやってみた > Twitterで特定のフレーズで検索して結果を表示するアプリ

Twitterで特定のフレーズで検索して結果を表示するアプリを作ってみました。

ライブラリ

tweepyはメンテナンスが停止したらしいのでTwthonというライブラリを使います。

Twython公式
https://github.com/ryanmcgrath/twython

Twythonを使う

tweepyについて
http://qiita.com/ogrew/items/0b267f57b8aaa24f1b73

押したキー
http://qiita.com/tobesan/items/d9f4bd543c3a85b49bb2

利用するAPI
Twitter Search
https://developer.twitter.com/en/docs/tweets/search/api-reference/get-search-tweets.html

環境

windows 10
python 3.6.2
virtualenv

準備

 virtualenv有効化

/Users/xxxxxx/.virtualenvs/djangodev/Scripts/activate

Twithonインストール

$ pip install twython

アプリ登録

https://apps.twitter.com/
アプリを登録して、APIキーとAppシークレットを取得
継続的にツイートを取得するためストリームAPIを使いたいなら、アクセストークンとアクセストークンシークレットも取得

コード

.config.py


APP_KEY = 'xxxxxxxxxxxxxxxxx'
APP_SECRET = 'xxxxxxxxxx'
ACCESS_TOKEN = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
ACCESS_TOKEN_SECRET = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'

検索API使うやつ

エンターキーを押すたびに、繰り返し検索する
Search APIを利用
OAuth1が必要

search.py


from twython import Twython, TwythonError
import config

pressed = ''
twitter = Twython(config.APP_KEY, config.APP_SECRET, oauth_version=2)
ACCESS_TOKEN = twitter.obtain_access_token()
twitter = Twython(config.APP_KEY, access_token=ACCESS_TOKEN)

while pressed == '':

    try:
        results = twitter.search(q='プロ野球')
        print('tweets num:', len(results))
        print(results)
    except TwythonError as e:
        print(e)

    pressed = input("type in enter")

print('finish')


ストリーミングAPI使うやつ

継続的にツイートを取得しフィルターする
Streamimg APIを利用
OAhth2が必要

stream.py


from twython import TwythonStreamer, TwythonError

import config

class MyStreamer(TwythonStreamer):
    def on_success(self, data):
        if 'text' in data:
            print(data['text'])

    def on_error(self, status_code, data):
        print(status_code)

try:
    stream = MyStreamer(config.APP_KEY, config.APP_SECRET, config.ACCESS_TOKEN, config.ACCESS_TOKEN_SECRET)
    stream.statuses.filter(track='AKB48')

except TwythonError as e:
    print(e)

 

コードはこちらからもダウンロードできます。
https://github.com/tech-joho-info/GetTweetsByPython

たくさんのデータを1つにまとめる| Python独学ならTech-Joho(9)

Python独学ならTech-Joho TOP > Python入門カリキュラム > たくさんのデータを1つにまとめる

たくさんのデータを1つにまとめる

Pythonには、複数のデータを1つにまとめるためのデータ型がいくつかあります。

よくつかうのが、リスト(list)、タプル(tuple)、辞書(dictionary)、セット(set)の4種類です。

下の黒い欄では、Pythonのコードを実際に実行してみることができます。
このページに出てくる例を、打ち込んで試してみて下さい。

 


リスト

リストは、文字通りいろいろなデータのリストと考えて下さい。
1, 2, 3等、数字のリスト、や、”ごはん”, “パン”, “麺” など文字列のリストなど、色々作れます。

>>> [1, 2, 3]
[1, 2, 2]
>>> ['ごはん', 'パン', '麺']
['ごはん', 'パン', '麺']
>>> [1, 'a', 1.00, 'alpha']

最後の例みたいに、数字と文字列が混ざったリストも作れます。
リストの各要素のデータ型に制限はありません。

リストの作り方

既に上で書いてしまいましたが、リストを作るには、リストに入れたいデータを”,”(コンマ)で区切ってつなげて、全体を[](角かっこ)でくくります。

>>> my_list = [1, 2, 3]
>>> print(my_list)
[1, 2, 3]

ちなみに、[と]のことを角かっこと呼ぶのを今知りました。
https://ja.wikipedia.org/wiki/%E6%8B%AC%E5%BC%A7

なお、角かっこだけを書けば、空のリストをつくることもできます。

>>> empty_list = []
>>> print(empty_list)
[]

要素へのアクセス

例えば、あるリストの2番目の要素を取り出すなど、リストの特定の要素だけにアクセスできます。
つまりこういうことです。

>>> my_list = [1, 2, 3]
>>> print(my_list[1])
2

わかりますか?
my_listの番号1(前から2番目)の要素を取り出してみました。
取り出すには、リストの変数名の後ろに[]でくくって、取り出したいデータの番号を入れます。

pythonでは、リストの番号は0から始まります。
なので、前から2番目の要素は、番号1になります。

同じように、前から3番目の要素は、番号2になります。

>>> my_list = ['a', 'b', 'c']
>>> print(my_list[2])
c

要素の追加・変更・削除

リストには、後から要素を追加できます。

追加するには、appendメソッドを使います。

>>> my_list = ['a', 'b', 'c']
>>> print(my_list)
['a', 'b', 'c']
>>> my_list.append('d')
>>> print(my_list)
['a', 'b', 'c', 'd']

この例では、’d’をリストの一番後ろに追加しています。

リストの要素は、変更することができます。
変更は、要素にアクセスするときと似ています。
変数名の後ろに[]と変更したい要素の番号を書いて、そこに=で代入します。

>>> my_list = ['a', 'b', 'c']
>>> print(my_list)
['a', 'b', 'c']
>>> my_list[2] = 'cccc'
>>> print(my_list)
['a', 'b', 'cccc']

この例では、リストの3番目(番号2)の要素を、’c’から’ccc’に変えました。

また、リストの要素を削除するには、popメソッドを使います。

>>> my_list = ['a', 'b', 'c']
>>> my_list.pop(1)
>>> print(my_list)
['a', 'c']

リストの連結

リスト同士で足し算すると、つながります。

>>> my_list = ['a', 'b', 'c']
>>> other = ['x', 'y', 'z']
>>> print(my_list + other)
['a', 'b', 'c', 'x', 'y', 'z']

 

リストについてのもう少し詳しい内容は、こちらで解説する予定です。

リスト[]

リストを操作する動画をとりました。こんな感じになります。


文字列

文字列も、文字というデータがたくさん集まったものです。
そのため、リストと同じような操作ができます。ここでは、文字列の1部を取り出す方法について解説しておきます。

文字列の変数名の後ろに[]を書き、その中に0から始まる番号を書くと、その番号の文字を取り出すことができます。

>>> mojiretsu = 'aiueo'
>>> mojiretsu[0]
'a'
>>> mojiretsu[1]
'i'

上の例では、文字列’aiueo’をmojiretsuという変数に割り当てています。そのあと、mojiretsu[0]で最初の文字aを取り出しています。
さらにそのあと、mojiretsu[1]で二番目の文字iを取り出しています。


タプル

タプルは変更できないリストみたいなものです。
丸かっこ()を使ってつくります。

>>> my_tuple = (1, 'a', 'あ')
>>> print(my_tuple)
(1, 'a', 'あ')

タプルの要素にアクセスするときは、リストと同じように[]を使います。

>>> my_tuple = (1, 'a', 'あ')
>>> print(my_tuple[1])
'a'

タプルの要素を、変更することはできません。変更しようとすると、エラーがでます。

>>> my_tuple = (1, 'a', 'あ')
>>> my_tuple[1] = 'あいうえお'
Traceback (most recent call last):
  module __main__ line 134
    traceback.print_exc()
  module  line 1
    my_tuple[1] = 'あいうえお'TypeError: 'tuple' object does not support item assignment

 


辞書

辞書は、番号ではなく、文字列に対応づけてでデータを保存できるものです。
英語のまま、ディクショナリとカタカナで書いてよぶこともあります。
どういう意味かというと、リストでは、個々の要素を0番, 1番, という風に数字で指定しますが、
辞書では、’a’, ‘b’など文字列で指定できます。
また、リストは角かっこ[]でつくりましたが、辞書は波かっこ{}でつくります。

この例を見てください。

>>> fruits = {'apple': 'リンゴ', 'orange': 'オレンジ', 'melon': 'メロン'}
>>> print(fruits)
{'apple': 'リンゴ', 'orange': 'オレンジ', 'melon': 'メロン'}
>>> fruits['orange']
'オレンジ'

この例では、英単語とその訳の日本語をペアで保存しています。変数名furuitsの後ろに[]を続けて、中に’orange’といれると、’オレンジ’という対応付けた文字列が取り出せました。

こういう例もあります。都道府県名と、その件が関東にあるか関西にあるか、という文字列を対応付けています。

>>> prefectures = {'東京': '関東', '神奈川': '関東', '大阪': '関西'}
>>> print(prefectures)
{'東京': '関東', '神奈川': '関東', '大阪': '関西'}

この場合、変数名prefecturesの後ろに、[]をつけて、中に’東京’といれると、’関東’が取り出せました。

>>> prefectures = {'東京': '関東', '神奈川': '関東', '大阪': '関西'}
>>> print(prefectures['神奈川'])
'関東'

辞書の練習

>>>languages = {'ruby': 'ルビー', 'php': 'ピーエイチピー', 'python': 'パイソン'}

上のlanguagesは、プログラミング言語の英語の名前とそのよみかたの辞書です。
下の黒い欄にプログラミングを書いて、上の辞書からpythonの読み方を取り出して表示してみて下さい。


セット

重複のないデータの集まりです。
リストでは、[1, 2, 1, 3, 1]のように、要素同士に同じものがあっても大丈夫ですが、セットは同じものが入りません。

セットをつくるには、空っぽのセットを作ってから、要素を追加します。

>>> test_set = set() #空のセットを作ります。
>>> print(test_set)
set([ ])
>>> test_set.add('a')
>>> test_set.add('b')
>>> test_set.add('c')
>>> print(test_set)
set(...)

または、既存のリストやタプルをセットへと変換して作ります。

>>> from_list = set(['か','き','く'])
>>> print(from_list)
set({'か', 'き', 'く'})

セットの練習

空っぽのセットをつくってから、’a’を3こ追加して、printしてみてください。

 


<< 前へ 第8回 データ型とオブジェクト

> > 次へ 第10回 場合によって処理を分ける


virtualenvでWindows10 に Django インストール | Django 入門

Python独学ならTech-Joho TOP > django入門/ > Windows 10 でDjango入門

Django

Djangoは、PythonのWebアプリケーションフレームワークです。

http://djangoproject.jp/

RubyのRuby on Railsくらい有名で、昔からあります。

最近いじってなかったのと、windows環境での開発は初めてなので、
開発環境を作ったメモを公開します。

このページはPython初心者の方には難しいです。まず入門編をご覧ください。
Python Hello World
続きもあります

環境

以下は導入済み

  • Windows 10 Creaters Update
  • Python 3.6.2 (x64)
  • MySQL5.7

現時点での最新版を入れると、Django 1.11.5 がはいりました。

参考

公式インストールガイド

virtualenvいれる

virtualenvは、Python用の仮想環境で、例えば環境ごとにpipでいれるモジュールをわけられます。

Rubyのrbenvみたいな感じです。

参考

windowsパワーシェルを起動し、ホームディレクトリで下記を実行

python get-pip.py
pip install virtualenv
mkdir .virtualenvs
virtualenv .virtualenvs/djangodev

pipをインストールし、virtualenv用のディレクトリ.virtualenvを作って、そこにdjangodevという名の仮想環境をインストールしています。

無事インストールできたら、下記のスクリプトを仮想環境djangodevを有効化できます。

.\/.virtualenvs/djangodev/Scripts/activate

私の環境では、パワーシェル用のスクリプトは実行デキない設定になっていました。
上のスクリプトを実行するにはポリシー変更が必要でした。

参考
http://www.atmarkit.co.jp/ait/articles/0805/16/news139.html
管理者権限でパワーシェルを起動し、下のコマンド実行でポリシーを変更できました。

Set-ExecutionPolicy RemoteSigned

仮想環境が有効化されたら、パワーシェルのプロンプトの左側に下のように表示されます。

(djangodev) xxx 

Djangoのインストール

仮想環境の中で、Djangoをインストールします。
pip install Django
python -m django –version

1.11.5が入ったことが確認できます。

Django起動

せっかくなのでチュートリアルのアプリを作って起動するところまでやってみます。

参考
https://docs.djangoproject.com/ja/1.11/intro/tutorial01/

cdコマンドでDjangoのプロジェクトを作りたいところまで移動して

django-admin startproject mysite

これでmysiteプロジェクトができます。

mysiteプロジェクトのディレクトリ内に移動します。

cd mysite

manage.pyはいろいろやってくれるpythonのスクリプトです。開発用のサーバを立ち上げましょう。

python manage.py runserver

これで起動するはずです。

ブラウザでhttp://127.0.0.1:8000/にアクセス。

Djangoの動作を確認できる初期画面

画面が確認できたら成功です。


おまけ iintellij ideaで既存のvirtualenvを読み込む方法

私はintellij ideaにpythonプラグインを入れたものをメインのエディタにしています。

iintellij ideaで既存のvirtualenvを読み込む方法は以下のサイトにのってました。

file>project structure  から
https://stackoverflow.com/questions/20877106/using-intellijidea-within-an-existing-virtualenv

つづき

モデルの追加とマイグレーション | Windows10でDjango入門2

Django をHerokuにデプロイ

データ型とオブジェクト |Python独学ならTech-Joho(8)

Python独学ならTech-Joho TOP > Python入門カリキュラム > データ型とオブジェクト

データ型とオブジェクト

かんたんなデータについては前に説明しました。
このページでは、データ型についてより詳しいことを、オブジェクトという考え方を使って説明しましす。

データ型のおさらい
第5回 変数の型について

 


文字列とメソッド

文字列型のデータを1つ用意すると、いろいろと便利なことができました。

>>> abc = ‘Alpha, Beta’
>>> abc.split(‘,’)
[‘Alpha’, ‘Beta’]

他にも、indexメソッドを使うと、引数で指定した文字が、何番目か分かります。

>>> abc.index(‘,’)
5

ちなみに、順番は一番最初が0番になります。

このように、文字列データを1つ用意するだけで、spllitやindexといった便利なメソッドをすぐに使うことができます。

 


フルーツと道具

ここにフルーツの「リンゴ」が1つあるとします。
このリンゴをどうしましょうか?
リンゴの扱いには、いろいろあります。

ナイフで普通に皮をむいて食べることもできます。
ミキサーを使ってジュースにして飲むの美味しいですね。
また、ちょっとひねった考えですが、植木鉢と土があれば種を植えて芽をださせ、リンゴの木を育てることもできます。

リンゴ


これらはすべて、フルーツのための道具のセットです。
普段は、「フルーツ」という言葉を聞いても実際のオレンジやリンゴしか思い浮かばいですが、ここでは、こうした道具も含めて「フルーツ」と考えます。
ちょっと変な考え方ですが、なんとか慣れて下さい。

「道具も含めてフルーツ」です。

 

文字列データ型を用意すると、いろいろなメソッドを使うことができました。

これを、材料としてのリンゴと、それを料理するための道具セットにも当てはめられます。
データにはそれぞれ型があったように、果物型を考えてみましょう。

文字列型と果物型

文字列データの場合、実際の内容は、それぞれの使うシチュエーションによって違います。例えば、’Red’、’Blue’など、いろいろな文字列を用意できます。これは、果物型で言えば、リンゴではなくてオレンジやメロンを用意することに似ています。

果物屋さんでリンゴを買っても、ナイフやミキサーなどの道具をおまけでくれることはありません。しかし、Pythonは親切なので、データをいろいろな方法で扱う道具を用意してくれます。これが、既に習ったメソッドです。

メソッドについてはこちら
第7回 関数とメソッドを使ってみる

Pythonが用意してくれるメソッドには、必要そうなものがだいたい揃っています。。これらの道具(メソッド)を上手に使うことで、プログラムをすばやく作ることができます。

「オブジェクト」とか「オブジェクト指向」という言葉を知っていますか?

オブジェクトとは、Pythonでは、データ型と同じような意味です。

Pythonにおける型は、実際のデータとそれを処理するメソッドが一緒になっているものです。
このものがオブジェクト。
オブジェクト指向とは、このものとしてのオブジェクトを使ってプログラミングすることです。

 


実体を作る

データ型は、実体が無い概念だけで、実際に使うには、実体(インスタンス)を作る必要があります。
果物型の例でいうと、果物型というのは果物全体を表す概念です。
それに対し、リンゴとかオレンジなどの実物がインスタンスに当たります。

文字列型で考えてみましょう。
「文字列型」というのは概念です。それに対し、いろいろなときに実際に使う’Alpha’だとか、’Orange’、’Osaka’などの実際の文字列がインスタンス、実体です。)

あるデータ型の実体を作るには、そのデータ型を同じ名前の関数を使います。

例えば、文字列型は本当は、str型という名前でした。
第五回 変数の型について
strという名前の関数を、作りたい文字列を引数に渡して実行すると、str型のインスタンスができます。
この、データ型と同じ名前の関数が「初期化メソッド」というものです。
下の例では、できたインスタンスをmy_strという変数に代入しています。

>>> my_str = str('Nagoya')
>>> print('Nagoya')
Nagoya

実は、下のように書いても、同じことです。文字列型(str型)のインスタンスを用意しています。

>>> my_str = 'Nagoya'
>>> print('Nagoya')
Nagoya

文字列(str)、整数(int)、小数(float)などは、組み込みデータ型といいます。
初期化メソッドを使う必要がないようになっています。

 


date型をつかってみる

もっと高機能なオブジェクトをつかってみましょう。
Pythonには、「日付」を表すdate型というデータ型が用意されています。

datetime型を使うには、最初にこのようにimport datetimeを実行する必要があります。

>>> from datetime import *

これはモジュールのimportという操作です。詳しくは別なページで解説します。

インスタンスを作る

特定の日を表す、date型のインスタンスをつくってみましょう。
下の例では、2020年1月1日のインスタンスを作っています。

>>> day = date(2020,1,1)
>>> print(day)
2020-01-11

date型のメソッド

date型は、その日が何曜日かを教えてくれるメソッド「weekday」を持っています。
このメソッドは、曜日を0から始まる数字で返します。0が月曜日、1が火曜日…と続き、6が日曜日です。

>>> day.weekday()
2

2020年1月1日の場合、2なので、水曜日という意味です。

実体がなくても使えるdate型のメソッド

date型は、実体がなくても使えるメソッドとして、todayを持っています。

>>> kyou = date.today()
>>> print(kyou)
2017-10-01

date型の引き算

date型も、引き算ができ、2つの日付の差を計算できます。
先程の、2020年1月1日から、今日の日付を引いてみましょう。

>>> sa = day - kyou
>>> print(sa)
822days, 0:00:00

2020年オリンピックイヤーまではあと822日でした。(もちろん、このコードを実行する日付によって日数は変わります。2020年よりあとに実行していたら、マイナスの日数かもしれません。)

データの属性

インスタンスが、属性やプロパティと呼ばれる変数を持っている場合があります。
例えば、上の例に出てきた日数の差を表す変数saは、実はtimedelta型のデータで、daysという変数(属性)を持っています。

>>> print(sa.days)
822

データ型の調べ方

ちなみに、typeという関数を使うと、インスタンスのデータ型を調べることができます。

>>> type(sa)
<class 'timedelta'>
>>> type(kyou)
<class 'date'>
>>> type(1)
<class 'int'>

 


<< 前へ 第7回 関数とメソッドを使ってみる
>> 次へ 第9回 たくさんのデータを1つにまとめる

Python入門

第1回 Python Hello World

第2回 Pythonでできること

第3回 簡単な計算をしてみよう

第4回 変数に値を代入する方法

第5回 変数の型について

第6回 比較する演算子

第7回 関数とメソッドを使ってみる

第8回 データ型とオブジェクト

第9回 たくさんのデータを1つにまとめる