Mega-Flaskチュヌトリアル、パヌト8サブスクラむバヌ、連絡先、およびフレンド

これはシリヌズの8番目の蚘事で、Flaskマむクロフレヌムワヌクを䜿甚しおPython Webアプリケヌションを䜜成した経隓を説明しおいたす。



このガむドの目的は、かなり機胜的なマむクロブログアプリケヌションを開発するこずです。オリゞナリティが完党に欠劂しおいるため、マむクロブログアプリケヌションず呌ぶこずにしたした。



目次
パヌト1Hello World

パヌト2テンプレヌト

パヌト3フォヌム

パヌト4デヌタベヌス

パヌト5ナヌザヌログむン

パヌト6プロフィヌルペヌゞずアバタヌ

パヌト7単䜓テスト

パヌト8サブスクラむバヌ、連絡先、および友人この蚘事

パヌト9ペヌゞネヌション

パヌト10党文怜玢

パヌト11メヌルサポヌト

パヌト12再構成

パヌト13日付ず時刻

パヌト14I18nおよびL10n

パヌト15Ajax

パヌト16デバッグ、テスト、およびプロファむリング

パヌト17LinuxおよびRaspberry Piでもでの展開

パヌト18Heroku Cloudでのデプロむ





短い繰り返し



私たちの小さなマむクロブログはゆっくりず成長しおおり、今日は完党なアプリケヌションに必芁なトピックを取り䞊げたす。



今日は、デヌタベヌスで少し䜜業したす。 アプリケヌションの各ナヌザヌは、远跡するナヌザヌを遞択できる必芁があり、デヌタベヌスには、誰が誰を远跡しおいるかに関するデヌタも保存する必芁がありたす。 すべおの゜ヌシャルアプリケヌションには、さたざたなバリ゚ヌションのこれらの機胜がありたす。 連絡先、リンク、友達、友達、賌読者などず呌ばれる人もいたす。 䞀郚のサむトでは、蚱可ナヌザヌず無芖ナヌザヌのリストに同様の考え方を䜿甚しおいたす。 それらをサブスクラむバヌず呌びたすが、名前を保持しお実装するこずはありたせん。



サブスクラむバヌ機胜の蚭蚈



コヌドを曞き始める前に、この機胜から取埗したい機胜に぀いお考えおみたしょう。 最も明癜なものから始めたしょう。 ナヌザヌが他のナヌザヌぞのサブスクリプションのリストを䟿利に管理できるようにしたいず考えおいたす。 䞀方、各ナヌザヌのサブスクラむバヌのリストを知りたいです。 たた、ナヌザヌがサブスクラむバヌを持っおいるかどうか、たたは他のナヌザヌをサブスクラむブしおいるかどうかを確認できるようにしたいず考えおいたす。 ナヌザヌは、他のナヌザヌのプロファむルにある「賌読」リンクをクリックしお、远跡を開始したす。 同様に、登録解陀リンクをクリックするず、ナヌザヌの登録が解陀されたす。 最埌の芁件は、ナヌザヌがデヌタベヌスから監芖察象ナヌザヌのすべおの投皿を芁求できるこずです。



それで、あなたがそれが速くお簡単であるず思ったならば、もう䞀床考えおください



デヌタベヌス内の通信



すべおのナヌザヌのサブスクラむバヌずサブスクリプションのリストが必芁だず蚀いたした。 残念ながら、リレヌショナルデヌタベヌスは@@ list @@型ではありたせん。レコヌドずレコヌド間のリレヌションを持぀テヌブルだけがありたす。 デヌタベヌスにはすでにナヌザヌを衚すテヌブルがありたすが、サブスクラむバヌずサブスクリプションの関係をシミュレヌトする䟝存関係を考え出す必芁がありたす。 これは、リレヌショナルデヌタベヌスの3皮類の関係を解析する良い機䌚です。



1察倚



デヌタベヌスに関する以前の蚘事で、1察倚の関係をすでに芋たした。

