Profile Page and Avatars (Profil Sayfası ve Avatarlar)
- Bu bölümde belirli bir kullanıcı için profil sayfasını oluşturmayı ve kullanıcıya avatar ekleme işlemini göreceğiz.
myapp/routes.pymodülündedef user(username)adında bir method açıyoruz.
xxxxxxxxxx.route('/user/<username>')def user(username): '''Kullanıcı detay sayfasını render eder''' user = User.query.filter_by(username=username).first_or_404() posts = [ {'author':user, 'body':"Deneme yayını 1"}, {'author':user, 'body':"Deneme yayını 2"}, {'author':user, 'body':"Deneme yayını 3"}, ] return render_template('user.html', title='Profil', user=user, posts=posts)- Diğer URL'lerden farklı olarak en sonda
< >işaretleri kullanılarak ve içine de username parametresi alan bir URL belirledik. Bu demek oluyor ki URL sonuna gelecek username ile her kullanıcı ismine özel profil sayfası görüntülenecek. Örneğin/user/adnandediğimizdeadnankullanıcısına ait profil sayfasını göreceğiz. def user(username)methoduna dikkat ederseniz, method parametresi ile URL parametresi aynı string olarak belirlenmelidir.def user(kullanici)dediğimizde hata ile karşılaşacağız. Stringlerin aynı olmasına dikkat edelim..first_or_404()methodufirst()methodunda farklı olarak, eğer kullanıcı yoksa404hatası dönecek.- posts değişkeni ile de gösterim amaçlı geçici obje oluşturduk.
templates/user.htmldosyasını oluşturalım.
xxxxxxxxxx{% extends 'base.html' %} {% block content%}<h3>Hoşgeldin {{user.username }}</h3><hr><ul> {%for post in posts %} <li> <p> <b>{{post.author.username}} </b>: <i>{{post.body}}</i> </p> </li> {%endfor%}</ul>{% endblock %}base.html'e de aşağıdaki satırı ekleyelim.
xxxxxxxxxx<td><a href="{{url_for('user', username=current_user.username)}}">Profil</a></td><td><a href="{{url_for('logout')}}">Çıkış Yap</a></td>- Burada
url_formethodunun ek olarak username parametresi aldığını görüyorsunuz. Mevcut kullanıcıyı (current_user.username)url_formethoduna verdik.

Avatar
- Profil sayfasını biraz daha güzelleştirmek için kullanıcılara avatar ekleyelim.
- Gravatar - Globally Recognized Avatars sitesinin sağladığı avatar oluşturma servisini kullanacağız. Büyük boyutlu resimler yüklemek yerine şimdilik bunu kullanalım.
- https://www.gravatar.com\/avatar/<hash> URL'ine kullanıcı e-mailini md5 ile hash'leyip vereceğiz. Örnek kullanım:
xxxxxxxxxx>>> from hashlib import md5>>> 'https://www.gravatar.com/avatar/'+md5(b'adnan@kaya.com').hexdigest()'https://www.gravatar.com/avatar/b560759d7ebe1fe931ac633979bf4805'sparametresi ilesize,dparametresi ile avatar kaydı yapmamış kullanıcılara random avatar üretir.myapp/models.py'daUsermodeline aşağıdaki methodu ekliyoruz.
xxxxxxxxxxfrom hashlib import md5#...class User(UserMixin, db.Model): #... def avatar(self, size): '''kullanıcı için avatar üretir''' digest = md5(self.email.lower().encode('utf-8')).hexdigest() return 'https://www.gravatar.com/avatar/{}?d=identicon&s={}'.format( digest, size)user.html'i aşağıdaki gibi düzenleyelim.
xxxxxxxxxx{% extends 'base.html' %} {% block content%}<table> <tr valign="top"> <td><img src="{{ user.avatar(128) }}" /></td> <td><h3>Hoşgeldin {{user.username }}</h3></td> </tr></table><hr><ul> {%for post in posts %} <li> <p> <b>{{post.author.username}} </b>: <i>{{post.body}}</i> </p> </li> {%endfor%}</ul>{% endblock %}
Sub Templates
- Jinja2'nun bize sunduğu
includesayesinde bir template'i başka bir template içerisine dahil edebiliriz. _post.htmladında bir sub template oluşturalım.
xxxxxxxxxx<table> <tr> <td><img src="{{post.author.avatar(36)}}"/></td> <td>{{post.author.username}} </td> <td>{{post.body}}</td> </tr></table>user.html'e bu template'i dahil edelim.
xxxxxxxxxx{% extends 'base.html' %} {% block content%}<table> <tr valign="top"> <td> <img src="{{ user.avatar(128) }}" /> </td> <td> <h3>Hoşgeldin {{user.username }}</h3> </td> </tr></table><hr>{%for post in posts %} {% include '_post.html' %} {%endfor%} {% endblock %}
'Hakkımda' bilgisi ve 'Son görülme tarihi' bilgisi ekleme
- Kullanıcı profillerine
about_mevelast_seenekleyelim. myapp/models.pymodülünü aşağıdaki gibi düzenleyelim.
xxxxxxxxxxclass User(UserMixin, db.Model): #... about_me = db.Column(db.String(280)) last_seen = db.Column(db.DateTime, default=datetime.utcnow)- Şimdi modelimizin tablolarının oluşması için
migrationyapalım.
xxxxxxxxxx(env) kayace@kayace-K53SV ~/flask/blog $ export FLASK_APP=main.py(env) kayace@kayace-K53SV ~/flask/blog $ flask db migrate -m "about me and last seen have been added"INFO [alembic.runtime.migration] Context impl SQLiteImpl.INFO [alembic.runtime.migration] Will assume non-transactional DDL.INFO [alembic.autogenerate.compare] Detected added column 'user.about_me'INFO [alembic.autogenerate.compare] Detected added column 'user.last_seen' Generating /home/kayace/flask/blog/migrations/versions/207c92b4950a_about_me_and _last_seen_have_been_added.py ... doneupgradekomutunu unutmuyoruz.
xxxxxxxxxx(env) kayace@kayace-K53SV ~/flask/blog $ flask db upgradeINFO [alembic.runtime.migration] Context impl SQLiteImpl.INFO [alembic.runtime.migration] Will assume non-transactional DDL.INFO [alembic.runtime.migration] Running upgrade 9d8ba8bdcb4e -> 207c92b4950a, about me and last seen have been addedLast seen (Son görülme) için
myapp/routes.pymodülünde düzenleme yapalım.
xxxxxxxxxxfrom datetime import datetime.before_requestdef before_request(): if current_user.is_authenticated: current_user.last_seen = datetime.utcnow() db.session.commit()@app.before_requestdecorator Flask'ın bize sunduğu özelliktir. Gösterim fonksiyonları( template'leri render eden methodlar ) çalışmadan öncebefore_requestçalıştırılacak.before_requestmethodumuz kullanıcının log-in olup olmadığına bakıyor.- Lokal zaman bilgisi yerine UTC zaman bilgisi kullanıyoruz yeniden.
current_userreferansını çağırdığımız zaman Flask-Login user loader callback fonksiyonunu çağırır. Bu fonksiyon mevcutuserobjesini database session'a ekler. Yani db.session.add uygulanır. Burada ikinci kez db.session.add yazmamıza gerek yok.- Profil sayfalarını yeniden görüntülediğinizde son görülme tarihini göreceksiniz.
- Bir kaç kullanıcı açıp onların profillerine girip son görülme tarihlerini görebilirsiniz.

