Followers
- Bu bölümde projemizde kullanıcıların birbirlerini takip etmesi için
models.py'da düzenlemeler yapacağız. - Başlamadan önce kısa bir database relationship (veritabanı ilişki) tiplerine göz atalım.
One-To-Many

- User ve Post olarak belirttiğimiz iki adet varlık ile kullanıcı ve kullanıcı yayınları(gönderileri) ilişkisini tabloda gösteriyoruz.
- Tabloda görüleceği üzere
user_idposts tablosuna foreign key olarak verildi. Burada 1 adet User, 1'den fazla Post yayınlayabileceği için many tarafı posts tablosu, one tarafı users tablosudur. - Many tarafındaki tablo One tarafına bağlanabilmesi için üzerinde bir bağlantı taşıması gerekiyor. İşte bu bağlantı
user_idolacak. - Ayrıca
user_idüzerinden bir kullanıcıya ait yayınların(gönderilerin) listesine de erişebiliyoruz.
Many-To-Many

- Örnek tablodaki gibi 1 Öğrencinin, 1'den fazla Öğretmeni olabileceği gibi; 1 Öğretmenin de 1'den fazla Öğrencisi olabilir.
- Many-To-Many ilişkisinde taraflara foreign key eklenemiyor.
- Many-To-Many karmaşıklığını yardımcı tablolar vasıtası ile çözüyoruz.
- Böylece 2 adet One-To-Many ilişkisi elde etmiş olduk.
Representing Followers (Takipçilerin Gösterimi)