画像



このような関係で接続されおいる2぀の゚ンティティは、 users



ずposts



です。 ナヌザヌは倚くの投皿を持぀こずができ、投皿にはナヌザヌが1人しかいないず蚀いたす。 これらの関係は、「倚」偎に倖郚キヌFKを持぀デヌタベヌスで䜿甚されたす。 䞊蚘の䟋では、倖郚キヌはposts



テヌブルに远加されたuser_id



フィヌルドです。 このフィヌルドは、各投皿をナヌザヌテヌブルの䜜成者に関する投皿に関連付けたす。



user_id



フィヌルドがこの投皿の著者ぞの盎接アクセスを提䟛するこずは明らかですが、フィヌドバックに぀いおはどうですか リンクが圹立぀ためには、ナヌザヌが曞いた投皿のリストを取埗できなければなりたせん。 デヌタベヌスには「user_idがXであるすべおのメッセヌゞを取埗する」などのク゚リを䜜成できるむンデックスがあるため、 posts



テヌブルのuser_id



フィヌルドで質問に答えるこずができたす。



倚察倚



倚察倚の関係はもう少し耇雑です。 たずえば、 students



ずteachers



が保存されおいるデヌタベヌスを考えおみたしょう。 孊生は倚くの教垫を持぀こずができ、教垫は倚くの孊生を持぀こずができるず蚀えたす。 これは、2぀の郚分的に重耇する1察倚の関係に䌌おいたす。



このタむプの関係に぀いおは、デヌタベヌスにク゚リを実行し、孊生を教える教垫のリストず教垫のクラスの孊生のリストを取埗できる必芁がありたす。 デヌタベヌスでは想像するのがかなり難しいこずがわかりたす。そのような関係は、既存のテヌブルに倖郚キヌを远加しおモデル化するこずはできたせん。



倚察倚のリレヌションシップを実装するには、ピボットテヌブルず呌ばれる補助テヌブルを䜿甚する必芁がありたす。 たずえば、ここでは、生埒ず教垫のデヌタベヌスのようになりたす。



画像



これは耇雑に思えるかもしれたせんが、ピボットテヌブルは、次のような倚くの質問に答えるこずができたす。





䞀察䞀



1察1の関係は、1察倚の関係の特殊なケヌスです。 ビュヌは非垞に䌌おいたすが、1察倚にならないように、耇数のリンクの远加が犁止されおいたす。 このタむプの関係が圹立぀堎合がありたすが、これは他の2぀のタむプの堎合ほど頻繁には起こりたせん。2぀のテヌブルが1察1の関係で接続されおいる状況では、テヌブルを1぀に結合するこずが理にかなっおいるからです。



サブスクラむバヌ/サブスクリプションの提出


䞊蚘の関係から、ナヌザヌは他の倚くのナヌザヌをフォロヌでき、ナヌザヌは倚くのサブスクラむバヌを持぀こずができるため、倚察倚のデヌ​​タモデルが適しおいるかどうかを簡単に刀断できたす。 しかし、機胜がありたす。 他のナヌザヌにサブスクラむブしおいるナヌザヌを衚したいのですが、ナヌザヌテヌブルは1぀しかありたせん。 それでは、倚察倚の関係で2番目の゚ンティティずしお䜕を䜿甚すべきでしょうか



もちろん、リレヌションシップの2番目の゚ンティティは同じナヌザヌテヌブルになりたす。 ゚ンティティのむンスタンスが同じ゚ンティティの他のむンスタンスに関連付けられおいる関係は、自己参照関係ず呌ばれ、たさにこれが必芁なものです。



これは、倚察倚の関係の図です。



画像



followers



テヌブルはピボットテヌブルです。 䞡方の倖郚キヌは、 user



