私たちはWtにニュースサイトを書いています

まず、私自身について少しお話しします。 「コンピューター、システム、システム、ネットワーク」を専門とするモスクワ航空研究所の4年生であり、初心者のC ++ / Qtプログラマーでもあります。 長い間、私はウェブ開発を学びたかったのですが、私の手はすべての必要な言語と技術の研究に到達しませんでした。 最近、 C ++ Wtライブラリを使用したWebアプリケーションの作成に関する記事が Habrに掲載され、このライブラリについて詳しく知ることにしました。



職場の準備



Qt CreatorのGentoo-linuxで書いたすべてのコード。 同じことをすることに決めた場合は、まず、ニーズに合わせて環境を準備する必要があります。

最初に行うことは、プロジェクトの作成です。 Qtサポートなしで「Simple C ++ Project」を使用しました。 WtはQtと組み合わせて使用​​できますが、この場合は必要ありません。





MyAppプロジェクトを呼び出しました。 次に、MyApp.proファイルを開き、少し編集します。 つまり、私の場合、次の行を追加する必要があります。



LIBS + = -L / usr / lib -lwt -lwthttp -lwtdbo -lwtdbosqlite3 -I / usr / local / include

LIBS + = -L / usr / local / lib -lwthttp -lwt -lboost_regex -lboost_signals

LIBS + = -lboost_system -lboost_thread -lboost_filesystem -lboost_date_time -lpthread -lcrypt





また、リソースフォルダーを、サイトを起動する場所にリンクする必要があります。 たとえば、次のように:

ln -s /usr/share/Wt/resources/ ~/build-MyApp-Qt5-/







この準備は完了していると考えることができます。



それでは始めましょう...



空のアプリケーションを起動するには、次のコードを書くだけで十分です。

 #include <iostream> #include <Wt/WServer> #include <Wt/WApplication> using namespace Wt; WApplication *createWidget(const WEnvironment& env) { WApplication *app=new WApplication(env); //  - app->setTitle("My Site"); //   ( ,   html <title></title>) app->setTheme(new Wt::WBootstrapTheme()); //   bootstrap return app; } int main(int argc, char **argv) { Wt::WServer server(argv[0]); //  server.setServerConfiguration(argc, argv, WTHTTP_CONFIGURATION); //  server.addEntryPoint(Wt::Application,createWidget); // " " if (server.start()) { int sig = Wt::WServer::waitForShutdown(); // ,   std::cerr << "Shutting down: (signal = " << sig << ")" << std::endl; server.stop(); } }
      
      







次のコマンドを使用して、これらすべてをlocalhostのポート8080で実行できます。



./myapp --docroot . --http-address 0.0.0.0 --http-port 8080







起動プロセスは自動化できます;このため、「Projects-> Run-> Parameters」行に起動パラメータを入力する必要があります







したがって、空のページを持つWebサーバーを取得します。 localhost:8080/







メニューを追加します。



記入を始めましょう。 まず、サイトのメニューを作成します。 これを行うには、新しいクラスを作成し、「ページ」と呼びます。

page.h:



 #ifndef PAGE_H #define PAGE_H #include <Wt/WContainerWidget> #include <Wt/WText> #include <Wt/WString> #include <Wt/WNavigationBar> #include <Wt/WMenu> #include <Wt/WStackedWidget> class Page : public Wt::WContainerWidget { public: Page(WContainerWidget *parent = 0); private: Wt::WStackedWidget *contentsStack; Wt::WNavigationBar *NavBar; Wt::WMenu *LeftMenu; }; #endif // PAGE_H
      
      







page.cpp:



 #include "page.h" using namespace Wt; Page::Page(WContainerWidget *parent):WContainerWidget(parent) { setStyleClass("container"); contentsStack = new Wt::WStackedWidget(); //  ""   ,     contentsStack->setStyleClass("container"); contentsStack->setPadding(48,Wt::Top); //,           "" NavBar = new WNavigationBar(this); //   NavBar->setTitle("MyApp","http://localhost:8080"); //    ,    NavBar->setResponsive(true); //       NavBar->addStyleClass("container"); // bootstrap NavBar->setPositionScheme(Wt::Fixed); //    LeftMenu=new WMenu(contentsStack,this); //  . ,    . NavBar->addMenu(LeftMenu); //     LeftMenu->addItem(WString::fromUTF8(""),new WText(WString::fromUTF8("  "))); //    "". addWidget(contentsStack); //    ,     ,    -  . }
      
      







