プログラミング塾の質問・回答コーナーを作りたい。個人ユーザーの質問は無料で受け付け、公開とする。企業ユーザーの質問は別のストアサイトで番号付きのチケットを発行し、それを使用し、非公開とする。

 

【Copilotの答えの始め】

Flask、MySQL Connector、Bootstrapを使用してプログラミング塾の質問・回答コーナーを作成するための基本的な手順を示します。以下のような機能を実装する必要があります。

1. 環境設定

最初に、必要なパッケージをインストールします。

1
pip install Flask mysql-connector-python Flask-Bootstrap

2. データベースの設計

まず、データベースのテーブルを設計します。例えば、usersquestionsanswersticketsテーブルを作成します。

users テーブル

1
2
3
4
5
CREATE TABLE users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    username VARCHAR(100) NOT NULL,
    user_type ENUM('individual', 'corporate') NOT NULL
);

questions テーブル

1
2
3
4
5
6
7
CREATE TABLE questions (
    id INT AUTO_INCREMENT PRIMARY KEY,
    user_id INT,
    question_text TEXT,
    is_public BOOLEAN,
    FOREIGN KEY (user_id) REFERENCES users(id)
);

tickets テーブル(企業ユーザーの質問を管理)

1
2
3
4
5
6
7
8
CREATE TABLE tickets (
    id INT AUTO_INCREMENT PRIMARY KEY,
    user_id INT,
    question_id INT,
    ticket_number VARCHAR(50),
    FOREIGN KEY (user_id) REFERENCES users(id),
    FOREIGN KEY (question_id) REFERENCES questions(id)
);

3. Flaskアプリの構築

次に、Flaskアプリを作成し、MySQLデータベースに接続します。

 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
from flask import Flask, render_template, request, redirect, url_for
from flask_bootstrap import Bootstrap
import mysql.connector

app = Flask(__name__)
Bootstrap(app)

# MySQLデータベースに接続
db = mysql.connector.connect(
    host="localhost",
    user="root",
    password="password",
    database="your_database_name"
)

@app.route('/')
def index():
    return render_template('index.html')

# 質問の表示と投稿用ルート
@app.route('/questions')
def questions():
    cursor = db.cursor(dictionary=True)
    cursor.execute("SELECT * FROM questions WHERE is_public = TRUE")
    questions = cursor.fetchall()
    return render_template('questions.html', questions=questions)

@app.route('/ask', methods=['GET', 'POST'])
def ask():
    if request.method == 'POST':
        user_id = request.form['user_id']
        question_text = request.form['question_text']
        is_public = True if request.form['user_type'] == 'individual' else False
        
        cursor = db.cursor()
        cursor.execute("INSERT INTO questions (user_id, question_text, is_public) VALUES (%s, %s, %s)",
                       (user_id, question_text, is_public))
        db.commit()
        
        if not is_public:
            question_id = cursor.lastrowid
            ticket_number = generate_ticket_number()
            cursor.execute("INSERT INTO tickets (user_id, question_id, ticket_number) VALUES (%s, %s, %s)",
                           (user_id, question_id, ticket_number))
            db.commit()
        
        return redirect(url_for('questions'))
    return render_template('ask.html')

def generate_ticket_number():
    import random
    return 'TICKET-' + str(random.randint(1000, 9999))

if __name__ == '__main__':
    app.run(debug=True)

4. Bootstrapによるフロントエンドの構築

テンプレートファイルを作成し、Bootstrapを使用してユーザーインターフェースを設計します。

index.html

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <title>プログラミング塾 - 質問・回答コーナー</title>
    <link href="{{ url_for('static', filename='bootstrap.min.css') }}" rel="stylesheet">
</head>
<body>
    <div class="container">
        <h1>プログラミング塾 - 質問・回答コーナー</h1>
        <a href="{{ url_for('questions') }}" class="btn btn-primary">質問を見る</a>
        <a href="{{ url_for('ask') }}" class="btn btn-secondary">質問を投稿する</a>
    </div>
</body>
</html>