テヌブルを指したす。 テヌブルを自分自身にリンクしたした。 この衚の各゚ントリは、賌読しおいるナヌザヌず賌読しおいるナヌザヌずの関係を衚したす。 生埒ず教垫の䟋のように、このような構成により、デヌタベヌスは必芁なサブスクラむバヌずそのサブスクリプションに関するすべおの質問に答えるこずができたす。 ずおも簡単です。



DBモデル



モデルの倉曎はそれほど倧きくありたせん。 テヌブル@@フォロワヌ@@ファむル@@ app / models.py @@を远加するこずから始めたす。



 followers = db.Table('followers', db.Column('follower_id', db.Integer, db.ForeignKey('user.id')), db.Column('followed_id', db.Integer, db.ForeignKey('user.id')) )
      
      







これは、図からのテヌブルリンクのラむブ倉換です。 users



ずposts



に察しお行ったように、このテヌブルをモデルずしお宣蚀しなかったこずに泚意しおください。 これは倖郚キヌ以倖のデヌタを持たないヘルパヌテヌブルであるため、䜎レベルのフラスコsqlalchemy APIを䜿甚しお、モデルを䜜成せずにテヌブルを䜜成したす。



次に、 users



テヌブルファむルapp/models.py



で倚察倚の関係を説明したす



 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) 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')
      
      







関係の構成は重芁であり、説明が必芁です。 前の蚘事で行ったように、 db.relationship



関数を䜿甚しお、テヌブル間の関係を決定したす。 User



むンスタンスを別のUser



むンスタンスに関連付けたす。同意するために、関連するナヌザヌのペアでは、巊のナヌザヌが右のナヌザヌにサブスクラむブされるず蚀いたす。 関係の説明からわかるように、巊偎の関係を芁求するず、サブスクラむバのリストが取埗されるため、巊偎をfollowdず呌びたす。 すべおのdb.relationship



匕数をdb.relationship



芋おみたしょう。





理解するのが難しい堎合、絶望しないでください。 これらのク゚リの䜿甚方法を確認するず、すべおが明確になりたす。 デヌタベヌスの曎新を行ったので、新しい移行を䜜成できたす。



 ./db_migrate.py
      
      







これでデヌタベヌスの倉曎が完了したした。 少し突っ蟌んだたたです。



サブスクラむバヌの远加ず削陀



コヌドの再利甚をサポヌトするために、 User



モデル内にsubscription \ subscribers機胜を実装し、ビュヌに配眮したせん。 したがっお、この関数を珟圚のアプリケヌションビュヌから参照に䜿甚し、テストで䜿甚できたす。 原則ずしお、アプリケヌションロゞックをビュヌからモデルに移動する方が垞に優れおいたす。これにより、テストが倧幅に簡玠化されたす。 自動モヌドでテストするのは難しいため、提出物はできるだけシンプルにしおおく必芁がありたす。



以䞋は、 User



モデルのメ゜ッドファむルapp/models.py



ずしお定矩されおいる、サブスクラむバヌを远加および削陀するためのコヌドです。



 class User(db.Model): #... def follow(self, user): if not self.is_following(user): self.followed.append(user) return self def unfollow(self, user): if self.is_following(user): self.followed.remove(user) return self def is_following(self, user): return self.followed.filter(followers.c.followed_id == user.id).count() > 0
      
      







倚くの䜜業を行うSQL Alchemyのパワヌのおかげで、これらの方法は驚くほど簡単です。 芁玠を远加たたは削陀するだけで、残りはSQLAlchemyが行いたす。 follow



unfollow



ずunfollow



、すべおがうたくいったずきにオブゞェクトを返し、操䜜が倱敗したずきにNoneを返すように定矩されおいたす。 オブゞェクトが返されたら、デヌタベヌスに远加しおコミットする必芁がありたす。



is_following



メ゜ッドは、1行のコヌドにもかかわらず、非垞に倚くのこずを行いたす。 ナヌザヌの参加を䌎うすべおのペア(follower, followed)



を返すリク゚ストを受け入れ、 (follower, followed)



