LoginSignup
1
5

More than 1 year has passed since last update.

【Django】校内2ちゃんねるをつくる【Pythonanywhere】

Last updated at Posted at 2021-10-17

はじめに

「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

目次

  1. まずは完成品
  2. Djangoについて
  3. 2ちゃんねるづくり
  4. Pythonanywhereについて
  5. 参考

まずは完成品

出来上がったものがこちら!

Djangoについて

Djangoは公式ドキュメントがめちゃくちゃわかりやすいので、Docsを読んだほうが良い

実践形式で、「まずはこうしよう」→「実はこんな便利なやり方もある」というパターンが多い。
急いで飛ばし飛ばしにやると間違いなく途中で詰むので素直にひとつひとつこなすのがおすすめ。

2ちゃんねるづくり

ビュー

views.py
....

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,)))

チュートリアルを改造し、新規スレッド作成と書き込みを実装した。
エラー処理はかなり雑

モデル

models.py

...

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で行っているため、標準出力なら綺麗に出るが内部でテキスト変換するとタイムゾーンがずれる。
関数化しようとも思ったがめんどくさくなりゴリ押しした。

関係 内容 備考
スレッド タイトル、作成日、最終更新日
レスポンス レス内容、投稿者、レス日

トップページ

index.html

...

{% 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のしっかりとした知識が必要。

ロゴはこのサイトだと適当にオシャンティーなものが作れるのでおすすめ

スレッドページ

detail.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の知識が不足していて、よくサイトが崩れたのでしっかりと学び直そうと思う

1
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
5