新人さんも入社し、ますます部下への対応を学ぶ機会ですね。
野口 大先生のパワハラとならない注意・指導方法
60日間 1,620円(税込)
新人さんも入社し、ますます部下への対応を学ぶ機会ですね。
野口 大先生のパワハラとならない注意・指導方法
60日間 1,620円(税込)
パンダスタジオさいたまは、2014年度の宅建受験生を応援するため、宅建eラーニング「まるで家庭教師」(30,000円(税込))をご購入いただいた方を対象に、2013年版の教科書を、改訂箇所を別紙で印刷したものを添えて無料で進呈させていただきます(先着20名様)。こちらの教科書は、eラーニングで収録されていない税金や免除科目も掲載しております。
■ 宅建教科書無料プレゼントキャンペーン概要
・ 対象/宅建eラーニング「まるで家庭教師」をご購入の方先着20名様
・ 期間/2014年5月15日~6月30日
不動産広告を長年取り扱い、豊富な業界の知識を持つ広告代理店・エクシム株式会社と、宅建講師として25年の実績を持つ岩本周二により誕生したeラーニングです。
出題が予想されるポイントを重点的に押さえ勉強時間を減らすとともに、「飽きない、眠くならない」ための工夫を施したWeb講座を提供。初学者、独学者から上級者まで満足でき、短期間で合格圏に届く実力の養成を目指します。
なお、本講座の有効期限は、お申し込みより365日です。また法改正等にあわせ随時更新いたします。
1.一方的な解説でなく、受講生との掛け合いで親しみやすい!
2.1コマ平均8分の飽きない講義!
3.基礎講義⇒○×クイズ⇒過去問解説、3ステップでわかりやすい!
4.主要3科目に絞った効率的な講義!
5.PC、スマホ、タブレットに対応。場所を選ばす学べる!
6.肢別問題を多く取り入れ、今後頻出する個数問題にも対応!
1.全科目のテキスト(PDF)
※eラーニングの主要3科目だけではなく税、免除など全科目を掲載。
※プリントアウトはご自身でお願いいたします。
※テキストは「宅建業法」のフォルダーに格納しています。
2.過去問+詳細解説250問(PDF)
※プリントアウトはご自身でお願いいたします。
※2014年5月下旬よりリリース予定です。
3.法改正に随時対応
4.10月、直前講義ライブ配信(予定)
・ 科目/宅建業法、法令上の制限、権利関係の主要3科目
・ 講座数/全320コマ(業法120コマ、法令80コマ、権利120コマ)
・ 講座時間/1コマ平均約8分。計約43時間
★権利、法令、業法全て受講できます。
まずは、ユーザ登録(無料)を!
重要数字講座を無料でご覧いただけます
■ 講座の特徴
・ 講師の一方的な解説ではなく、講師と受講生の掛け合いによる構成
・ 1コマの時間を5分から10分程度に抑えた短時間集中タイプ
・ 1単元に対し、基礎、○×クイズ(応用)、過去問解説の3ステップで対応
・ 基本パターンは1単元を基礎、○×、過去問の3コマで完了
・ 1コマ平均約8分。1日6コマ(48分)×54日=2ヶ月で終了
・ パソコン、スマートフォン(アイフォン、アンドロイド)、タブレットにも対応
・ 無料サンプルを確認後の購入システム
・ 科目ごとなど受講生のニーズにより選択可能なシステム
日本大学法学部法律学科卒業。
大学、地方自治体、大手不動産会社、専門学校、地区講習会にて宅建指導。
ラジオ講座、インターネット宅建講座、ビデオ講座等への出演多数。
主な著書は、住宅新報社刊の的中宅建民法重要条文、宅建六法(重要ワード担当)、宅建ネット塾、パーフェクト宅建過去10年間(共著)等
サンプルの視聴、ご購入にはユーザ登録(無料)が必要です!
初めての方はログインボタン下の「ユーザー登録」をクリック!
※すでに登録をされている方は、IDとパスワードをご入力してお進みください。
※ユーザ登録後、必ず”無料サンプル講義”を視聴し、お使いの端末での視聴が可能か確認してください。YouTubeのサンプルをご覧いただいた方も、ご試聴のほどお願いいたします。端末・環境により閲覧できない場合があります。
まずは、ユーザ登録(無料)を!重要数字講座を無料でご覧いただけます
会社名 | エクシム株式会社 |
住所 | 〒330-0801 埼玉県さいたま市大宮区土手町1-233-1 |
電話番号 | 0120-78-5828 |
FAX番号 | 048-653-7451 |
eラーニング支援部 担当 | 岩中 |
Eメールアドレス | panda@exsim.co.jp |
みなさん、Pythonってご存知でしょうか?
ニシキヘビ。。ではないです。
プログラミング言語のPythonです。
このPython。日本国内では、それほど知名度は高くないのですが、2010年で最も成長したプログラミング言語にも選ばれるなど、急速に人気の高まりつつある言語です。2011年にはPHPとC++を抜かして3位になれそうな勢いです!では、このPython、どうして急に人気がでてきたのでしょうか?理由は大きくわけて3つあると思います。
Pythonが急に普及し始めた理由
これが最大の理由だと思います。Googleのサーバを使って簡単にサービスを提供できます。1日あたり1GBまでの転送なら、料金は一切かかりません ※1。無料利用分を超えて使った場合も、課金設定(1日当たりの支払い額の上限)を設定するだけで、簡単にサーバを増強できます。ロードバランス、データベースのレプリケーション、そんなことは一切考える必要がありません。全部自動でやってくれます。固定費が不要なので、AmazonEC2なんかより、よっぽど敷居は低いです。
これには異論が多いと思います。C、Java、PHPなどとは似ても似つかないソースコード。でも、Python、慣れてしまえば読みやすいですよ。Pythonはインデントに縛られた言語です。プログラムの構造と見た目(インデント)が必ず一致しているので、誰が書いても似たようなソースコードになります。慣れないうちは思うように書き進められないかもしれませんが、しばらく使い込めば「読みやすいコード」が自然にかけるようになっているはずです。
Pythonはスクリプト言語です。コンパイル言語と比べると桁違いに遅いです。でも、Webアプリケーションのボトルネックって、言語ではないですよね?多くの場合、データベースアクセスや、ネットワーク通信、マルチメディアファイルのダウンロードがボトルネックです。スクリプト言語の遅さが問題になっていたのは10年前の話です。今は、PHPだって、RoRだって、Pythonだって実用上問題ない速度で動作します。1番にもつながりますが、言語の速度ではなく、スケールアウトするかどうか、つまり、サーバの台数に応じてきちんと性能が伸びるかが問題なのです。
※1 CPUの使用時間(無料分: 6.5時間/日)なども課金対象ですが、通信量制限(無料分: 1GB/日)が最も課金対象になりやすいです。
Pythonを使う○○個の理由とか並べてても、実際に使ってみないと説得力がないので、実際につかってみた。ソースコードも全文貼り付けていますが、初心者が書いたコードなのであまり信用しないで頂けると幸いです。
GAEからサーバの監視をしてみた。HTTPリクエストの応答時間を計るだけのシンプルなサービスだが、安定して稼動している。社内のサーバは、Zabbixなどを活用してデータセンタ内からきっちり監視しているが、データセンタと外部との回線の障害などに関しては、外部からの監視が有用だ。(スクリーンショットに掲載したデータは私が個人的に借りているサーバものです)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 | #!/usr/bin/env python import cgi import datetime import wsgiref.handlers import urllib import appengine_utilities.sessions import os from datetime import datetime from datetime import timedelta from google.appengine.api.urlfetch import fetch from google.appengine.ext import db from google.appengine.api import users from google.appengine.ext import webapp from google.appengine.api import images from google.appengine.api.labs import taskqueue class Site(db.Model): date = db.DateTimeProperty(auto_now_add=True) name = db.StringProperty() url = db.URLProperty() class Log(db.Model): date = db.DateTimeProperty(auto_now_add=True) response = db.FloatProperty() url = db.URLProperty() class MainPage(webapp.RequestHandler): def get(self): session = appengine_utilities.sessions.Session() if "admin" in session: self.response.out.write('<html><head><title>Response Monitor!!</title></head><body>') self.response.out.write('<form method="post" action="/"><input type="submit" value="logout"/></form>') self.response.out.write('[ <a href="http://blog.elearning.co.jp?s=add&search_404=1">+</a> ]<br />') sites = db.GqlQuery("SELECT * FROM Site ORDER BY date DESC LIMIT 10") for site in sites: self.response.out.write('[ <a href="#" onclick="if(confirm(\'Are you sure to delete it?\'))location.href=\'/delete?id=%s\'">delete</a> ] ' % (site.key())) self.response.out.write('<a href="/detail/%s">%s</a> [ %s ]<br />' % (site.url, site.name, site.url)) self.response.out.write("</body></html>") else: self.response.out.write('<html><head><title>Response Monitor!!</title></head><body>') self.response.out.write('<form method="post" action="/"><input type="password" name="password"/><input type="submit" value="login"/></form>') sites = db.GqlQuery("SELECT * FROM Site ORDER BY date DESC LIMIT 10") for site in sites: self.response.out.write('<a href="/detail/%s">%s</a> [ %s ]<br />' % (site.url, site.name, site.url)) self.response.out.write("</body></html>") def post(self): session = appengine_utilities.sessions.Session() if self.request.get("password") == "hakodate2010": session["admin"] = 1 else: if "admin" in session: del session["admin"] self.redirect('/') class Detail(webapp.RequestHandler): def get(self, key): self.response.out.write('<html><head><title>Log for %s</title></head><body>' % urllib.unquote(key)) self.response.out.write("Log for '%s'" % urllib.unquote(key)) self.response.out.write("<br />") responseMap = {}; for i in range(0,4): query = db.GqlQuery("SELECT * FROM Log WHERE url = :1 ORDER BY date DESC LIMIT %s, 1000" % (1000 * i) , urllib.unquote(key) ); for log in query: log.date+=timedelta(hours=9) day = str(log.date)[0:10] hour = str(log.date)[11:13] if day not in responseMap: responseMap[day] = {} if hour not in responseMap[day]: responseMap[day][hour] = {} responseMap[day][hour][log.date] = log.response self.response.out.write('<table border=1 style="border-style:solid ">') self.response.out.write("<tr><td></td>") for day in sorted(list(responseMap)): self.response.out.write("<td>") self.response.out.write(day) self.response.out.write("</td></tr>") for hour in range(0,24): hour = "%02d" % hour self.response.out.write("<tr>") self.response.out.write("<td>%s</td>" % hour) for day in sorted(list(responseMap)): self.response.out.write('<td valign="top">') if hour in responseMap[day]: limitter = 12 for log in sorted(list(responseMap[day][hour])): limitter = limitter - 1 if limitter < 0: break if responseMap[day][hour][log] == 0: self.response.out.write("<font color=red>") self.response.out.write(str(log)[14:19] + " ERR ") elif responseMap[day][hour][log] < 1.5 and responseMap[day][hour][log] != 0: self.response.out.write("<font>") self.response.out.write(str(log)[14:19] + " %.3f" % responseMap[day][hour][log]) elif responseMap[day][hour][log] < 3: self.response.out.write('<font color="#FF8135">') self.response.out.write(str(log)[14:19] + " %.3f" % responseMap[day][hour][log]) else: self.response.out.write('<font color="#FFBF00">') self.response.out.write(str(log)[14:19] + " %.3f" % responseMap[day][hour][log]) self.response.out.write("</font><br />") self.response.out.write("</td>") self.response.out.write("</tr>") self.response.out.write("</table>") self.response.out.write('<div><a href="/">back</a></div>') self.response.out.write('</body></html>') class Cron(webapp.RequestHandler): def get(self): size = 5 sites = db.GqlQuery("SELECT * FROM Site ORDER BY date DESC") for i in range(0, sites.count(), size): params = {} for j in range(0, size): if i + j >= sites.count(): break params["url"+str(j)] = sites[i+j].url taskqueue.add(url='/worker', params = params) class Worker(webapp.RequestHandler): def post(self): if(int(self.request.headers.environ['HTTP_X_APPENGINE_TASKRETRYCOUNT']) > 0): return for key in self.request.arguments(): try: url = self.request.get(key) fetchAndLog(url) except: pass class Add(webapp.RequestHandler): def get(self): self.response.out.write(""" <form action="/add" method="post" enctype='multipart/form-data'> <div>Name: <input type="text" name="name" /></div> <div>URL: <input type="text" name="url" /></div> <div><input type="submit" value="submit"/></div> </form>""") def post(self): if self.request.get('name') != '' or self.request.get('url') != '': site = Site() site.url = self.request.get('url') site.name = self.request.get('name') site.put(); self.redirect('/') class Delete(webapp.RequestHandler): def get(self): Site.get(self.request.get('id')).delete() self.redirect('/') def fetchAndLog(url): log = Log() log.url = url log.response = 0.0 log.put() start = datetime.now() ret = fetch(url = url, deadline = 30) end = datetime.now() diff = end - start log.response = diff.seconds + diff.microseconds / 1000000.0 log.put() application = webapp.WSGIApplication([ ('/', MainPage), ('/add', Add), ('/delete', Delete), ('/cron', Cron), ('/worker', Worker), ('/detail/(.*)', Detail), ], debug=True) def main(): wsgiref.handlers.CGIHandler().run(application) if __name__ == '__main__': main() |
GAEって静的ファイルおけないんでしょ?ってよく言われるので、アップロードしたZIPファイルを展開して公開するサービスを作ってみた。ファイルはデータストアに保存しているので厳密な意味では静的ファイルではない。(静的ファイルをデプロイすることもできますが、その場合、GAEの管理ツールを使わないとファイルを更新できません。)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 | #!/usr/bin/env python import cgi import datetime import wsgiref.handlers from google.appengine.ext import db from google.appengine.api import users from google.appengine.ext import webapp from google.appengine.api import images class Entry(db.Model): content = db.StringProperty(multiline=True) date = db.DateTimeProperty(auto_now_add=True) data = db.BlobProperty() contentType = db.StringProperty() class MainPage(webapp.RequestHandler): def get(self): self.response.out.write('<html><body>[ <a href="http://blog.elearning.co.jp?s=add&search_404=1">+</a> ]<br />') entries = db.GqlQuery("SELECT * FROM Entry ORDER BY date DESC LIMIT 10") for entry in entries: self.response.out.write('[<a href="#" onclick="if(confirm(\'Are you sure to delete it?\'))location.href=\'/delete?id=%s\'">d</a>][<a href="http://blog.elearning.co.jp?s=edit?id=%s&search_404=1">e</a>] %s<br />' % (entry.key(), entry.key(), cgi.escape(entry.content))) if entry.data: self.response.out.write('<a href="/image/%s/data"><img src="/image/%s/thumnail"/></a><br />' % (entry.key(),entry.key())) self.response.out.write("</body></html>") class Get(webapp.RequestHandler): def get(self, key): image = db.get(key) if type == 'thumnail': self.response.headers['Content-Type'] = 'image/jpeg' self.response.out.write(image.thumnail) else: if image.contentType: self.response.headers['Content-Type'] = image.contentType.encode('utf-8') else: self.response.headers['Content-Type'] = 'image/jpeg' self.response.out.write(image.data) class Add(webapp.RequestHandler): def get(self): self.response.out.write(""" <form action="/add" method="post" enctype='multipart/form-data'> <div><textarea name="content" rows="3" cols="60"></textarea></div> <div><input type="file" name="file"/></div> <div><input type="submit" value="submit"/></div> </form>""") def post(self): if self.request.get('content') != '' or self.request.get('file') != '': entry = Entry() entry.content = self.request.get('content') if self.request.get('file'): entry.data = self.request.POST.get('file').file.read() img = images.Image(entry.data) img.resize(60, 100) entry.contentType = self.request.body_file.vars['file'].headers['content-type'] entry.put(); self.redirect('/') class Edit(webapp.RequestHandler): def get(self): post = Entry.get(self.request.get('id')) self.response.out.write(""" <form action="/edit?id=%s" method="post"> <div><textarea name="content" rows="3" cols="60">%s</textarea></div> <div><input type="submit" value="submit"/></div> </form>""" % (self.request.get('id'), post.content)) def post(self): entry = Entry.get(self.request.get('id')) entry.content = self.request.get('content') entry.put() self.redirect('/') class Delete(webapp.RequestHandler): def get(self): Entry.get(self.request.get('id')).delete() self.redirect('/') application = webapp.WSGIApplication([ ('/', MainPage), ('/add', Add), ('/get/([-\w]+)', Get), ], debug=True) def main(): wsgiref.handlers.CGIHandler().run(application) if __name__ == '__main__': main() |
ブログシステムを作ってみた。一覧表示ページ、個別記事ページ、タグページぐらいしかないが、一般的な用途ならこれぐらいでいい気がする。RSSを配信しているので、FeedTweetなどを使ってTwttterに更新履歴を流したりもできる。Wordpressとなどと比べると機能も少ないし、デザインもテンプレート化できていないが、レスポンスはよいし、満足して使っている。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 | #!/usr/bin/env python # -*- coding: utf-8 -*- from google.appengine.ext import webapp from google.appengine.ext.webapp import util from google.appengine.ext import db from google.appengine.api import users import urllib, datetime, re step = 10 title = "Python blog system" class AuthHandler(webapp.RequestHandler): def get(self, key = ""): if users.get_current_user() == None: self.write("<a href="%s">Sign in or register</a>." % users.create_login_url("/admin")) elif users.is_current_user_admin() != True: self.write('Your account %s is not admin. <a href="%s">Log out</a> and log in with an admin account.' % (users.get_current_user(), users.create_logout_url("/admin"))) else: if key: self.get2(key) else: self.get2() def post(self, key = ""): if users.is_current_user_admin(): if key: self.post2(key) else: self.post2() def write(self, str): self.response.out.write(str) class MainHandler(AuthHandler): def get(self, pageStr): try: page = int(pageStr) except ValueError: page = 0 printHeader(self, title) self.write('<h1><a href="/">%s</a></h1>' % title) if users.is_current_user_admin(): self.write('<h2>[<a href="http://blog.elearning.co.jp?s=&search_404=1">New</a>] [<a href="%s">Log out</a>]</h2>' % users.create_logout_url("/")) entries = Entry.all().order("-datetime").fetch(step + 1, page * step) for entry in entries[:step]: printEntry(self, entry) if len(entries) > step: self.write('[ <a href="/%d"> Next %d</a> ]' % (page + 1, step)) if page > 0: self.write('[ <a href="/%d"> Prev %d</a> ]' % (page - 1, step)) printFooter(self) class RSSHandler(AuthHandler): def get(self, pageStr): self.write( u"""< ?xml version="1.0" encoding="utf-8"?> <rdf:rdf xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://purl.org/rss/1.0/"> <channel rdf:about="http://python-blog-system.appspot.com/"> <title>%(title)s</title> <link>http://python-blog-system.appspot.com</link> <description>%(title)s</description> <dc:language>ja</dc:language> <dc:creator>N/A</dc:creator> <dc:date>%(now)s</dc:date> </channel>""" % {'now' : '2010-12-31T16:57:12+09:00', 'title' : title}) for entry in Entry.all().order("-datetime").fetch(30): self.write(""" <item rdf:about="http://python-blog-system.appspot.com/entry/%(key)s"> <title>%(title)s</title> <link>http://python-blog-system.appspot.com/entry/%(key)s</link> <description>%(body)s</description> <dc:date>%(datetime)s</dc:date> </item> """ % {"key" : entry.key(), "title" : h(entry.title), "body" : h(entry.body), "datetime" : entry.formattedDatetimeInJST}) self.write("</rdf:rdf>") class AdminHandler(AuthHandler): def get2(self, key): self.redirect("/") class PostHandler(AuthHandler): def get2(self,key = ""): entry = Entry.get(key) if key != '' else Entry() title = "Edit Entry" if key!= '' else "New Entry" deleteButton = """<input type="button" value="delete" onclick="if(confirm('Are you sure to delete it?'))location.href='/delete/%s'"/>""" % key if key!= '' else '' printHeader(self, title) self.write("<h1>%s</h1>" % title) self.write(u"""<form method="post" action="/post/%(key)s"> <h2>タイトル</h2><input type="text" name="title" value="%(title)s" style="width:400px"/> <h2>本文</h2><textarea name="body" style="width:400px;height:300px;">%(body)s</textarea> <h2>タグ</h2><input type="text" name="tags" value="%(tags)s" style="width:400px"/> <h2>画像 [<a href="http://blog.elearning.co.jp?s=uploader&search_404=1" target="_blank">uploader</a>]</h2> <div>%(deleteButton)s<input type="submit" value="submit"/></div></form>""" % {"key" : key, "title" : entry.title, "body" : entry.body, "tags" : entry.tagStr(), "deleteButton":deleteButton}) printFooter(self) def post2(self, key = ""): if self.request.get("title") != '' and self.request.get("body") != '': entry = Entry.get(key) if key != '' else Entry() entry.title = self.request.get("title") entry.body = self.request.get("body") entry.tags = [] for tagStr in self.request.get('tags').replace(u' ',' ').replace(' ',' ').replace(',',' ').split(' '): tag = Tag.all().filter("tag =", tagStr).get() if tag == None: tag = Tag(tag = tagStr) tag.put() entry.tags.append(tag.key()) entry.put() self.redirect('/') class PostCommentHandler(AuthHandler): def post(self, key): if self.request.get("comment") != '': Comment( entry = Entry.get(key), comment = self.request.get("comment"), delpass = self.request.get("delpass"), nickname = self.request.get("nickname") ).put() self.redirect("/entry/%s" % key) class DeleteHandler(AuthHandler): def get2(self, key): db.delete(Entry.get(key)) self.redirect('/') class DeleteCommentHandler(AuthHandler): def post(self, key): comment = Comment.get(key) entry_key = comment.entry.key() self.write(self.request.get("delpass")) self.write(comment.delpass) if self.request.get("delpass") == comment.delpass: db.delete(comment) self.redirect('/entry/%s' % entry_key) class TagHandler(AuthHandler): def get(self, key): tagStr = urllib.unquote(key).decode('utf-8') title = "Python blog system / %s" % tagStr printHeader(self, title); tag = Tag.all().filter("tag =", tagStr).get() self.write('<h1><a href="/">Python blog system</a> / %s</h1>' % h(tagStr)) if tag: for entry in tag.entries: printEntry(self, entry) else: self.write("<h2>Tag %s does not exist</h2>" % h(tagStr)) printFooter(self) class EntryHandler(AuthHandler): def get(self, key): entry = Entry.get(key) printHeader(self, "%s / %s" % (title, entry.title)); self.write('<h1><a href="/">%s</a></h1>' % title) printEntry(self, entry, commentDetail = True) printFooter(self) class UploaderHandler(AuthHandler): def get2(self, key): printHeader(self, "Uploader") self.write("<h1>Uploader</h1>") for image in Image.all(): self.write('<h2><img src="/image/%(key)s"/><br /><input type="text" value="[img:%(key)s]" style="width:300px;font-size:x-small"/><input type="button" value="delete" onclick="location.href=\'/deleteImage/%(key)s\'"/></h2>' % {"key":image.key()}) self.write(u'<h2><form action="/uploader" enctype="multipart/form-data" method="post"><input type="file" name="file"/><input type="submit" value="Upload"/></form></h2>') printFooter(self) def post2(self, key): if self.request.get('file'): self.write("hoge") image = Image() image.image = self.request.POST.get('file').file.read() image.contentType = self.request.body_file.vars['file'].headers['content-type'] image.put() self.redirect('/uploader') class DeleteImageHandler(AuthHandler): def get2(self, key): Image.get(key).delete() self.redirect('/uploader') class ImageHandler(AuthHandler): def get(self, key): image = Image.get(key) self.response.headers['Content-Type'] = image.contentType.encode('utf-8') self.response.out.write(image.image) def printEntry(self, entry, commentDetail = False): user = users.get_current_user() if user: editLink = '[<a href="/post/%s">edit</a>]' % entry.key() else: editLink = '' self.write('<div class="entry">\n<div class="entryHeader">\n') self.write('<h2 class="title"><a href="/entry/%(key)s">%(title)s</a> %(editLink)s</h2> <div class="entryDate">%(datetime)s</div>' % {"key" : entry.key(), "title" : h(entry.title), "editLink" : editLink, "datetime" : entry.formattedDatetimeInJST}) self.write('</div>\n')#header self.write(replaceImages(linkURLs(nl2br(h(entry.body))))); self.write('\n<div class="entryFooter">tag:\n') for tag in entry.tags: tagObj = Tag.get(tag) self.write('<a href="/tag/%s"><span class="tag">%s</span></a>\n' % (urllib.quote_plus(tagObj.tag.encode('utf-8')) ,h(tagObj.tag))) if commentDetail: self.write(u'<h2>コメント</h2><div class="comments"><a name="comments">\n') for comment in entry.comments.order('datetime'): if comment.nickname == None or comment.nickname == "": comment.nickname = "Anonymous" delbutton = u""" <div style="float:right"> <form method="post" name="form" action="/deleteComment/%(key)s"> <input type="text" name="delpass" class="delcommentpassword"/> <input type="button" onclick="if(confirm('本当に削除しますか?'))form.submit()" value="削除" class="delcommentbutton"/> </form> </div><br clear="all"/>""" % {"key":comment.key()} self.write('<h3 class="comment">%s: %s %s</h3>' % (comment.nickname, comment.comment, delbutton)) self.write(u'<div style="width:84px;float:left;font-size:xx-small;position:relative;top:6px;">名前</div>') self.write(u'<div style="width:184px;float:left;font-size:xx-small;position:relative;top:6px;">コメント</div>') self.write(u'<div style="width:100px;float:left;font-size:xx-small;position:relative;top:6px;">削除パス</div>') self.write(u'<br clear="all"/>') self.write(u'<form action="/postComment/%s" method="post" style="padding:0">' % entry.key()) self.write(u'<input type="text" name="nickname" style="width:80px;"/>') self.write(u'<input type="text" name="comment" style="width:180px;"/>') self.write(u'<input type="text" name="delpass" style="width:50px;"/>') self.write(u'<input type="submit" value="投稿" style="width:50px"/>') self.write("</form></a></div>\n") else: self.write(u'<a href="/entry/%s#comments">コメント(%s)</a>\n' % (entry.key(), entry.comments.count())) self.write("</div>\n")#footer self.write("</div>\n")#entry def urlReplacer(match, limit = 45): return '<a href="%s" target="_blank">%s</a>' % (match.group(), match.group()[:limit] + ('...' if len(match.group()) > limit else '')) def linkURLs(str): return re.sub(r'([^"]|^)(https?|ftp)(://[\w:;/.?%#&=+-]+)', urlReplacer, str) def replaceImages(str): return re.sub(r'\[img:(.*)\]', r'<img src="http://blog.elearning.co.jp?s=\1&search_404=1" style="max-width:400px"/>', str) def printHeader(self, title): self.write("""< ?xml version="1.0" encoding="UTF-8"?> < !DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja"> <head> <link rel="alternate" type="application/rss+xml" title="RSS" href="rss"/> <meta http-equiv="content-script-type" content="text/javascript"/> <meta http-equiv="content-type" content="text/html; charset=utf-8"/> <title>%s</title> <link rel="stylesheet" type="text/css" href="/css/style.css"/> <meta name = "viewport" content = "width=420"/> <script type="text/javascript"> var _gaq = _gaq || []; _gaq.push(['_setAccount', 'UA-20245912-2']); _gaq.push(['_trackPageview']); (function() { var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); })(); </script>""" % (h(title))) self.write("</head>\n<body>\n"); def printFooter(self): self.write(u'<div>developed by <a href="http://php6.jp/python/">python練習帳</a></div>\n</body>\n</html>') def nl2br(str): return str.replace('\r\n','\n').replace('\n','<br />\n') class Entry(db.Model): title = db.StringProperty(default = "") body = db.TextProperty(default = "") tags = db.ListProperty(db.Key) datetime = db.DateTimeProperty(auto_now_add = True) @property def formattedDatetimeInJST(self): return (self.datetime + datetime.timedelta(hours=9)).strftime("%Y-%m-%d %H:%M:%S") def tagStr(self): return " ".join([Tag.get(x).tag for x in self.tags]) class Tag(db.Model): tag = db.StringProperty() @property def entries(self): return Entry.all().filter('tags', self.key()).order('-datetime') class Comment(db.Model): comment = db.TextProperty(default = "") entry = db.ReferenceProperty(Entry, collection_name = 'comments') user = db.UserProperty() datetime = db.DateTimeProperty(auto_now_add = True) delpass = db.TextProperty() nickname = db.TextProperty() class Image(db.Model): image = db.BlobProperty() contentType = db.StringProperty() def main(): application = webapp.WSGIApplication([ ('/tag/(.*)', TagHandler), ('/entry/(.*)', EntryHandler), ('/admin/?(.*)', AdminHandler), ('/postComment/?(.*)', PostCommentHandler), ('/post/?(.*)', PostHandler), ('/rss/?(.*)', RSSHandler), ('/deleteComment/?(.*)', DeleteCommentHandler), ('/deleteImage/(.*)', DeleteImageHandler), ('/delete/?(.*)', DeleteHandler), ('/uploader/?(.*)', UploaderHandler), ('/image/(.*)', ImageHandler), ('/(.*)', MainHandler) ], debug=True) util.run_wsgi_app(application) def h(html): return html.replace('&','&').replace('< ','<').replace('>','>').replace('"','"') if __name__ == '__main__': main() |
Pythonの良さをざっと紹介しましたが、どのように感じられましたでしょうか?C、Java、PHPなどに慣れた人にとっては異質なソースコードだと思います。でも、一度慣れてしまうと、すごく合理的で分かりやすい言語だと思います。このブログにPython関連の記事を書き続けるのは気が引けますので、興味を持たれた方はPython練習帳をご覧いただければと思います。
27日にAppleからiPadが発表され、同時にiBooksという形で電子ブック市場への参入も発表されました。iPadではePubという電子ブック規格が採用されていますが、ここで改めて、Amazon Kindleで採用されている電子ブック規格AZW形式についてまとめてみたいと思います。
詳細は、こちらの記事にありますので、ここでは簡単に書きたいと思います。
ePub形式はiPadでも採用され、こちらは米国の電子書籍標準化団体の1つであるInternational Digital Publishing Forum(IDPF)が普及促進するオープンな電子書籍ファイルフォーマット規格です。ベンダー依存が無いため、様々なハードウェア・アプリケーションに採用されています。
また、2009年8月にGoogleブックにおいても、ePubブックス形式でダウンロード出来るようになりました。
(参考:http://www.itmedia.co.jp/news/articles/0908/28/news008.html)
ePub形式の特徴としては、すでに一般化している技術を組み合わせたシンプルな構造にあります。規格は全体の構造を決める「Open Publication Structure」と、XHTML 1.1およびCSS 2.0のサブセットとしてレイアウトに関する取り決めを行う「Open Packaging Format」、ファイルの圧縮形式を定義した「OEBPS Container Format」の3段階に分かれ、それが1つとなってePubを構成しています。
仕様書情報は下記で日本語訳も非公式ながら公開されています。
http://lost_and_found.lv9.org/ops/ops_2.0_final_spec_ja.html
http://lost_and_found.lv9.org/opf/opf_2.0_final_spec_ja.html
日本語も、UTF-8として扱うため十分対応しています。
テキストや画像の書籍コンテンツをXML/XHTMLで作成、それをzip形式で圧縮し、拡張しを”.epub”に変更するとePubコンテンツは出来るようです。
AZW形式はKindleの独自規格です。こちらは完全にKindleの独自規格で、現在のKindle Storeに出回っている電子ブックはAZW形式です。
こちらのAZW形式ですが、AmazonからHTML, XHTML, XML (OPF/IDPF format),そしてePub形式のコンテンツを変換するソフトウェア,KindleGenが公開されています。WindowsとLinuxに対応しているようです。ちなみに、KindleGenは昨年12月に出ています。
今まではKindleが電子ブック市場をかなり独占していた状態でしたが、ePubに切り替えるサービスも徐々に増え、今後の動向に注目したいところです。
また、ePub形式のコンテンツをAZW形式に変換するKindleGenをAmazonが出しており、電子ブック市場は白熱していると言えるといえます。
eラーニング教材を作る
機材等のレンタル