はじめに
「Webアプリをつくりたい!」と思い、JSPとサーブレットを勉強していたところ、プロから「PHPの方が流行ってるよ」と言われ撃沈。
もちろん、Java開発のメリットも多いが、スクリプト言語の攻撃力はとても高い。
ゴリゴリC言語プログラマーとして生きてきたが、時代には巻かれなければと思いPythonのWebアプリケーションフレームワークであるDjangoに手を出した。
チュートリアルが終わったため、次のアイデアを考えていると「2ちゃんねるなら手軽に作れそう!」と思い立つ。
課題研究にこじつけて、「みんなの交流場」的な感じで校内2ちゃんねるを作ることにした。
お前誰やねん
しがない学生
電子回路とマイコン制御ならプロ
Pythonはディープラーニングを実装する時に少し触った程度
HTML・CSSはコピペでなんとかしていく
開発環境
OS : Linux mint 20
言語 : Python 3.9
エディタ : VSC
フレームワーク : Django
Webサーバー : Pythonanywhere.com
目次
まずは完成品
出来上がったものがこちら!
Djangoについて
Djangoは公式ドキュメントがめちゃくちゃわかりやすいので、Docsを読んだほうが良い
実践形式で、「まずはこうしよう」→「実はこんな便利なやり方もある」というパターンが多い。
急いで飛ばし飛ばしにやると間違いなく途中で詰むので素直にひとつひとつこなすのがおすすめ。
2ちゃんねるづくり
ビュー
....
def create_thread(request):
try:
thread = Thread(
thread_text=request.POST['thread_str'],
pub_date=timezone.now(),
latest_date=timezone.now(),
)
except (KeyError):
# Redisplay the thread voting form.
return render(request, 'board/index.html', {
'error_message': "Error",
})
else:
thread.save()
# Always return an HttpResponseRedirect after successfully dealing
# with POST data. This prevents data from being posted twice if a
# user hits the Back button.
return HttpResponseRedirect(reverse('board:index'))
def tweet(request, thread_id):
thread = get_object_or_404(Thread, pk=thread_id)
try:
tweet = thread.response_set.create(
response_text=request.POST['tweet_str'],
name_text=request.POST['name_str'],
tweet_date=datetime.now()
)
except (KeyError):
# Redisplay the thread voting form.
return render(request, 'board/detail.html', {
'thread': thread,
'error_message': "You didn't have a tweet.",
})
else:
tweet.save()
thread.update_date()
thread.save()
# Always return an HttpResponseRedirect after successfully dealing
# with POST data. This prevents data from being posted twice if a
# user hits the Back button.
return HttpResponseRedirect(reverse('board:results', args=(thread.id,)))
チュートリアルを改造し、新規スレッド作成と書き込みを実装した。
エラー処理はかなり雑
モデル
...
class Thread(models.Model):
thread_text = models.CharField(max_length=255)
pub_date = models.DateTimeField('date published')
latest_date = models.DateTimeField('date published')
def __str__(self):
return self.thread_text
def print_pub_date(self):
return (self.pub_date+datetime.timedelta(hours=9)).strftime('%Y-%m-%d %H:%M:%S')#wrong
def update_date(self):
self.latest_date = timezone.now()
def print_latest_date(self):
return (self.latest_date+datetime.timedelta(hours=9)).strftime('%Y-%m-%d %H:%M:%S')#wrong
def print_count_response(self):
return self.response_set.count()
def print_title(self):
if(len(self.thread_text) > 16):
return self.thread_text[0:16]+'...'
else:
return self.thread_text
@ admin.display(
boolean=True,
ordering='pub_date',
description='Published recently?',
)
def was_published_recently(self):
now = timezone.now()
return now - datetime.timedelta(days=1) <= self.pub_date <= now
class Response(models.Model):
thread = models.ForeignKey(Thread, on_delete=models.CASCADE)
response_text = models.CharField(max_length=255)
name_text = models.CharField(max_length=255)
tweet_date = models.DateTimeField('date published')
def __str__(self):
return self.response_text
def print_tweet_date(self):
return (self.tweet_date+datetime.timedelta(hours=9)).strftime('%Y-%m-%d %H:%M:%S')#wrong
タイムゾーン設定はDjango.settingで行っているため、標準出力なら綺麗に出るが内部でテキスト変換するとタイムゾーンがずれる。
関数化しようとも思ったがめんどくさくなりゴリ押しした。
関係 | 内容 | 備考 |
---|---|---|
親 | スレッド | タイトル、作成日、最終更新日 |
子 | レスポンス | レス内容、投稿者、レス日 |
トップページ
...
{% if latest_thread_list %}
{% for thread in latest_thread_list %}
<a href="{% url 'board:detail' thread.id %}" class="btn-flat-double-border">
{{ thread.print_title }} <br>
スレ数 : {{ thread.print_count_response}} <br>
更新日時 : {{ thread.print_latest_date}}<br>
作成日時 : {{ thread.print_pub_date}}</a>
</a>
{% endfor %}
{% else %}
<p>そして誰も居なくなった...</p>
<p>新規スレを立ててね!</p>
{% endif %}
<div class="box17">
<form action="{% url 'board:create_thread' %}" method="post">
{% csrf_token %}
新規スレ:<br>
<textarea name="thread_str" rows="4" class="textarea_width"></textarea> <br>
<input type="submit" value="新規">
<input type="reset" value="リセット">
</form>
</div>
チュートリアルを改造して、2ちゃんねるっぽく作り変えた。
フォーム類はDocsを読まないとよくわからないため、DjangoとHTMLのしっかりとした知識が必要。
ロゴはこのサイトだと適当にオシャンティーなものが作れるのでおすすめ
スレッドページ
...
<ul>
{% for response in thread.response_set.all %}
<li>
{{ forloop.counter }}.{{ response.name_text }} -- {{ response.print_tweet_date }}<br>
{{ response.response_text }}
</li>
{% endfor %}
</ul>
<div class="box17">
<form action="{% url 'board:tweet' thread.id %}" method="post">
{% csrf_token %}
<a name="jump">書き込み</a><br>
<input type="text" value="ななしちゃん" name="name_str" required minlength="1" maxlength="10"> <br>
つぶやき : <br>
<textarea name="tweet_str" rows="4" class="textarea_width"></textarea> <br>
<input type="submit" value="書き込み">
<input type="reset" value="リセット">
</form>
</div>
...
スレッド内のレスを表示し、書き込みを可能にしている。
CSS
こちらのサイトからほぼ全てコピペさせていただいた。
スマホ表示とPC表示の切り替えは苦労した。
HTMLとCSSの知識が不足していて、よくサイトが崩れたのでしっかりと学び直そうと思う