同時に、main.cppに行を追加する必要があります



 ... WApplication *createWidget(const WEnvironment& env) { WApplication *app=new WApplication(env); app->setTitle("My Site"); app->setTheme(new Wt::WBootstrapTheme()); new Page(app->root()); // ! return app; } ...
      
      







私たちはチェックします:







言ってみよう。 ニュースはどこですか?



今、それらに着きます。 まず、データベースを操作する方法を学ぶ必要があります。

Wtでは、データベースの操作は、私にとってはかなり奇妙に実装されていますが、原則を理解したとき、特別な問題や困難はもうありませんでした。



最初に必要なことは、ニュースレターのテンプレートをクラスとして作成することです。



news.h:



 #ifndef NEWS_H #define NEWS_H #include <Wt/WDateTime> #include <Wt/Dbo/Types> #include <Wt/Dbo/WtSqlTraits> class News { public: News(); std::string title; //  std::string text; //  std::string author; //  Wt::WDateTime created; //  template<class Action> //       void persist(Action& a) { Wt::Dbo::field(a, title, "title"); Wt::Dbo::field(a, text, "text"); Wt::Dbo::field(a, author, "aurhor"); Wt::Dbo::field(a, created, "created"); } }; DBO_EXTERN_TEMPLATES(News); #endif // NEWS_H
      
      





news.cpp:

 #include "news.h" #include <Wt/Dbo/Impl> DBO_INSTANTIATE_TEMPLATES(News); News::News(): created(Wt::WDateTime::currentDateTime()) //   ,  ,      . {}
      
      







「うーん、それの使い方は?」とあなたは尋ねます。 すべてが非常に簡単です。 私はsqlite3を何らかの理由で使用しました(プロジェクトとの移植性と、MySQLのWtのサポートは不明な理由でコンパイルされていなかったため)。



page.cppを書き換えます:



 #include "page.h" #include "news.h" #include <Wt/Dbo/backend/Sqlite3> #include <Wt/WApplication> #include <Wt/WPanel> using namespace Wt; Page::Page(WContainerWidget *parent):WContainerWidget(parent) { Wt::Dbo::backend::Sqlite3 DataBase=WApplication::instance()->appRoot() + "myapp.db"; //   Wt::Dbo::Session DBSession; //  DBSession.setConnection(DataBase); // DBSession.mapClass<News>("news"); //     news   Wt::Dbo::Transaction transaction(DBSession); //  try { DBSession.createTables(); //     ,      .     . Wt::log("info") << "Database created"; } catch (...) { Wt::log("info") << "Using existing database"; } transaction.commit();//  Wt::WTable *NewsTable=new Wt::WTable();//     NewsTable->addStyleClass("container");//    Wt::Dbo::Transaction transaction1(DBSession);//  .       ,   . Wt::Dbo::collection<Wt::Dbo::ptr<News> > a=DBSession.find<News>().orderBy("created desc");//    ,      . int j=0; for (Wt::Dbo::collection<Wt::Dbo::ptr<News> >::const_iterator i = a.begin(); i != a.end(); ++i) {//  .       ,        .   =) Wt::Dbo::ptr<News> Article = *i; Wt::WPanel *panel = new Wt::WPanel(); panel->setTitle(Article.get()->title); panel->setCentralWidget(new Wt::WText(WString::fromUTF8("<p>:")+Article.get()->author+"</p><p>"+Article.get()->text+"</p>")); NewsTable->elementAt(j,0)->addWidget(panel); j++; } transaction1.commit();// . ,    . setStyleClass("container"); contentsStack = new Wt::WStackedWidget(); contentsStack->setStyleClass("container"); contentsStack->setPadding(48,Wt::Top); NavBar = new WNavigationBar(this); NavBar->setTitle("MyApp","http://cursed.redegrade.net"); NavBar->setResponsive(true); NavBar->addStyleClass("container"); NavBar->setPositionScheme(Wt::Fixed); LeftMenu=new WMenu(contentsStack,this); NavBar->addMenu(LeftMenu); LeftMenu->addItem(WString::fromUTF8(""),NewsTable); //       . this->addWidget(contentsStack); }
      
      







さて、ニュースの出力に関しては、すべてが明確ですが、作成についてはどうですか?



うーん、本当に。 創造なしの場所。 締めます。 記事内で最後に、Pageクラスを再度書き換える必要があります。



page.h:



 #ifndef PAGE_H #define PAGE_H #include <Wt/WContainerWidget> #include <Wt/WText> #include <Wt/WString> #include <Wt/WNavigationBar> #include <Wt/WMenu> #include <Wt/WTable> #include <Wt/WStackedWidget> #include <Wt/Dbo/Session> class Page : public Wt::WContainerWidget { public: Page(WContainerWidget *parent = 0); private: Wt::WStackedWidget *contentsStack; Wt::WNavigationBar *NavBar; Wt::WMenu *LeftMenu; Wt::WTable *CreateArticle; Wt::WLineEdit *Title; Wt::WLineEdit *Author; Wt::WTextArea *Text; Wt::WPushButton *AddNews; Wt::Dbo::Session DBSession; void AddArticle(); }; #endif // PAGE_H
      
      







page.cpp



 #include "page.h" #include "news.h" #include <Wt/WApplication> #include <Wt/WPanel> #include <Wt/WLineEdit> #include <Wt/WTextEdit> #include <Wt/WPushButton> #include <Wt/Dbo/backend/Sqlite3> using namespace Wt; Page::Page(WContainerWidget *parent):WContainerWidget(parent) { Wt::Dbo::backend::Sqlite3 DataBase=WApplication::instance()->appRoot() + "myapp.db"; DBSession.setConnection(DataBase); DBSession.mapClass<News>("news"); Wt::Dbo::Transaction transaction(DBSession); try { DBSession.createTables(); Wt::log("info") << "Database created"; } catch (...) { Wt::log("info") << "Using existing database"; } transaction.commit(); Wt::WTable *NewsTable=new Wt::WTable(); NewsTable->addStyleClass("container"); Wt::Dbo::Transaction transaction1(DBSession); Wt::Dbo::collection<Wt::Dbo::ptr<News> > a=DBSession.find<News>().orderBy("created desc"); int j=0; for (Wt::Dbo::collection<Wt::Dbo::ptr<News> >::const_iterator i = a.begin(); i != a.end(); ++i) { Wt::Dbo::ptr<News> Article = *i; Wt::WPanel *panel = new Wt::WPanel(); panel->setTitle(WString::fromUTF8(Article.get()->title)); panel->setCentralWidget(new Wt::WText(WString::fromUTF8("<p>:")+WString::fromUTF8(Article.get()->author)+"</p><p>"+WString::fromUTF8(Article.get()->text)+"</p>"));//  .        . NewsTable->elementAt(j,0)->addWidget(panel); NewsTable->elementAt(j,0)->setLoadLaterWhenInvisible(true); j++; } transaction1.commit(); setStyleClass("container"); contentsStack = new Wt::WStackedWidget(); contentsStack->setStyleClass("container"); contentsStack->setPadding(48,Wt::Top); NavBar = new WNavigationBar(this); NavBar->setTitle("MyApp","http://localhost:8080"); NavBar->setResponsive(true); NavBar->addStyleClass("container"); NavBar->setPositionScheme(Wt::Fixed); LeftMenu=new WMenu(contentsStack,this); NavBar->addMenu(LeftMenu); LeftMenu->addItem(WString::fromUTF8(""),NewsTable); CreateArticle=new Wt::WTable(); //     Title=new Wt::WLineEdit(WString::fromUTF8(" ")); //  Author=new Wt::WLineEdit(WString::fromUTF8("")); Text=new Wt::WTextArea(WString::fromUTF8(" ")); AddNews=new Wt::WPushButton(WString::fromUTF8(" ")); CreateArticle->addStyleClass("container"); CreateArticle->elementAt(0,0)->addWidget(Title); //    CreateArticle->elementAt(1,0)->addWidget(Author); CreateArticle->elementAt(2,0)->addWidget(Text); CreateArticle->elementAt(3,0)->addWidget(AddNews); LeftMenu->addItem(WString::fromUTF8(" "),CreateArticle); //     Page::AddArticle    AddNews->clicked().connect(this,&Page::AddArticle); this->addWidget(contentsStack); } void Page::AddArticle() { Wt::Dbo::backend::Sqlite3 DataBase=WApplication::instance()->appRoot() + "myapp.db"; DBSession.setConnection(DataBase); // (   , ,     ,   ) Wt::Dbo::Transaction transaction(DBSession); //:        . News *a=new News(); //  a->title=Title->text().toUTF8(); a->author=Author->text().toUTF8(); a->text=Text->text().toUTF8(); Wt::Dbo::ptr<News> Article=DBSession.add(a); //    }
      
      







結果:









PS追加の説明が必要な場合は、コメントを書き込んでください。詳細を説明します。 私はWtを学び始めたばかりなので、どこかで間違っている可能性が十分にあります。 正しければ嬉しいです。

PPS Wtの記事に興味があるなら、コメントで他に彼について知りたいことを書いてください。私はそれについて書きます。



All Articles