So far, we have the user profile and login in place, but the user profile does not have a link on the home page. Now let’s add it:

<! -- app/templates/base.html -->
<! -... -->
<! DOCTYPEhtml>
<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) }}">The personal data</a>
            <a class="dropdown-item" href="{{ url_for('auth.logout') }}">logout</a>
        </div>
    </nav>
    <! -... -->
</body>
<! -... -->

</html>
Copy the code

As you may have noticed, our web pages are now loading very slowly because we are using CDN instead of local resources. We can speed up the process by downloading resources, which I have put on GitHub and can obtain by ourselves if necessary. Here is the code to load the resource locally:

<! } {% 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 block #}</title> {# <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 code block #} <! - the introduction of js - > < script SRC = "{{url_for (' static ', filename = 'javascript/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', Flask-moment locale.locale ('zh-cn')}} {# flask-moment locale.locale ('zh-cn')}} #} {% endblock %} </ HTML >Copy the code

Ok, now you load resources much faster. Let’s move on to today’s topic: adding questions.

ahem

To add problems, first build the database model. Open models.py and create a Question model:

# app/models.py
#...

class Question(db.Model) :
    """ Problem model """
    __tablename__ = 'questions'
    id = db.Column(db.Integer, primary_key=True)
    # Question title
    title = db.Column(db.String(64))
    # Markdown format problem body
    body_markdown = db.Column(db.Text)
    # problem body in HTML format
    body_html = db.Column(db.Text)
    # publisher ID
    author_id = db.Column(db.Integer, db.ForeignKey('users.id'))

    def __repr__(self) :
        return '<Question %d>' % self.id

Copy the code

Then add relationship to the User model:

Class User(db.model, UserMixin): # User class inherits from db.model """ User Model """ __tablename__ = 'users' # define tablename #... Questions = db. Relationship ('Question', backref='author', lazy='dynamic') #Copy the code

After that, update the database:

flask db migrate
flask db upgrade
Copy the code

Ok, now that we have the basic problem model set up, let’s write the view. Create a new Question folder to hold the question view.

i>init.py **“`text

app/question/init.py

from flask import Blueprint

question = Blueprint(‘question’, name, url_prefix=’/question’)

from . import views

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(): Data body_markdown = form.body_markdown.data # Get editor. md automatically generated HTML body_html = Request. Form [' editormd-htmd-code '] # request. Form [' editormd-htmd-code '] # request. body_html=body_html, Db.session.mit () return render_template('question/add.html', form=form)Copy the code

i>forms.py **“`python

app/question/forms.py

from wtforms import StringField, TextAreaField, HiddenField, SubmitField from wtforms.validators import DataRequired from flask_wtf import FlaskForm

Class AddQuestionForm(FlaskForm): Title = StringField(‘ title ‘, Validators =[DataRequired()], render_KW ={‘ Autocomplete ‘: ‘off’, ‘autofocus’: ‘true’}) submit = TextAreaField(‘ introduce ‘) submit = SubmitField(‘ add question ‘)

Okay, now let's do the trickiest part: templates. As you may have noticed, our model defines the problem body in Markdown and HTML format, all of which requires a Markdown editor. I choose here is [https://pandao.github.io/editor.md/#Heading%206] (https://pandao.github.io/editor.md/#Heading%206), it is maintained by the Chinese, So he is very friendly to Chinese. Download editor. md, unzip it, rename it editormd, and place it in the static directory. Then, in the Templates folder, create a Question folder to hold the Jinja templates for the problem. i>templates/question/add.html **```html <! --app/templates/question/add.html--> {% extends 'base.html' %} {% from 'bootstrap/form.html' import render_field %} {% {% endBlock %} {% block content %} <div class="container"> <h1> Create problem </h1> <hr> <! Manually generated form - - - > < form method = "POST" action = "{{url_for (' question. Add ')}}" > <! --> {{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() }} <! <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> $(function () {// editormd editor = editormd('editormd', {// placeholder text placeholder: // syncScrolling: 'both', // EditorMD's path: {{url_for('static',filename='editormd/lib/')}}", // enable code folding codeFold: True, // automatically saveHTMLToTextarea saveHTMLToTextarea: true, // replace searchReplace: true, // emoji: Workflow: flowsheet; // flowChart: flowsheet; // flowChart: flowChart; True, // sequenceDiagram: true, // imageUpload: false}); }); </script> {% endblock %}Copy the code

Ok, now we can create the basic problem. Let’s add a link to 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="{{ </a> <a class="dropdown-item" href="{{url_for('user.user_profile', The username = current_user. Username)}} "> information < / a > < a class =" dropdown can - item "href =" {{url_for (' auth. Logout)}} "> logout < / a > < / div > <! -... --> </nav> <br> {{ render_messages(container=True, dismissible=True, Dismiss_animate =True);}} {# use the bootstrap-flask built-in function to render flash messages #} <br> {% block content %}{% endblock %} -... --> </html>Copy the code

Now the page looks like this:

Okay, I’ll leave you there for today, and I’ll come back. The code for this article has been placed at github.com/samzhangjy/… The version number is B2CAB15, you can get it yourself if necessary.