Flask sets the avatar and creates the post model class

We often see on some websites that if the user does not have a custom avatar, an avatar will be generated for each user, which makes the website look more beautiful. How is this achieved? There is a plugin in Flask called Flask-avatars that provides avatar solutions. It integrates various avatar solutions. Let’s explain it below.

1. Install

pip install flask-avatars

2. Initialization

Extensions need to be initialized in the usual way before they can be used:

from flask_avatars import Avatars

app = Flask(__name__)
avatars = Avatars(app)

3. Configuration

The available configuration options are listed below:

4. Avatar

Flask-Avatarsavatars provides an object in the template context that you can use to get the avatar URL.

1. Gravatar:
Regarding what is Gravatar, here is an introduction from Wikipedia for readers’ reference:

On Gravatar, users can sign up for an account with their email and upload an avatar tied to it. Many popular blog programs support Gravatar, including famous blog programs such as WordPressTypecho. When a user posts a comment and fills in his email address, the blog program will automatically check whether there is an avatar bound to it on Gravatar. If available, the avatar will be displayed with the comment. WordPress v2.5 began to provide native support for Gravatar. In addition, there are many programs that support Gravatar through plug-ins, such as the forum program Discuz!.

A Gravatar avatar can use images up to 512 pixels, and by default it will be displayed in 80*80 size. If the uploaded avatar is not of this size, Gravatar will scale the avatar. Users can determine their avatar level according to the MPAA grading system, so that webmasters can display appropriate avatars on their sites.

In order to prevent the user's email address from being leaked and receive a large amount of spam, Gravatar uses the email address through MD5 hash operation when delivering the user's email address.

For more information on Gravatar, please refer to: https://zh.wikipedia.org/wiki/Gravatar

You can use avatars.gravatar() to get the avatar URL provided by Gravatar, passing the email hash:

<img src="{<!-- -->{ avatars.gravatar(email_hash) }}"/>

You can get email hash like this:

import hashlib

avatar_hash = hashlib.md5(my_email.lower().encode('utf-8')).hexdigest()

2. Logo generation
Flask-Avatars provides an Identicon class that generates identicon avatars, and most of the code is based on random avatars. First, you need to set the configuration variable AVATARS_SAVE_PATH to tell Flask-Avatars the path to save the generated avatars. Generally speaking, we will generate an avatar when creating a user record, so the best place to generate an avatar is in the user database model class:

First create a new avatars object in exts

from flask_avatars import Avatars
avatars = Avatars()

in app.py

When registering, it is saved to the database

The path to save the avatar in the configuration file config

# Avatar configuration
AVATARS_SAVE_PATH = os.path.join(BASE_DIR, "media", "avatars")

Create a new media/avatars under the root path of the project to store all avatars
Then create a new media package/views file in apps

Register to save avatar

User uploads a custom image

@bp.post("/avatar/upload")
@login_required
def upload_avatar():
    form = UploadImageForm(request.files)
    if form. validate():
        image = form.image.data
        # Do not use the file name uploaded by the user, otherwise it is easy to be hacked
        filename = image.filename
        # xxx.png, xx.jpeg split to get the suffix name
        _, ext = os.path.splitext(filename)
        filename = md5((g.user.email + str(time.time())).encode("utf-8")).hexdigest() + ext
        image_path = os.path.join(current_app.config['AVATARS_SAVE_PATH'], filename)
        image. save(image_path)
        # Depending on personal needs, whether to modify the user's avatar field immediately after the image upload is completed
        g.user.avatar = filename
        db.session.commit()
        return restful.ok(data={<!-- -->"avatar": filename})
    else:
        message = form. messages[0]
        return restful.params_error(message=message)
class UploadImageForm(BaseForm):
    image = FileField(validators=[FileAllowed(['jpg', 'jpeg', 'png'], message="The image format does not meet the requirements!"), FileSize(max_size=1024*1024*5, message="The image is the largest Cannot exceed 5M!")])

Signature

@bp.post("/profile/edit")
@login_required
def edit_profile():
    form = EditProfileForm(request. form)
    if form. validate():
        signature = form. signature. data
        g.user.signature = signature
        db.session.commit()
        return restful. ok()
    else:
        return restful.params_error(message=form.messages[0])
class EditProfileForm(BaseForm):
    signature = StringField(validators=[Length(min=1, max=50, message="The length of the personalized signature is between 1-50 words!")])

Initialization of command line custom commands

Increase the model class of the plate

from exts import db
from datetime import datetime
# from sqlalchemy_serializer import SerializerMixin

# Post section model class
class BoardModel(db.Model):
    serialize_only = ("id", "name", "priority", "create_time")
    __tablename__ = "board"
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    name = db.Column(db.String(20), unique=True)
    # Block weight
    priority = db.Column(db.Integer, default=1)
    create_time = db.Column(db.DateTime, default=datetime.now)

# posts
class PostModel(db.Model):
    serialize_only = ("id", "title", "content", "create_time", "board", "author")
    __tablename__ = "post"
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    title = db.Column(db.String(200), nullable=False)
    content = db.Column(db.Text, nullable=False)
    create_time = db.Column(db.DateTime, default=datetime.now)
    # Post section foreign key
    board_id = db.Column(db.Integer, db.ForeignKey("board.id"))
    # author
    author_id = db.Column(db.String(100), db.ForeignKey("user.id"))

    #Through the attribute of the post, you can directly access the section you belong to. Back reference, if you have a section object, you can access all the models under the section
    board = db. relationship("BoardModel", backref=db. backref("posts"))
    author = db.relationship("UserModel", backref=db.backref("posts"))

# carousel
class BannerModel(db.Model):
    __tablename__ = 'banner'
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    # image name
    name = db.Column(db.String(255), nullable=False)
    # image link
    image_url = db.Column(db.String(255), nullable=False)
    # jump link
    link_url = db.Column(db.String(255), nullable=False)
    # priority
    priority = db.Column(db.Integer, default=0)
    create_time = db.Column(db.DateTime, default=datetime.now)

# Comment
class CommentModel(db.Model):
    __tablename__ = 'comment'
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    content = db.Column(db.Text, nullable=False)
    create_time = db.Column(db.DateTime, default=datetime.now)
    # The id of the post to which it belongs
    post_id = db.Column(db.Integer, db.ForeignKey("post.id"))
    # author's id
    author_id = db.Column(db.String(100), db.ForeignKey("user.id"), nullable=False)
                                                                      # Comment sorting post delete comment also delete
    post = db.relationship("PostModel", backref=db.backref('comments', order_by="CommentModel.create_time.desc()", cascade="delete, delete-orphan"))
    author = db. relationship("UserModel", backref='comments')

Get the template data rendering template

boards = BoardModel.query.order_by(BoardModel.priority.desc()).all()