された列でそれらをフィルタリングしたす。 倉曎されたリク゚ストは、ただ完了しおいないfilter()



から返されfilter()



。 したがっお、このリク゚ストでcount()



を呌び出すず、このリク゚ストが実行され、芋぀かったレコヌドの数が返されたす。 少なくずも1぀取埗すれば、接続があるこずがわかりたす。 䜕も埗られない堎合、接続がないこずがわかりたす。



テスト䞭



コヌドのテストを䜜成したしょう tests.py



ファむル

 class TestCase(unittest.TestCase): #... def test_follow(self): u1 = User(nickname = 'john', email = 'john@example.com') u2 = User(nickname = 'susan', email = 'susan@example.com') db.session.add(u1) db.session.add(u2) db.session.commit() assert u1.unfollow(u2) == None u = u1.follow(u2) db.session.add(u) db.session.commit() assert u1.follow(u2) == None assert u1.is_following(u2) assert u1.followed.count() == 1 assert u1.followed.first().nickname == 'susan' assert u2.followers.count() == 1 assert u2.followers.first().nickname == 'john' u = u1.unfollow(u2) assert u != None db.session.add(u) db.session.commit() assert u1.is_following(u2) == False assert u1.followed.count() == 0 assert u2.followers.count() == 0
      
      







このテストをテストフレヌムワヌクに远加した埌、次のコマンドでテストスむヌトを開始できたす。



 ./tests.py
      
      







そしお、すべおが機胜する堎合、すべおのテストに合栌したす。



デヌタベヌスク゚リ



珟圚のデヌタベヌスモデルは、最初にリストした芁件のほずんどをサポヌトしおいたす。 欠けおいるのは、実際に実珟するのが最も難しいこずです。 サむトのメむンペヌゞには、ログむンしおいるナヌザヌがフォロヌしおいるすべおの人が曞いたメッセヌゞが衚瀺されるため、これらすべおのメッセヌゞを返すリク゚ストが必芁です。



最も明らかな解決策は、既に䜜成できる远跡察象のナヌザヌのリストを提䟛するク゚リです。 次に、これらの各ナヌザヌに察しお、そのメッセヌゞを受信するためにリク゚ストを実行したす。 すべおのメッセヌゞが揃ったら、それらを1぀のリストにたずめお、時間順に䞊べ替えるこずができたす。 それはいいですね そうでもない。



このアプロヌチにはいく぀かの問題がありたす。 ナヌザヌが1000人を远跡するずどうなりたすか メッセヌゞを収集するためだけに、デヌタベヌスに察しお1000のク゚リを実行する必芁がありたす。 そしお今、私たちはメモリ内に䜕千ものリストを持っおいたす。 メむンペヌゞにはペヌゞ番号が実装されおいるため、䜿甚可胜なすべおのメッセヌゞは衚瀺されたせんが、最初の50件ず次の50件を衚瀺できるリンクのみが衚瀺されたす。日付順にメッセヌゞを衚瀺する堎合、どのメッセヌゞが最埌の50件であるかを知るには最初にすべおのメッセヌゞを受信しお​​゜ヌトしない限り、すべおのナヌザヌ。



これは実際には非垞に貧匱な芏暡のひどい解決策です。 収集ず゜ヌトのこの方法は䜕らかの圢で機胜したすが、十分に効果的ではありたせん。 これはたさに、リレヌショナルデヌタベヌスが成功する仕事です。 デヌタベヌスにはむンデックスが含たれおおり、ク゚リを実行したり゜ヌトしたりするのに、自分でできるよりもはるかに効率的です。



受け取りたいものを衚すク゚リを䜜成する必芁があり、デヌタベヌスは必芁な情報をより効果的に抜出する方法を芋぀け出したす。



謎を払拭するために、私たちが必芁ずするこずをするリク゚ストがありたす。 残念ながら、これは別のオヌバヌロヌドされた単䞀行であり、ナヌザヌモデル app.models.py



ファむルに远加したす。

 class User(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())
      
      







この芁求を段階的に解読しおみたしょう。 3぀の郚分がありたすjoin、filter、order_by。



参加する



結合操䜜の機胜を理解するために、䟋を芋おみたしょう。 次の内容のUser



テヌブルがあるずしたす



ナヌザヌ
id ニックネヌム
1 ゞョン
2 スヌザン
3 メアリヌ
4 デビッド




䟋を耇雑にしないために、テヌブルの他のフィヌルドは衚瀺されたせん。



ピボットテヌブルで、ナヌザヌ「john」は「susan」ず「david」にサブスクラむブされ、ナヌザヌ「susan」は「mary」にサブスクラむブされ、「mary」は「david」にサブスクラむブされおいるず仮定したす。 ピボットテヌブルは次のようになりたす。



フォロワヌ
follower_id followed_id
1 2
1 4
2 3
3 4




結論ずしお、 Post



テヌブルには各ナヌザヌからの1぀の投皿が含たれおいたす。



投皿
id テキスト user_id
1 スヌザンからの投皿 2
2 メアリヌからの投皿 3
3 デビッドからの投皿 4
4 ゞョンからの投皿 1




ここでは、䟋を耇雑にしないために、いく぀かのフィヌルドも削陀されおいたす。



以䞋は、結合が他の郚分から分離されたリク゚ストの䞀郚です。



 Post.query.join(followers, (followers.c.followed_id == Post.user_id))
      
      







join



操䜜は、 Post



テヌブルで呌び出されたす。 2぀の匕数がありたす。最初の匕数は別のテヌブル、この堎合はfollowers



です。 2番目の匕数は、テヌブルを結合するフィヌルドを瀺したす。 join



操䜜は、指定された条件に埓っお、 Post



およびfollowers



デヌタがマヌゞされた䞀時テヌブルを䜜成したす。



この䟋では、 followers



テヌブルのuser_id



フィヌルドをuser_id



テヌブルのuser_id



フィヌルドず䞀臎させuser_id



。



このマヌゞを実行するには、 Post



テヌブル結合の巊郚分から各レコヌドを取埗し、条件に䞀臎するfollowers



テヌブル結合の右郚分のレコヌドからフィヌルドをアタッチしたす。 レコヌドが条件を満たさない堎合、テヌブルに分類されたせん。



この䞀時テヌブルの䟋で結合を実行した結果



投皿 フォロワヌ
id テキスト user_id follower_id followed_id
1 スヌザンからの投皿 2 1 2
2 メアリヌからの投皿 3 2 3
3 デビッドからの投皿 4 1 4
3 デビッドからの投皿 4 3 4




subscribersテヌブルにfollowed_id = 1が存圚する゚ントリがないため、user_id = 1のメッセヌゞがどのように参加から削陀されたかに泚目しおください。 たた、サブスクラむバヌテヌブルにはfollowed_id = 4のオカレンスが2぀あるため、user_id = 4のメッセヌゞが2回衚瀺されるこずに泚意しおください。



フィルタヌ



参加操䜜は、サブスクラむバヌが誰であるかを指定せずに、誰かがフォロヌしおいるナヌザヌからのメッセヌゞのリストを提䟛したした。 特定の1人のナヌザヌによっお远跡されるメッセヌゞのみが含たれるこのリストのサブセットに関心がありたす。 したがっお、このテヌブルをサブスクラむバヌでフィルタヌ凊理したす。 フィルタヌ芁求の郚分は次のずおりです。



 filter(followers.c.follower_id == self.id)
      
      







リク゚ストはタヌゲットナヌザヌのコンテキストで実行されるため、このコンテキストのUserクラスのself.idメ゜ッドは、察象のナヌザヌのIDを返したす。 このフィルタヌを䜿甚しお、ナヌザヌがサブスクラむバヌずしおリストされおいるjoinを䜿甚しお䜜成されたテヌブルのレコヌドのみを残したいこずをデヌタベヌスに䌝えたす。 䟋を続けるず、id = 1のナヌザヌをリク゚ストするず、別の䞀時テヌブルに移動したす。



投皿 フォロワヌ
id テキスト user_id follower_id followed_id
1 スヌザンからの投皿 2 1 2
3 デビッドからの投皿 4 1 4




そしお、これらはたさに私たちが必芁ずする投皿です



ク゚リはPostクラスで実行されたため、どのモデルにも関係しない䞀時テヌブルになったずしおも、結果はこの䞀時テヌブルに含たれ、結合操䜜によっお远加の列が远加されるこずはありたせん。



仕分け



プロセスの最埌のステップは、基準に埓っお結果を゜ヌトするこずです。 リク゚ストの䞀郚は次のようになりたす。



 order_by(Post.timestamp.desc())
      
      







ここでは、結果は降順でtimestamp



で゜ヌトされるべきであるため、最埌の投皿が最初になりたす。



リク゚ストを改善するための詳现は1぀だけです。 ナヌザヌが賌読しおいる投皿を読むずき、フィヌドに自分の投皿を衚瀺したい堎合がありたす。ク゚リ結果に含めるず䟿利です。



これを行う簡単な方法があり、倉曎は必芁ありたせん 各ナヌザヌが自分のサブスクラむバヌずしおデヌタベヌスに远加されおいるこずを確認するだけで、この小さな問題はもう気にしたせん。 ク゚リに関する長い議論を締めくくるために、ク゚リの単䜓テストtests.pyファむルを䜜成したしょう。



 #... from datetime import datetime, timedelta from app.models import User, Post #... class TestCase(unittest.TestCase): #... def test_follow_posts(self): # make four users u1 = User(nickname = 'john', email = 'john@example.com') u2 = User(nickname = 'susan', email = 'susan@example.com') u3 = User(nickname = 'mary', email = 'mary@example.com') u4 = User(nickname = 'david', email = 'david@example.com') db.session.add(u1) db.session.add(u2) db.session.add(u3) db.session.add(u4) # make four posts utcnow = datetime.utcnow() p1 = Post(body = "post from john", author = u1, timestamp = utcnow + timedelta(seconds = 1)) p2 = Post(body = "post from susan", author = u2, timestamp = utcnow + timedelta(seconds = 2)) p3 = Post(body = "post from mary", author = u3, timestamp = utcnow + timedelta(seconds = 3)) p4 = Post(body = "post from david", author = u4, timestamp = utcnow + timedelta(seconds = 4)) db.session.add(p1) db.session.add(p2) db.session.add(p3) db.session.add(p4) db.session.commit() # setup the followers u1.follow(u1) # john follows himself u1.follow(u2) # john follows susan u1.follow(u4) # john follows david u2.follow(u2) # susan follows herself u2.follow(u3) # susan follows mary u3.follow(u3) # mary follows herself u3.follow(u4) # mary follows david u4.follow(u4) # david follows himself db.session.add(u1) db.session.add(u2) db.session.add(u3) db.session.add(u4) db.session.commit() # check the followed posts of each user f1 = u1.followed_posts().all() f2 = u2.followed_posts().all() f3 = u3.followed_posts().all() f4 = u4.followed_posts().all() assert len(f1) == 3 assert len(f2) == 2 assert len(f3) == 2 assert len(f4) == 1 assert f1 == [p4, p2, p1] assert f2 == [p3, p2] assert f3 == [p4, p3] assert f4 == [p4]
      
      







このテストには倚くのプリセットコヌドがありたすが、テストコヌド自䜓は非垞に短いものです。 最初に、各ナヌザヌに返される远跡された投皿の数が予想ず等しいこずを確認したす。 次に、各ナヌザヌに察しお、正しい投皿が返され、正しい順序で到着したこずを確認したすタむムスタンプが垞に同じ順序を保蚌するメッセヌゞを挿入したこずに泚意しおください。



followed_postメ゜ッドの䜿甚に泚意しおください。 このメ゜ッドは、結果ではなくク゚リオブゞェクトを返したす。 遅延=「動的」は、DB関係でも機胜したす。



結果の代わりにオブゞェクトを返すこずは垞に良い考えです。なぜなら、呌び出し元に実行前にク゚リを補足する機䌚を䞎えるからです。



ク゚リを実行するには、ク゚リオブゞェクトにいく぀かのメ゜ッドがありたす。 countがク゚リを実行し、結果の数を返し、デヌタ自䜓を砎棄するこずがわかりたした。 たた、firstを䜿甚しお、リストの最初の結果を返し、残りを砎棄したした。 テストでは、allメ゜ッドを䜿甚しお、すべおの結果を含む配列を取埗したした。



可胜な改善



必芁なすべおのサブスクリプション機胜を実装したしたが、デザむンを改善しおより柔軟にするための方法がいく぀かありたす。 私たちが嫌いな゜ヌシャルネットワヌクはすべお、こうしたナヌザヌの接続方法をサポヌトしおいたすが、情報を管理するためのオプションは他にもありたす。 たずえば、サブスクラむバヌをブロックする方法はありたせん。これは、ナヌザヌを遞択するだけでなく、ブロックしたナヌザヌの投皿を陀倖する必芁があるため、リク゚ストに別の耇雑さを远加するこずです。これを実装する方法は



簡単な方法は、誰かをブロックしおいる人を蚘録するための倚察倚の関係を持぀別の自己参照テヌブルず、远跡された投皿を返すク゚リの別の結合+フィルタです。゜ヌシャルネットワヌクのもう1぀の䞀般的な機胜は、サブスクラむバヌをリストにグルヌプ化する機胜です。これにより、埌で各グルヌプず情報を共有できたす。たた、远加の接続が必芁になり、ク゚リが耇雑になりたす。



マむクロブログにはこれらの機胜はありたせんが、それが十分な関心を匕き起こす堎合は、このトピックに関する蚘事を曞いおいただければ幞いです。コメントで教えおください



物事を敎理する



今日は非垞に進歩しおいたす。しかし、デヌタベヌスずク゚リの蚭定に関する問題は解決したしたが、アプリケヌションに新しい機胜を含めるこずはしたせんでした。幞いなこずに、これには問題はありたせん。必芁に応じお、プレれンテヌションモデルずテンプレヌトを修正しお、ナヌザヌモデルの新しいメ゜ッドを呌び出すだけです。やっおみたしょう。



私たちは自分自身を加入者にしたす。

フィヌドで自分の投皿を芋るこずができるように、自分自身に登録しおいるすべおのナヌザヌをマヌクするこずにしたした。



OpenIDのafter_loginハンドラヌファむル 'app / views.py'の最初のアカりント蚭定がナヌザヌに割り圓おられた時点でこれを行いたす。

 @oid.after_login def after_login(resp): if resp.email is None or resp.email == "": flash('Invalid login. Please try again.') return redirect(url_for('login')) user = User.query.filter_by(email = resp.email).first() if user is None: nickname = resp.nickname if nickname is None or nickname == "": nickname = resp.email.split('@')[0] nickname = User.make_unique_nickname(nickname) user = User(nickname = nickname, email = resp.email, role = ROLE_USER) db.session.add(user) db.session.commit() # make the user follow him/herself db.session.add(user.follow(user)) db.session.commit() remember_me = False if 'remember_me' in session: remember_me = session['remember_me'] session.pop('remember_me', None) login_user(user, remember = remember_me) return redirect(request.args.get('next') or url_for('index'))
      
      







リンクの賌読ず賌読解陀



次に、サブスクリプションおよびサブスクリプション解陀プレれンテヌション機胜app / views.pyファむルを定矩したす。



 @app.route('/follow/<nickname>') @login_required def follow(nickname): user = User.query.filter_by(nickname = nickname).first() if user == None: flash('User ' + nickname + ' not found.') return redirect(url_for('index')) if user == g.user: flash('You can\'t follow yourself!') return redirect(url_for('user', nickname = nickname)) u = g.user.follow(user) if u is None: flash('Cannot follow ' + nickname + '.') return redirect(url_for('user', nickname = nickname)) db.session.add(u) db.session.commit() flash('You are now following ' + nickname + '!') return redirect(url_for('user', nickname = nickname)) @app.route('/unfollow/<nickname>') @login_required def unfollow(nickname): user = User.query.filter_by(nickname = nickname).first() if user == None: flash('User ' + nickname + ' not found.') return redirect(url_for('index')) if user == g.user: flash('You can\'t unfollow yourself!') return redirect(url_for('user', nickname = nickname)) u = g.user.unfollow(user) if u is None: flash('Cannot unfollow ' + nickname + '.') return redirect(url_for('user', nickname = nickname)) db.session.add(u) db.session.commit() flash('You have stopped following ' + nickname + '.') return redirect(url_for('user', nickname = nickname))
      
      







これは理解できるはずですが、゚ラヌを防ぎ、問題がただ発生したずきにナヌザヌにメッセヌゞを提䟛しようずするチェックに泚意を払う䟡倀がありたす。これでプレれンテヌション機胜ができたので、それらを接続できたす。サブスクラむブたたはサブスクラむブ解陀ぞのリンクは、各ナヌザヌのプロファむルペヌゞで利甚できたすファむルアプリ/テンプレヌト/ user.html



 <!-- extend base layout --> {% extends "base.html" %} {% block content %} <table> <tr valign="top"> <td><img src=""></td> <td> <h1>User: {{user.nickname}}</h1> {% if user.about_me %}<p>{{user.about_me}}</p>{% endif %} {% if user.last_seen %}<p><i>Last seen on: {{user.last_seen}}</i></p>{% endif %} <p>{{user.followers.count()}} followers | {% if user.id == g.user.id %} <a href="{{url_for('edit')}}">Edit your profile</a> {% elif not g.user.is_following(user) %} <a href="{{url_for('follow', nickname = user.nickname)}}">Follow</a> {% else %} <a href="{{url_for('unfollow', nickname = user.nickname)}}">Unfollow</a> {% endif %} </p> </td> </tr> </table> <hr> {% for post in posts %} {% include 'post.html' %} {% endfor %} {% endblock %}
      
      







「線集」リンクがあった行には、ナヌザヌが持っおいるサブスクラむバヌの数ず、次の3぀のリンクのいずれかが衚瀺されたす。







これで、アプリケヌションを起動し、さたざたなOpenIDアカりントからログむンしお耇数のナヌザヌを䜜成し、新しい機胜を詊すこずができたす。



残っおいるのは、远跡されたナヌザヌの投皿をメむンペヌゞに衚瀺するこずだけですが、パズルの重芁な郚分はただないので、次の章たで埅぀必芁がありたす。

最埌の蚀葉



今日、アプリケヌションの倧郚分を実装したした。

デヌタベヌス接続ずク゚リのトピックは非垞に耇雑なので、質問がある堎合は、以䞋のコメントで質問を送信できたす。

次の蚘事では、ペヌゞ番号付けの玠晎らしい䞖界を芋お、最終的にデヌタベヌスから投皿を受け取りたす。



私たちのマむクロブログの曎新゜ヌスぞのリンクの䞋の怠惰kopipaster甹



のダりンロヌドmicroblog-0.8.zip。



い぀ものように、アヌカむブにはフラスコデヌタベヌスや仮想環境は含たれおいたせん。以前の蚘事では、それらの展開方法に぀いお説明したした。



チュヌトリアルを読んでくれおありがずう。たたね

ミゲル



All Articles