questions.html

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <title>公開質問一覧</title>
    <link href="{{ url_for('static', filename='bootstrap.min.css') }}" rel="stylesheet">
</head>
<body>
    <div class="container">
        <h1>公開質問一覧</h1>
        <ul>
            {% for question in questions %}
                <li>{{ question.question_text }}</li>
            {% endfor %}
        </ul>
        <a href="{{ url_for('index') }}" class="btn btn-secondary">戻る</a>
    </div>
</body>
</html>

ask.html

 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
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <title>質問を投稿</title>
    <link href="{{ url_for('static', filename='bootstrap.min.css') }}" rel="stylesheet">
</head>
<body>
    <div class="container">
        <h1>質問を投稿</h1>
        <form method="post">
            <div class="form-group">
                <label for="user_id">ユーザーID</label>
                <input type="text" class="form-control" id="user_id" name="user_id" required>
            </div>
            <div class="form-group">
                <label for="question_text">質問内容</label>
                <textarea class="form-control" id="question_text" name="question_text" required></textarea>
            </div>
            <div class="form-group">
                <label for="user_type">ユーザータイプ</label>
                <select class="form-control" id="user_type" name="user_type" required>
                    <option value="individual">個人</option>
                    <option value="corporate">企業</option>
                </select>
            </div>
            <button type="submit" class="btn btn-primary">送信</button>
        </form>
        <a href="{{ url_for('index') }}" class="btn btn-secondary">戻る</a>
    </div>
</body>
</html>

これで、Flask、MySQL Connector、Bootstrapを使用して基本的な質問・回答コーナーを作成する手順が理解できたと思います。これらの基本を基にして、さらに機能を追加したり、デザインを改善したりすることができます。

 

【Copilotの答えの終わり】

 

回答関連の画面とコントローラーも

 

【Copilotの答えの始め】
 

了解しました!次に、回答関連の画面とコントローラーを追加しましょう。

Flaskアプリの更新

1. 回答の表示と投稿のルート

Flaskアプリに回答を表示し、投稿するための新しいルートを追加します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
@app.route('/question/<int:question_id>', methods=['GET', 'POST'])
def question(question_id):
    if request.method == 'POST':
        answer_text = request.form['answer_text']
        cursor = db.cursor()
        cursor.execute("INSERT INTO answers (question_id, answer_text) VALUES (%s, %s)", (question_id, answer_text))
        db.commit()
        return redirect(url_for('question', question_id=question_id))
    
    cursor = db.cursor(dictionary=True)
    cursor.execute("SELECT * FROM questions WHERE id = %s", (question_id,))
    question = cursor.fetchone()

    cursor.execute("SELECT * FROM answers WHERE question_id = %s", (question_id,))
    answers = cursor.fetchall()

    return render_template('question.html', question=question, answers=answers)

2. 回答画面のテンプレート

question.html

 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
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <title>質問と回答</title>
    <link href="{{ url_for('static', filename='bootstrap.min.css') }}" rel="stylesheet">
</head>
<body>
    <div class="container">
        <h1>質問と回答</h1>
        <h2>質問: {{ question.question_text }}</h2>

        <h3>回答一覧</h3>
        <ul>
            {% for answer in answers %}
                <li>{{ answer.answer_text }}</li>
            {% endfor %}
        </ul>

        <h3>新しい回答を投稿</h3>
        <form method="post">
            <div class="form-group">
                <label for="answer_text">回答内容</label>
                <textarea class="form-control" id="answer_text" name="answer_text" required></textarea>
            </div>
            <button type="submit" class="btn btn-primary">送信</button>
        </form>
        <a href="{{ url_for('questions') }}" class="btn btn-secondary">戻る</a>
    </div>
</body>
</html>

これにより、質問に対して回答を投稿し、表示する機能が追加されます。

3. データベースの更新

回答関連のテーブルをすでに作成しているため、特に変更は必要ありません。ただし、必要に応じてフィールドやインデックスを追加することもできます。

これで、質問・回答コーナーに必要な基本機能が揃いました。

 

【Copilotの答えの終わり】

 

 

 

 

熱帯夜絵画の融ける茶褐色