Profil Sayfası Düzenleme Formu (Editing Profile)
- Profil sayfasını düzenlemek için bir adet form ekleyelim.
myapp/forms.pymodülünde:
xxxxxxxxxxfrom wtforms import StringField, TextAreaField, SubmitFieldfrom wtforms.validators import DataRequired, Length# ...class EditProfileForm(FlaskForm): '''Kullanıcı profil düzenleme formu''' username = StringField('Kullanıcı Adı', validators=[DataRequired()]) about_me = TextAreaField('Hakkımda', validators=[Length(min=0, max=280)]) submit = SubmitField('Submit')- Burada
TextAreaFieldkullandık. Hakkımda yazısı uzun olabilir. validatorskısmında daLengthkullandık. Kullanıcı minimum ve maksimum belirlenen karakter sayısı girebilir.
Şimdi profil düzenleme form template'ini oluşturalım.
templates/edit_profile.html
xxxxxxxxxx{%extends 'base.html'%} {% block content %}<h3>Profili Düzenle</h3><form action="" method="POST"> {{form.hidden_tag()}} <table> <tr> <th>{{form.username.label}}</th> <td>{{form.username(size=24)}}</td> <td> {% for error in form.username.errors %} <span style="color: red;">[{{ error }}]</span> {% endfor %} </td> </tr> <tr> <th>{{form.about_me.label}}</th> <td>{{form.about_me(cols=50, rows=4)}}</td> <td> {% for error in form.about_me.errors %} <span style="color: red;">[{{ error }}]</span> {% endfor %} </td> </tr> </table> <p>{{form.submit()}}</p></form>{% endblock %}Ve son olarak gösterim fonksiyonunu (view function) yazlım.
myapp/routes.py
xxxxxxxxxxfrom app.forms import EditProfileForm#....route('/edit_profile', methods=['GET', 'POST'])def edit_profile(): '''Kullanıcı bilgileri düzenleme sayfasını render eder''' form = EditProfileForm() if form.validate_on_submit(): current_user.username = form.username.data current_user.about_me = form.about_me.data db.session.commit() flash("Değişiklikler kaydedildi.") return redirect(url_for('edit_profile')) elif request.method == 'GET': form.username.data = current_user.username form.about_me.data = current_user.about_me return render_template('edit_profile.html', title='Edit Profile', form=form)- Eğer kullanıcı formu submit etmişse (yani form bilgilerini doldurup kaydet, submit butonuna basmışsa) ; formdan alınan username ve about_me bilgilerini sisteme giriş yapmış kullanıcının(current_user) username ve about_me alanlarına atama yapıyoruz.
- Değişiklikler sonrası
edit_profilesayfasınaflashile bilgi mesajı bırakıyoruz. - Eğer kullanıcı formu submit etmemişse; form alanlarına mevcut kullanıcının(current_user) username ve about_me bilgilerini dolduruyoruz(yerleştiriyoruz). Böylece kullanıcı profil düzenle dediği zaman varsa eski bilgileri form alanlarında görülecek.
Son olarak profil düzenleme sayfasına gitmek için bir link ekleyelim.
templates/user.htmliçerisine aşağıdaki satırı ekliyoruz.
xxxxxxxxxx{% extends 'base.html' %} {% block content%} {% if user == current_user%} <a href="{{url_for('edit_profile')}}">Edit Profile</a> {%endif%}<hr />...- Burada
{% if user == current_user%}kontrolü ileuser, sisteme giriş yapmışcurrent_userolmalı. Yani kullanıcı sadece kendi profilini düzenleyebilmeli!

Submit sonrası ...

Yorumlar