ここまでで、ユーザープロフィールとログインはできましたが、ユーザープロフィールはホームページにリンクが追加されていません。では、追加してみましょう:
<!-- app/templates/base.html -->
<!--...-->
<!DOCTYPE html>
<html lang="en">
<head>
<!--...-->
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<!--...-->
<div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
<a class="dropdown-item" href="{{ url_for('user.user_profile', username=current_user.username) }}">個人情報</a>
<a class="dropdown-item" href="{{ url_for('auth.logout') }}"> </a>
</div>
</nav>
<!--...-->
</body>
<!--...-->
</html>
お気づきかもしれませんが、最近ウェブページの読み込みが非常に遅くなっています。その原因は、ローカルリソースの代わりにCDNを使用しているためです。GitHubにリソースを置いているので、必要であれば自分でダウンロードしてください。以下はローカルからリソースを読み込むコードです:
<!-- app/templates/base.html -->
{# Bootstrapをインポートする-Flaskの組み込み関数は #}
{% from 'bootstrap/nav.html' import render_nav_item %}
{% from 'bootstrap/utils.html' import render_messages %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{% block title %}{% endblock %} {# #}</title>
{# カスタムBootstrapを紹介する css #}
<link rel="stylesheet" href="{{ url_for('static', filename='css/bootstrap.css') }}">
<link rel="stylesheet" href="{{ url_for('static', filename='css/styles.css') }}">
<link rel="stylesheet" href="{{ url_for('static', filename='fonts/font-awesome-4.7.0/css/font-awesome.css') }}">
</head>
<body>
<!--...-->
</body>
{% block scripts %} {# JS #}
<!--jsの紹介-->
<script src="{{ url_for('static', filename='js/jquery.js') }}"></script>
<script src="{{ url_for('static', filename='js/popper.js') }}"></script>
<script src="{{ url_for('static', filename='js/bootstrap.js') }}"></script>
{{ moment.include_moment(local_js=url_for('static', filename='js/moment-with-locales.js')) }}
{{ moment.locale('zh') }} {# フラスコをセットアップする-momentデフォルトの言語は英語だ。 #}
{% endblock %}
</html>
さて、これでリソースの読み込みがかなり速くなりました。それでは本日の本題、問題の追加に入りましょう。
(ヒューヒュー
質問を追加するには、まずデータベースモデルを作成します。models.pyを開き、Questionモデルを作成します:
# app/models.py
# ...
class Question(db.Model):
"""問題モデリング"""
__tablename__ = 'questions'
id = db.Column(db.Integer, primary_key=True)
# 質問タイトル
title = db.Column(db.String(64))
# Markdownテキストをフォーマットする
body_markdown = db.Column(db.Text)
# HTMLテキストをフォーマットする
body_html = db.Column(db.Text)
# パブリッシャーID
author_id = db.Column(db.Integer, db.ForeignKey('users.id'))
def __repr__(self):
return '<Question %d>' % self.id
次に、Userモデルにリレーションシップを追加します:
class User(db.Model, UserMixin): # Userdbから継承したクラス.Model
"""ユーザーモデル"""
__tablename__ = 'users' # テーブル名を定義する
# ...
# 質問
questions = db.relationship('Question', backref='author', lazy='dynamic')
# ...
その後、データベースをアップグレードします:
flask db migrate
flask db upgrade
さて、最も基本的な質問モデルが構築されたので、次はビューを書きましょう。質問ビューを保持するために新しい質問フォルダを作成します。
i>init.py **```テキスト
app/question/init.py
from flask import ブループリント
question = ブループリント('question', name, url_prefix='/question')
から. インポートビュー
i>views.py
**```python
# app/question/views.py
from . import question
from flask_login import current_user, login_required
from flask import request, render_template
from ..models import Question
from ..extensions import db
from .forms import AddQuestionForm
@question.route('/add/', methods=['GET', 'POST'])
@login_required
def add():
form = AddQuestionForm()
if form.validate_on_submit():
title = form.title.data
body_markdown = form.body_markdown.data
# エディターを入手する.md自動生成HTML
body_html = request.form['editormd-html-code']
# 問題を作る
_question = Question(
title=title, body_markdown=body_markdown, body_html=body_html, author=current_user)
db.session.add(_question)
# データベースに保存する
db.session.commit()
return render_template('question/add.html', form=form)
i>forms.py **``python
app/question/forms.py
from wtforms import StringField, TextAreaField, HiddenField, SubmitField from wtforms.validators import DataRequired from flask_wtf importFlaskForm
さて、トリッキーな部分に入ろう:テンプレートだ。
お気づきかもしれないが、このモデルは問題の本体をMarkdownとHTMLの両方のフォーマットで定義しており、すべてMarkdownエディターが必要だ。私が選んだのは
[https://../.md/#%06](ps://../.md/#%06)
バージョン番号はb2cab15だから、必要なら自分で手に入れられるよ。
エディターをダウンロードする.mdそれを解凍し、editormdにリネームし、staticディレクトリに置く。それから、templatesフォルダにquestionフォルダを作成し、問題のJinjaテンプレートを保存する。
i>templates/question/add.html
**```html
<!--app/templates/question/add.html-->
{% extends 'base.html' %}
{% from 'bootstrap/form.html' import render_field %}
{% block title %}問題を作る{% endblock %}
{% block content %}
<div class="container">
<h1>問題を作る</h1>
<hr>
<!--手動フォーム生成-->
<form method="POST" action="{{ url_for('question.add') }}">
<!--WTFCSRFトークンは-->
{{ form.csrf_token() }}
<!--タイトルをレンダリングする-->
{{ render_field(form.title) }}
<!--ボディボックスを手動でレンダリングする-->
<div id="editormd" style="border-radius: 5px;">
{{ form.body_markdown() }}
</div>
<!--投稿ボタンをレンダリングする-->
{{ render_field(form.submit, button_map={'submit': 'primary'}) }}
</form>
</div>
{% endblock %}
{% block scripts %}
{{ super() }}
<!--エディターを読み込む.mdの依存ファイルは-->
<link rel="stylesheet" href="{{ url_for('static', filename='editormd/css/editormd.min.css') }}">
<script src="{{ url_for('static',filename='editormd/editormd.min.js') }}"></script>
<script>
// editor
var editor;
$(function () {
// editor.mdeditormd "divの最初のtextareaを自動的に探してくれる。
editor = editormd('editormd', {
// 立っているテキスト
placeholder: '問題の説明を入力する',
// エディタの高さ
height: 640,
// スクロール・ロック
syncScrolling: 'both',
// editormd依存ライブラリの場所
path: "{{ url_for('static',filename='editormd/lib/') }}",
// コード・フォールディングを有効にする
codeFold : true,
// textareaにhtmlを自動保存する
saveHTMLToTextarea : true,
// 置換検索
searchReplace : true,
//
emoji : true,
// TODO表
taskList : true,
//
tocm: true,
// tex
tex : true,
//
flowChart : true,
//
sequenceDiagram : true,
// イメージアップロードを有効にしない
imageUpload : false
});
});
</script>
{% endblock %}
さて、最も基本的な質問ができました。これがbase.htmlのリンクです:
<!-- app/templates/base.html -->
<!--...-->
<!DOCTYPE html>
<html lang="en">
<head>
<!--...-->
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<!--...-->
<div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
<a class="dropdown-item" href="{{ url_for('question.add') }}">質問を追加する</a>
<a class="dropdown-item" href="{{ url_for('user.user_profile', username=current_user.username) }}">個人情報</a>
<a class="dropdown-item" href="{{ url_for('auth.logout') }}"> </a>
</div>
<!--...-->
</nav>
<br>
{{ render_messages(container=True, dismissible=True, dismiss_animate=True) }} {# Bootstrapを使う-Flask点滅メッセージをレンダリングする組み込み関数 #}
<br>
{% block content %}{% endblock %} {# #}
</body>
<!--...-->
</html>
現在作成されているページは以下のようになります: