A tutorial on implementing the user's profile and avatar in Python's flask framework

Source: Internet
Author: User
Tags time zones time and date


User Profile page




On the User profile page, there is basically nothing special to emphasize and introduce in the new concept. You just need to create a new View function template page that contains HTML.



Here is the View function (project directory/views.py):



@ app.route ('/user/')
@login_ required
def user(nickname):
user =  User.query.filter_ by(nickname = nickname).first()
if user == None:
Flash ('nonexistent user: '+ nickname +'! ')
return redirect(url_ for('index'))
posts = [
{ 'author': user, 'body': 'Test post #1' },
{ 'author': user, 'body': 'Test post #2' }
]
return render_ template(' user.html ',
user = user,
posts = posts) 





The @app.route logo here is primarily used to illustrate that this view function differs from the previous ones. We have defined a parameter named. Inside the function it translates into a parameter with the same name, and when the user has a request, such as a url:url/user/miguel, the secondary view function is identified as having a parameter named nickname value ' Miguel ', which is nickname = ' Miguel '.




There is no need to be surprised by the way this method is implemented. First, we need to use the converted nickname parameter as a condition to try to call the user's data from the database. If the data is not queried, we will give the user a wrong hint and jump to the home page as before.






Once we have found a change user, we will display the user's article below the template. Note that in the User profile page we only let the user show the article, so the author of the article is the user.






The initialized view template is very simple (project directory/templates/user.html):



 





  {% extends "base.html"%} {% block content%}

User nickname: {{user.nickname}}!

{% for post in posts%}

{{Post.body}}

{% ENDFOR%} {% Endblock%}








The User profile page is ready, but the site does not yet point to the page to change the link address. In order to make it convenient for users to view their information, we put the link address on the top navigation (project directory/templates/base.html):






Microblog:
Home
{% if g. user.is_ authenticated() %}
|Your profile
|Log out
{% endif %}





Notice that we've given the function a reference to the previous and preceding URLs.



Try this project now. Clicking on the "Your profile" link above will jump to the user profile page. Since we have not yet pointed to a random user profile page of the link address, so here if you want to see other people's information, you need to manually enter the address. For example, if you want to see Miguel's data, the address is: Http://localhost:5000/user/miguelt






Avatar section


I'm sure you'll feel that the current user profile page looks monotonous. To look good, we'll add the feature of the user's avatar.



In order to avoid the need for our server to handle a large number of uploaded avatar images, we are here to use Gravatar to provide the user's avatar can be.



Since returning a user avatar belongs to the user, we put the code inside the Theuserclass (project directory/models.py):







from hashlib import md5
# ...
class User(db.Model):
  # ...
  def avatar(self, size):
    return 'http://www.gravatar.com/avatar/' + md5(self.email).hexdigest() +
    '?d=mm&s=' + str(size)





Avatar will return the address of the Avatar image and request the pixel size of the image you want according to your needs.




Getting image images from Gravatar is simple. You just need to use MD5 to encrypt the user's mailbox hash and merge it into the URL form above. Of course you also have the freedom to choose a custom image size. where "d=mm" is to set the default avatar that the user displays without Gravatar account. The "MM" option returns a gray picture of a person's silhouette, called a "riddle-like person." The "s=" option is used to set the pixel that returns the size of the picture you given.



Of course Gravatar also has its own documentation to describe the URL splicing technology!






Here userclass can return a picture of a user picture, we need to integrate this into the user profile layout (project directory/templates/user.html):



 
{% extends " base.html " %}
{% block content %}
User nickname:{{ user.nickname }}
{% for post in posts %}
{{ post.author.nickname }}Published:{{ post.body }}
{% endfor %}
{% endblock %}





The highlight of our design userclass to return the avatar is: if one day we feel that the avatar on the Gravatar website is not what we want, We only need to rewrite the Avatar processing function to return to the address we want (even if someone hotlinking point to our server, we can also protect their own host), so that a dozen need to modify this point, so the template is still automatically normal operation.






We have added the user picture section to the top of the user profile Details page, but at the bottom of the page we also have to show the article did not do, in front of the article we also need to display the user's avatar. Of course, the user profile page needs to show the same picture of the article, but it would be nice to move the Avatar function to the homepage to show the author's avatar for the article.



We only need to modify the template file slightly to implement the function of displaying the corresponding author's avatar to the article (Project directory/templates/user.html):



 
{% extends " base.html " %}
{% block content %}
User nickname:{{ user.nickname }}
{% for post in posts %}
{{ post.author.nickname }}
Published:
{{ post.body }}
{% endfor %}
{% endblock %}





This is the end of our user profile page:



Micro-Blog User Details page





Reusing sub-templates



The User profile page shows the user's own articles, but the homepage of the site needs to display different user articles at the moment. Here, there are two template files for displaying user articles. We can directly copy the code that handles the display of the article and then paste it directly into the new template, in fact, that is not the ideal method, if one day we need to modify the display of the article that block, we need to update so those containing the article display code template file.




Instead, we will go to create a new sub-template file to handle the function of the article display, and then include this file when you need to display the article.



Let's start by creating a sub-empty template file and then copying the code that shows the article in the User Profile page (project directory/templates/post.html):



 
  


  
{{ post.author.nickname }} Published: {{ post.body }}





We then call the child template file (project directory/templates/user.html) using JINJA2 's include function.



 
{% extends " base.html " %}
{% block content %}
User nickname:{{ user.nickname }}
{% for post in posts %}
{% include ' post.html ' %}
{% endfor %}
{% endblock %}





Once we have the full page, we can follow the above method to invoke the sub-template to display the article, but it is not urgent to say, in the later chapters of the tutorial said.




More related personal information



Although this user Information page is more sophisticated, there is still a lot of information that is not displayed. Most people like to show their own more information on the site, so we can let users fill in their own information displayed here. Of course, we can also record the user each time landing to the site, display to their own details page.




In order to display such information, we need to update the database. In particular, new fields (project directory/models.py) are required in UserClass:




class User(db.Model):
  id = db.Column(db.Integer, primary_key = True)
  nickname = db.Column(db.String(64), unique = True)
  email = db.Column(db.String(120), index = True, unique = True)
  role = db.Column(db.SmallInteger, default = ROLE_USER)
  posts = db.relationship('Post', backref = 'author', lazy = 'dynamic')
  about_me = db.Column(db.String(140))
  last_seen = db.Column(db.DateTime)





Each time we modify the database, we need to generate a new record (migration). It is important to note that when we process the data update to the database, we remember to create a (migration), and now we look at the final result. We just need the following code to update the new two fields into the database:



./db_migrate.py





Of course the corresponding response script is




New migration saved as db_repository/versions/003_migration.py
Current database version: 3





Now our new two fields are saved to the database. However, it is a little different to call this script under the window System.




If you do not support data migration, you have to manually modify the database, otherwise you will need to delete and then re-create the data from the beginning.



Next we need to modify the user Details page to display the fields we just added (project directory/templates/user.html):






 
{% extends " base.html " %}
{% block content %}
User nickname:{{ user.nickname }}
{% if  user.about_ me %}
{{ user.about_ me}}
{% endif %}
{% if  user.last_ seen %}
Last seen on: {{ user.last_ seen}}
{% endif %}
{% for post in posts %}
{% include ' post.html ' %}
{% endfor %}
{% endblock %}





Since we need to be able to display these fields only when the user has filled out the fields themselves, we will use the JINJA2 to show them.



For this, both fields are empty for all users, and nothing is displayed.



The last displayed field (Last_seen) is particularly well-handled. It is important to note that we have set up the receive parameters for registering user requests (FLASK.G and Global, Asg.user). That is, you need to record the user's login time in this best segment (project directory/views.py):




from datetime import datetime
# ...
@app.before_request
def before_request():
  g.user = current_user
  if g.user.is_authenticated():
    g.user.last_seen = datetime.utcnow()
    db.session.add(g.user)
    db.session.commit()





If you log in, the last login time will be displayed on the data details page, and the corresponding login time will be updated automatically if you refresh each page. This is because when the browser does not refresh it will ask us to set the receive parameters and update the database processing function.




Here we record the UTC time zone of the international standard. In the previous chapters we also mentioned how to store a timestamp suitable for all time zones, which would have a negative error message, because the time in UTC is displayed on all user's profile pages, which I will explain in detail in the next section on time and date.



To display more information about the user, we have to give them a link that is best placed on the edit page of the user profile.

Edit User Details

Create a User profile Edit page that's so easy, we just need to create the following Web Form (project directory/forms.py):




from flask.ext.wtf import Form, TextField, BooleanField, TextAreaField
from flask.ext.wtf import Required, Length
 
class EditForm(Form):
  nickname = TextField('nickname', validators = [Required()])
  about_me = TextAreaField('about_me', validators = [Length(min = 0, max = 140)])





View template file (project directory/templates/edit.html):



 
  {% extends "base.html"%} {% block content%}

Edit Your Profile

{% Endblock%}





Finally, of course, the method of creating the View (Project directory/views.py):




from forms import LoginForm, EditForm
 
@app.route('/edit', methods = ['GET', 'POST'])
@login_required
def edit():
  form = EditForm()
  if form.validate_on_submit():
    g.user.nickname = form.nickname.data
    g.user.about_me = form.about_me.data
    db.session.add(g.user)
    db.session.commit()
    flash('Your changes have been saved.')
    return redirect(url_for('edit'))
  else:
    form.nickname.data = g.user.nickname
    form.about_me.data = g.user.about_me
  return render_template('edit.html',
    form = form)





For user-friendly editing, we need to add a link address to this page on the user's profile page (project directory/templates/user.html):




{% extends " base.html " %}
{% block content %}
User nickname:{{ user.nickname }}
{% if  user.about_ me %}
{{ user.about_ me}}
{% endif %}
{% if  user.last_ seen %}
Last login time:{{ user.last_ seen}}
{% endif %}
{% if  user.id  == g. user.id  %}
Modification of information
{% endif %}
{% for post in posts %}
{% include ' post.html ' %}
{% endfor %}
{% endblock %}





But you need to make a decision on the condition that the link is displayed only when the user browses to his or her profile page, not by browsing to anyone's profile page.



The following is the latest profile page, which contains our newly added fields, and also contains "About Me" text:





The last point is for you to study.



Seemingly through the above some of the columns made, the profile page feels already very perfect, right? Come to think of it, but we still have some bugs to fix.



I wonder if you found out?



Let me remind you, in the previous chapters, when we browsed the user login, I have already mentioned this bug. Now we've made the same mistake in the code sheet above.



Think about it, if you know what the problem is, you can say it in the comments below. I'll go over the bug in the next section and say how to fix it.




As before, I'm going to pack up the code for today. Download



Download Address Microblog-0.6.zip.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.