- Öğrenci & Öğretmen (Student & Teacher) ilişkisine benzer bir many-to-many ilişki de takip edilen & takipçi (followed & follower) arasındaki ilişkidir.
- Student & Teacher varlıkları 2 adet tabloda temsil ediliyordu. Ancak bizim sadece User varlığımız ve bunun users tablosu elimizde mevcut.
- Many-To-Many Relationship gerçekleşmesi için 2. varlık nedir? Bu da User varlığıdır.
- Bu şekildeki gibi kendisini referans alan varlık yapılarına self-referential relationship ilişkisi deniliyor.
- foreign key'ler
followerstablosunda bulunuyor. - Şimdi followers tablosunu
myapp/models.pymodülüne ekleyelim
xxxxxxxxxxfollowers = db.Table( 'followers', db.Column('follower_id', db.Integer, db.ForeignKey('user.id')), db.Column('followed_id', db.Integer, db.ForeignKey('user.id')),)class User(UserMixin, db.Model):#...- Tanımladığımız
followerstablosu bir model sınıfı değildir. Yardımcı bir tablo olarak tanımladık. - Şimdi many-to-many ilişkisini User modeline uygulayalım.
myapp/models.py
xxxxxxxxxxclass User(UserMixin, db.Model): #... followed = db.relationship( 'User', secondary=followers, primaryjoin=(followers.c.follower_id == id), secondaryjoin=(followers.c.followed_id == id), backref=db.backref('followers', lazy='dynamic'), lazy='dynamic' )Yeniden
db.relationship()methodu ile model sınıfları arası ilişki tanımlıyoruz. BuradaUseryukarıda tabloda gösterdiğimiz gibi kendisi ile ilişkisel bağlantı oluşturacak.Burada
followedreferansı ile takip edilen kulanıcıların listesini alabileceğiz.db.relationship()methodu parametrelerine bakarsak;User; ilişki kurulacak model adı. Burada aynı modeli kullandığımız için yine User model sınıfını verdik.secondary; ilişki kurulacak yardımcı tablo ile konfigurasyon sağlar. Yardımcı tablomuz followers dır.primaryjoin; follower user ile yardımcı tabloyu birbirine bağlayan şartı belirtir.secondaryjoin; followed user ile yardımcı tabloyu birbirine bağlayan şartı belirtir.backref; tablolar arası ilişkiye nasıl erişileceğini tanımlar.followedüzerindenfollowers'a erişmek diyebiliriz.
Şimdi terminalden migration yapalım:
xxxxxxxxxx(env) kayace@kayace-K53SV ~/flask/blog $ flask db migrate -m "followers is added by adnan"#...(env) kayace@kayace-K53SV ~/flask/blog $ flask db upgrade#...Takip Ekleme/Silme (Adding/Removing Follows)
- Örneğin
user1veuser2adında iki kullanıcımızın olduğunu varsayalım. user1,user2'yi takip etmesi için;user1.followed.append(user2)yazabiliriz.- Takip'ten çıkması için de
user1.followed.remove(user2)yazabiliriz. - Listelerdeki
appendveremovemethodları ile çok basit şekilde yapabiliyoruz. - Ancak kodlarımızın daha efektif ve yeniden kullanılabilir olması için ekleme, silme işlemlerini kendi methodlarımız üzerinden yapacağız.
myapp/models.py
xxxxxxxxxxclass User(UserMixin, db.Model): #... def follow(self, user): if not self.is_following(user): self.followed.append(user) def unfollow(self, user): if self.is_following(user): self.followed.remove(user) def is_following(self, user): return self.followed.filter( followers.c.followed_id == user.id).count() > 0is_following()methodu yardımı ile takip edip etmediği kontrolü yapıyoruz.
Takip edilenlerin gönderilerini listelemek (Obtaining the Posts from Followed Users)
myapp/models.py
xxxxxxxxxxclass User(UserMixin, db.Model): #... def followed_posts(self): return Post.query.join( followers, (followers.c.followed_id == Post.user_id)).filter( followers.c.follower_id == self.id).order_by( Post.timestamp.desc())Post.query.join(...).filter(...).order_by(...)açıklayalım.
JOIN
- User tablosu aşağıdaki gibi olsun.
| id | username |
|---|---|
| 1 | Adnan |
| 2 | Abdullah |
| 3 | Murat |
| 4 | Mehmet |
followersyardımcı tablomuz da aşağıdaki gibi olsun.
| follower_id | followed_id |
|---|---|
| 1 | 2 |
| 1 | 4 |
| 2 | 3 |
| 3 | 4 |
- Adnan Abdullah'ı ve Mehmet'i;
- Abdullah Murat'ı;
- Murat da Mehmet'i takip ediyor.
poststablosu
| id | text | user_id |
|---|---|---|
| 1 | post from Abdullah | 2 |
| 2 | post from Murat | 3 |
| 3 | post from Mehmet | 4 |
| 4 | post from Adnan | 1 |
Post.query.join(followers, (followers.c.followed_id == Post.user_id))- ilk argüman followers; yardımcı tablo
- ikinci argüman join şartı.
- Burada diyoruz ki database'e; bizim için geçici bir tablo oluştur ve posts tablosu ile followers tablosunu birleştir ancak bizim belirttiğimiz şarta göre!
- Şart: takip edilen kullanıcı ID'si , Post tablosundaki kullanıcı ID'si ile eşleşmelidir.
| id | text | user_id | follower_id | followed_id |
|---|---|---|---|---|
| 1 | post from Abdullah | 2 | 1 | 2 |
| 2 | post from Murat | 3 | 2 | 3 |
| 3 | post from Mehmet | 4 | 1 | 4 |
| 3 | post from Mehmet | 4 | 3 | 4 |
user_idilefollowed_idbirbirine eşit durumda! (join şartımız.)- Adnan kullanıcısını kimse takip etmediği için tabloda yok.
- Mehmet'i 2 kişi takip ettiği için 2 adet post kaydı var tablomuzda.
Filters
Şimdi sadece 1 kullanıcının takip ettiği kişilerin gönderilerini almak için filtreleme yapalım.
filter(followers.c.follower_id == self.id)self.id; user ID'dir.
Örneğin Adnan kullanıcısının takip ettiği kullanıcıların listesi:
| id | text | user_id | follower_id | followed_id |
|---|---|---|---|---|
| 1 | post from Abdullah | 2 | 1 | 2 |
| 3 | post from Mehmet | 4 | 1 | 4 |
Sorting
Sıralama için :
order_by(Post.timestamp.desc())- Son yayınlanan post'ları almak için sıralama yapıldı.
Mevcut kullanıcı ve takipçilerin gönderilerinin birleştirilmesi (Combining own user and followed posts)
myapp/models.py
xxxxxxxxxxdef followed_posts(self): followed = Post.query.join( followers, (followers.c.followed_id == Post.user_id)).filter( followers.c.follower_id == self.id) own = Post.query.filter_by(user_id=self.id) return followed.union(own).order_by(Post.timestamp.desc())followed; ile takip edilenlerin gönderilerini,own; ile mevcut kullanıcının gönderilerini alıyoruz.followed.union(own)diyerek bu iki listeyi birleştiriyoruz.- son olarak
order_byile sıralıyoruz.
Takipçileri Projeye Entegre Etmek (Integrating Followers)
myapp/routes.py
xxxxxxxxxx.route('/follow/<username>')def follow(username): user = User.query.filter_by(username=username).first() if user is None: flash('User {} not found'.format(username)) return redirect(url_for('index')) if user==current_user: flash('You cannot follow yourself') return redirect(url_for('user', username=username)) current_user.follow(user) db.session.commit() flash('You are following {}!'.format(username)) return redirect(url_for('user', username=username)).route('/unfollow/<username>')def unfollow(username): user = User.query.filter_by(username=username).first() if user is None: flash('User {} not found'.format(username)) return redirect(url_for('index')) if user==current_user: flash('You cannot unfollow yourself') return redirect(url_for('user', username=username)) current_user.unfollow(user) db.session.commit() flash('You are not following {}!'.format(username)) return redirect(url_for('user', username=username))myapp/templates/user.html
xxxxxxxxxx{% extends 'base.html' %}{% block content%}<table> <tr valign="top"> <td> <img src="{{ user.avatar(128) }}" /> </td> <td> <h3>Hoşgeldin {{user.username }}</h3> {%if user.about_me%} <small>{{user.about_me}}</small>{%endif%} {%if user.last_seen%} <br /> <small>Son görülme: {{user.last_seen}}</small>{%endif%} <!-- --> {% if user==current_user %} <p><a href="{{url_for('edit_profile')}}">Edit Profile</a></p> {% elif not current_user.is_following(user)%} <a href="{{url_for('follow', username=user.username)}}">Follow</a> {% else %} <a href="{{url_for('unfollow', username=user.username)}}">Unfollow</a> {%endif%} </td> </tr></table><hr> {%for post in posts %} {% include '_post.html' %} {%endfor%} {% endblock %}{% if user==current_user %}; mevcut kullanıcıEdit Profilelinki görülür.{% elif not current_user.is_following(user)%}; mevcut kullanıcı değilse ve profilini ziyaret ettiğimiz kullanıcı takip edilmiyorsa,Followlinki görülür.{% else %}; mevcut kullanıcı değil ve profili ziyaret edilen kullanıcı takip ediliyorsa,Unfollowlinki görülür.
- Ekran Görüntüleri


Yorumlar