{"id":34078,"date":"2025-11-10T22:40:59","date_gmt":"2025-11-10T19:40:59","guid":{"rendered":"https:\/\/fatihsoysal.com\/blog\/?p=34078"},"modified":"2025-11-10T22:40:59","modified_gmt":"2025-11-10T19:40:59","slug":"bottle-mikro-cercevesini-kullanarak-python-web-uygulamalari-gelistirme-rehberi","status":"publish","type":"post","link":"https:\/\/fatihsoysal.com\/blog\/bottle-mikro-cercevesini-kullanarak-python-web-uygulamalari-gelistirme-rehberi\/","title":{"rendered":"Bottle Mikro \u00c7er\u00e7evesini Kullanarak Python Web Uygulamalar\u0131 Geli\u015ftirme Rehberi"},"content":{"rendered":"<p><body><\/p>\n<h2>Bottle Mikro \u00c7er\u00e7evesini Kullanarak Python Web Uygulamalar\u0131 Geli\u015ftirme Rehberi<\/h2>\n<p>Python ekosistemi, web geli\u015ftirme i\u00e7in zengin bir ara\u00e7 yelpazesi sunar. Django ve Flask gibi pop\u00fcler \u00e7er\u00e7eveler genellikle karma\u015f\u0131k ve b\u00fcy\u00fck \u00f6l\u00e7ekli projeler i\u00e7in tercih edilirken, daha k\u00fc\u00e7\u00fck, h\u0131zl\u0131 ve hafif \u00e7\u00f6z\u00fcmlere ihtiya\u00e7 duyuldu\u011funda mikro \u00e7er\u00e7eveler devreye girer. Bu makalede, Python&#8217;\u0131n en basit ve en etkili mikro \u00e7er\u00e7evelerinden biri olan Bottle&#8217;\u0131 derinlemesine inceleyece\u011fiz. Bottle ile web uygulamalar\u0131 geli\u015ftirmenin temel prensiplerini, ileri seviye \u00f6zelliklerini ve en iyi uygulamalar\u0131n\u0131 ad\u0131m ad\u0131m ke\u015ffedece\u011fiz.<\/p>\n<h3>Giri\u015f: Bottle Mikro \u00c7er\u00e7evesi Nedir ve Neden Tercih Edilmelidir?<\/h3>\n<p>Bottle, tek bir Python dosyas\u0131 olarak da\u011f\u0131t\u0131lan, h\u0131zl\u0131, basit ve hafif bir WSGI mikro web \u00e7er\u00e7evesidir. Harici bir k\u00fct\u00fcphaneye ba\u011f\u0131ml\u0131l\u0131\u011f\u0131 yoktur (sadece Python Standart K\u00fct\u00fcphanesi&#8217;ni kullan\u0131r) ve bu \u00f6zelli\u011fi onu inan\u0131lmaz derecede ta\u015f\u0131nabilir ve \u00f6\u011frenmesi kolay k\u0131lar. Bottle&#8217;\u0131n felsefesi &#8220;her \u015feyi yapmaya \u00e7al\u0131\u015fma&#8221; \u00fczerine kuruludur; bunun yerine, web uygulamalar\u0131 olu\u015fturmak i\u00e7in gerekli temel i\u015flevleri (y\u00f6nlendirme, \u015fablonlama, statik dosya sunumu vb.) minimalist bir \u015fekilde sa\u011flar.<\/p>\n<h4>Bottle&#8217;\u0131n Temel \u00d6zellikleri<\/h4>\n<p>*   <strong>Tek Dosya:<\/strong> Bottle, tek bir <code>.py<\/code> dosyas\u0131ndan olu\u015fur, bu da onu kurmay\u0131 ve da\u011f\u0131tmay\u0131 son derece basit hale getirir.<br \/>\n*   <strong>Ba\u011f\u0131ml\u0131l\u0131ks\u0131z:<\/strong> Python standart k\u00fct\u00fcphanesi d\u0131\u015f\u0131nda hi\u00e7bir harici ba\u011f\u0131ml\u0131l\u0131\u011f\u0131 yoktur.<br \/>\n*   <strong>H\u0131zl\u0131 ve Hafif:<\/strong> Minimum bellek ve i\u015flemci kullan\u0131m\u0131yla y\u00fcksek performans sunar.<br \/>\n*   <strong>WSGI Uyumlulu\u011fu:<\/strong> Gunicorn, uWSGI, CherryPy gibi pop\u00fcler WSGI sunucular\u0131yla sorunsuz \u00e7al\u0131\u015f\u0131r.<br \/>\n*   <strong>Yerle\u015fik \u015eablon Motoru:<\/strong> Basit ve h\u0131zl\u0131 bir \u015fablon motoruna sahiptir, ancak Jinja2 veya Mako gibi di\u011fer motorlarla da entegre edilebilir.<br \/>\n*   <strong>URL Y\u00f6nlendirme:<\/strong> Dinamik URL&#8217;ler, HTTP metotlar\u0131 ve d\u00fczenli ifadelerle g\u00fc\u00e7l\u00fc y\u00f6nlendirme yetenekleri sunar.<br \/>\n*   <strong>Esneklik:<\/strong> \u0130htiya\u00e7 duyulan her \u015feyi kendi ba\u015f\u0131na sa\u011flamak yerine, geli\u015ftiricilere \u00fc\u00e7\u00fcnc\u00fc taraf k\u00fct\u00fcphaneleri (veritaban\u0131 ORM&#8217;leri, kimlik do\u011frulama, form do\u011frulama vb.) entegre etme \u00f6zg\u00fcrl\u00fc\u011f\u00fc verir.<\/p>\n<h4>Neden Bottle Kullanmal\u0131s\u0131n\u0131z?<\/h4>\n<p>*   <strong>H\u0131zl\u0131 Prototipleme:<\/strong> H\u0131zla bir API veya k\u00fc\u00e7\u00fck bir web uygulamas\u0131 olu\u015fturman\u0131z gerekti\u011finde idealdir.<br \/>\n*   <strong>\u00d6\u011frenme Kolayl\u0131\u011f\u0131:<\/strong> Python&#8217;a yeni ba\u015flayanlar veya web \u00e7er\u00e7evelerine giri\u015f yapmak isteyenler i\u00e7in m\u00fckemmel bir ba\u015flang\u0131\u00e7 noktas\u0131d\u0131r.<br \/>\n*   <strong>K\u00fc\u00e7\u00fck ve Orta \u00d6l\u00e7ekli Projeler:<\/strong> Karma\u015f\u0131k bir veritaban\u0131 \u015femas\u0131na veya kullan\u0131c\u0131 y\u00f6netimine ihtiya\u00e7 duymayan projeler i\u00e7in uygundur.<br \/>\n*   <strong>Mikroservisler:<\/strong> Hafif ve ba\u011f\u0131ms\u0131z mikroservisler geli\u015ftirmek i\u00e7in harika bir se\u00e7enektir.<br \/>\n*   <strong>G\u00f6m\u00fcl\u00fc Sistemler:<\/strong> Kaynak k\u0131s\u0131tl\u0131 ortamlarda web aray\u00fczleri sa\u011flamak i\u00e7in kullan\u0131labilir.<\/p>\n<h3>Ba\u015flang\u0131\u00e7: Bottle Kurulumu ve \u0130lk Uygulaman\u0131z<\/h3>\n<p>Bottle ile web uygulamas\u0131 geli\u015ftirmeye ba\u015flamak olduk\u00e7a basittir. \u0130lk ad\u0131m, Bottle&#8217;\u0131 Python ortam\u0131n\u0131za kurmakt\u0131r.<\/p>\n<h4>Bottle Kurulumu<\/h4>\n<p>Python y\u00fckl\u00fc bir sistemde, terminalinizi a\u00e7\u0131n ve a\u015fa\u011f\u0131daki komutu \u00e7al\u0131\u015ft\u0131r\u0131n:<\/p>\n<pre><code class=\"language-bash\">pip install bottle<\/code><\/pre>\n<p>Bu komut, Bottle k\u00fct\u00fcphanesini sanal ortam\u0131n\u0131za veya sisteminize kuracakt\u0131r.<\/p>\n<h4>&#8220;Merhaba D\u00fcnya!&#8221; Uygulamas\u0131<\/h4>\n<p>\u015eimdi, Bottle ile ilk web uygulaman\u0131z\u0131 olu\u015ftural\u0131m. <code>app.py<\/code> ad\u0131nda bir dosya olu\u015fturun ve i\u00e7ine a\u015fa\u011f\u0131daki kodu yap\u0131\u015ft\u0131r\u0131n:<\/p>\n<pre><code class=\"language-python\">from bottle import route, run, template\n\n@route('\/')\ndef index():\n    return \"Merhaba, D\u00fcnya!\"\n\n@route('\/hello\/<name>')\ndef hello(name):\n    return template('<b>Merhaba {{name}}<\/b>!', name=name)\n\nif __name__ == '__main__':\n    run(host='localhost', port=8080, debug=True, reloader=True)<\/code><\/pre>\n<p>Bu kod par\u00e7as\u0131, Bottle ile temel bir web uygulamas\u0131n\u0131n nas\u0131l olu\u015fturulaca\u011f\u0131n\u0131 g\u00f6stermektedir.<\/p>\n<p>*   <code>from bottle import route, run, template<\/code>: Bottle k\u00fct\u00fcphanesinden gerekli fonksiyonlar\u0131 i\u00e7e aktar\u0131yoruz.<br \/>\n*   <code>@route('\/')<\/code>: Bu dekorat\u00f6r, ana URL (<code>\/<\/code>) i\u00e7in bir y\u00f6nlendirme tan\u0131mlar. Kullan\u0131c\u0131 bu adrese gitti\u011finde, <code>index()<\/code> fonksiyonu \u00e7al\u0131\u015f\u0131r.<br \/>\n*   <code>index()<\/code>: Bu fonksiyon, taray\u0131c\u0131ya &#8220;Merhaba, D\u00fcnya!&#8221; metnini d\u00f6nd\u00fcr\u00fcr.<br \/>\n*   <code>@route('\/hello\/<name>')<\/code>: Bu, dinamik bir URL y\u00f6nlendirmesidir. <code><name><\/code> k\u0131sm\u0131, URL&#8217;den al\u0131nan bir parametreyi temsil eder. \u00d6rne\u011fin, <code>\/hello\/Ali<\/code> adresine gidildi\u011finde <code>name<\/code> parametresi &#8220;Ali&#8221; olacakt\u0131r.<br \/>\n*   <code>hello(name)<\/code>: Bu fonksiyon, al\u0131nan <code>name<\/code> parametresini kullanarak bir \u015fablonu i\u015fler ve taray\u0131c\u0131ya d\u00f6nd\u00fcr\u00fcr. Bottle&#8217;\u0131n yerle\u015fik <code>template<\/code> fonksiyonunu kullanarak HTML \u00e7\u0131kt\u0131s\u0131 olu\u015fturuyoruz.<br \/>\n*   <code>if __name__ == '__main__':<\/code>: Bu blok, beti\u011fin do\u011frudan \u00e7al\u0131\u015ft\u0131r\u0131ld\u0131\u011f\u0131nda Bottle sunucusunu ba\u015flat\u0131r.<br \/>\n*   <code>run(host='localhost', port=8080, debug=True, reloader=True)<\/code>: Bottle&#8217;\u0131n geli\u015ftirme sunucusunu ba\u015flat\u0131r.<br \/>\n    *   <code>host='localhost'<\/code>: Uygulaman\u0131n sadece yerel makineden eri\u015filebilir olmas\u0131n\u0131 sa\u011flar.<br \/>\n    *   <code>port=8080<\/code>: Uygulaman\u0131n 8080 portunda \u00e7al\u0131\u015fmas\u0131n\u0131 sa\u011flar.<br \/>\n    *   <code>debug=True<\/code>: Hata ay\u0131klama modunu etkinle\u015ftirir. Hatalar taray\u0131c\u0131da g\u00f6r\u00fcnt\u00fclenir ve daha fazla bilgi sa\u011flar.<br \/>\n    *   <code>reloader=True<\/code>: Dosyalarda yap\u0131lan de\u011fi\u015fiklikleri otomatik olarak alg\u0131lar ve sunucuyu yeniden ba\u015flat\u0131r. Geli\u015ftirme s\u00fcrecinde \u00e7ok kullan\u0131\u015fl\u0131d\u0131r.<\/p>\n<h4>Uygulamay\u0131 \u00c7al\u0131\u015ft\u0131rma<\/h4>\n<p>Terminalinizde <code>app.py<\/code> dosyas\u0131n\u0131n bulundu\u011fu dizine gidin ve a\u015fa\u011f\u0131daki komutu \u00e7al\u0131\u015ft\u0131r\u0131n:<\/p>\n<pre><code class=\"language-bash\">python app.py<\/code><\/pre>\n<p>Taray\u0131c\u0131n\u0131z\u0131 a\u00e7\u0131n ve <code>http:\/\/localhost:8080\/<\/code> adresine gidin. &#8220;Merhaba, D\u00fcnya!&#8221; mesaj\u0131n\u0131 g\u00f6rmelisiniz.<br \/>\n\u015eimdi <code>http:\/\/localhost:8080\/hello\/Ahmet<\/code> adresine gidin. &#8220;Merhaba Ahmet!&#8221; mesaj\u0131n\u0131 g\u00f6rmelisiniz.<br \/>\nTebrikler, ilk Bottle uygulaman\u0131z\u0131 ba\u015far\u0131yla \u00e7al\u0131\u015ft\u0131rd\u0131n\u0131z!<\/p>\n<h3>Temel Kavramlar: Bottle&#8217;\u0131n \u0130n\u015fa Ta\u015flar\u0131<\/h3>\n<p>Bottle&#8217;\u0131n g\u00fcc\u00fc, basit ama etkili temel kavramlar\u0131nda yatar. Bu b\u00f6l\u00fcmde, y\u00f6nlendirme, istek ve yan\u0131t nesneleri, \u015fablonlar ve statik dosyalar gibi temel yap\u0131 ta\u015flar\u0131n\u0131 ayr\u0131nt\u0131l\u0131 olarak inceleyece\u011fiz.<\/p>\n<h4>Y\u00f6nlendirme (Routing)<\/h4>\n<p>Y\u00f6nlendirme, gelen HTTP isteklerini belirli Python fonksiyonlar\u0131na e\u015fleme i\u015flemidir. Bottle&#8217;da <code>@route()<\/code> dekorat\u00f6r\u00fc ile y\u00f6nlendirme tan\u0131mlan\u0131r.<\/p>\n<h5>Basit Y\u00f6nlendirmeler<\/h5>\n<pre><code class=\"language-python\">from bottle import route, run\n\n@route('\/about')\ndef about():\n    return \"Bu bir 'Hakk\u0131m\u0131zda' sayfas\u0131d\u0131r.\"\n\n@route('\/contact')\ndef contact():\n    return \"\u0130leti\u015fim bilgilerimiz burada.\"\n\nrun(host='localhost', port=8080)<\/code><\/pre>\n<h5>Dinamik Y\u00f6nlendirmeler ve Parametreler<\/h5>\n<p>URL&#8217;den parametre almak i\u00e7in <code><param_name><\/code> s\u00f6zdizimini kullan\u0131r\u0131z.<\/p>\n<pre><code class=\"language-python\">@route('\/users\/<user_id>')\ndef show_user(user_id):\n    return f\"Kullan\u0131c\u0131 ID: {user_id}\"\n\n@route('\/posts\/<year:int>\/<month:int>\/<day:int>')\ndef show_post_by_date(year, month, day):\n    return f\"Y\u0131l: {year}, Ay: {month}, G\u00fcn: {day} tarihli g\u00f6nderi.\"<\/code><\/pre>\n<p>Yukar\u0131daki \u00f6rnekte:<br \/>\n*   <code><user_id><\/code>: <code>user_id<\/code> ad\u0131nda bir parametre al\u0131r. Varsay\u0131lan olarak, parametreler string olarak kabul edilir.<br \/>\n*   <code><year:int><\/code>, <code><month:int><\/code>, <code><day:int><\/code>: Bu, parametre t\u00fcr\u00fcn\u00fc belirtir. <code>int<\/code> (tam say\u0131), <code>float<\/code> (kayan noktal\u0131 say\u0131), <code>path<\/code> (e\u011fik \u00e7izgiler dahil t\u00fcm yolu al\u0131r) gibi yerle\u015fik t\u00fcrler veya \u00f6zel t\u00fcrler kullan\u0131labilir.<\/p>\n<h5>HTTP Metotlar\u0131<\/h5>\n<p>Bir rota, belirli HTTP metotlar\u0131na (GET, POST, PUT, DELETE vb.) yan\u0131t verecek \u015fekilde yap\u0131land\u0131r\u0131labilir.<\/p>\n<pre><code class=\"language-python\">from bottle import route, request, run\n\n@route('\/login', method='GET')\ndef login_form():\n    return '''\n        <form action=\"\/login\" method=\"post\">\n            Kullan\u0131c\u0131 Ad\u0131: <input name=\"username\" type=\"text\" \/>\n            \u015eifre: <input name=\"password\" type=\"password\" \/>\n            <input value=\"Giri\u015f Yap\" type=\"submit\" \/>\n        <\/form>\n    '''\n\n@route('\/login', method='POST')\ndef login_submit():\n    username = request.forms.get('username')\n    password = request.forms.get('password')\n    if username == 'admin' and password == 'password':\n        return \"<p>Giri\u015f ba\u015far\u0131l\u0131!<\/p>\"\n    else:\n        return \"<p>Kullan\u0131c\u0131 ad\u0131 veya \u015fifre yanl\u0131\u015f.<\/p>\"\n\nrun(host='localhost', port=8080)<\/code><\/pre>\n<p>Bu \u00f6rnekte, <code>\/login<\/code> rotas\u0131 hem GET (formu g\u00f6stermek i\u00e7in) hem de POST (form verilerini i\u015flemek i\u00e7in) metotlar\u0131n\u0131 destekler.<\/p>\n<h4>\u0130stek ve Yan\u0131t Nesneleri (Request and Response Objects)<\/h4>\n<p>Bottle, gelen HTTP iste\u011fine (<code>request<\/code>) ve g\u00f6nderilen HTTP yan\u0131t\u0131na (<code>response<\/code>) eri\u015fim sa\u011flayan global nesneler sunar.<\/p>\n<h5><code>request<\/code> Nesnesi<\/h5>\n<p><code>request<\/code> nesnesi, istemciden gelen t\u00fcm bilgileri i\u00e7erir:<\/p>\n<p>*   <code>request.query<\/code>: URL sorgu parametreleri (<code>?key=value<\/code>).<br \/>\n*   <code>request.forms<\/code>: POST isteklerinden gelen form verileri.<br \/>\n*   <code>request.params<\/code>: Hem sorgu hem de form parametrelerini birle\u015ftirir.<br \/>\n*   <code>request.headers<\/code>: \u0130stek ba\u015fl\u0131klar\u0131.<br \/>\n*   <code>request.cookies<\/code>: \u0130stemciden gelen \u00e7erezler.<br \/>\n*   <code>request.files<\/code>: Y\u00fcklenen dosyalar.<br \/>\n*   <code>request.json<\/code>: JSON format\u0131ndaki istek g\u00f6vdesi.<br \/>\n*   <code>request.url<\/code>, <code>request.path<\/code>, <code>request.method<\/code>: \u0130stek URL&#8217;si, yolu ve metodu.<\/p>\n<p>\u00d6rnek:<\/p>\n<pre><code class=\"language-python\">from bottle import route, request, run\n\n@route('\/search')\ndef search():\n    query = request.query.get('q', 'arama terimi belirtilmedi')\n    return f\"Arama sonu\u00e7lar\u0131: '{query}'\"\n\n@route('\/upload', method='POST')\ndef upload_file():\n    upload = request.files.get('upload')\n    if upload:\n        name, ext = os.path.splitext(upload.filename)\n        if ext not in ('.png', '.jpg', '.jpeg'):\n            return \"Sadece resim dosyalar\u0131na izin verilir.\"\n        save_path = f\"\/tmp\/{upload.filename}\" # G\u00fcvenli bir dizine kaydedin!\n        upload.save(save_path)\n        return f\"Dosya '{upload.filename}' ba\u015far\u0131yla y\u00fcklendi.\"\n    return \"Dosya y\u00fcklenemedi.\"\n\nrun(host='localhost', port=8080)<\/code><\/pre>\n<h5><code>response<\/code> Nesnesi<\/h5>\n<p><code>response<\/code> nesnesi, istemciye g\u00f6nderilecek yan\u0131t\u0131 yap\u0131land\u0131rmak i\u00e7in kullan\u0131l\u0131r:<\/p>\n<p>*   <code>response.status<\/code>: HTTP durum kodu (\u00f6rn. 200, 404, 500).<br \/>\n*   <code>response.headers<\/code>: Yan\u0131t ba\u015fl\u0131klar\u0131.<br \/>\n*   <code>response.set_cookie()<\/code>: \u0130stemciye \u00e7erez g\u00f6nderme.<br \/>\n*   <code>response.delete_cookie()<\/code>: \u0130stemciden \u00e7erez silme.<br \/>\n*   <code>response.redirect()<\/code>: Y\u00f6nlendirme yapma.<\/p>\n<p>\u00d6rnek:<\/p>\n<pre><code class=\"language-python\">from bottle import route, response, redirect, run\n\n@route('\/set_cookie')\ndef set_cookie():\n    response.set_cookie('my_cookie', 'some_value', max_age=3600)\n    return \"\u00c7erez ayarland\u0131.\"\n\n@route('\/get_cookie')\ndef get_cookie():\n    cookie_value = request.get_cookie('my_cookie')\n    return f\"\u00c7erez de\u011feri: {cookie_value}\" if cookie_value else \"\u00c7erez bulunamad\u0131.\"\n\n@route('\/go_to_home')\ndef go_home():\n    redirect('\/') # Ana sayfaya y\u00f6nlendir\n    return \"Y\u00f6nlendiriliyor...\" # Bu sat\u0131r asl\u0131nda \u00e7al\u0131\u015fmayacak\n\nrun(host='localhost', port=8080)<\/code><\/pre>\n<h4>\u015eablonlar (Templates)<\/h4>\n<p>Bottle, varsay\u0131lan olarak basit bir \u015fablon motoruyla gelir, ancak Jinja2 veya Mako gibi pop\u00fcler \u015fablon motorlar\u0131yla da kolayca entegre edilebilir.<\/p>\n<h5>Yerle\u015fik \u015eablon Motoru Kullan\u0131m\u0131<\/h5>\n<p><code>template()<\/code> fonksiyonu, bir \u015fablon dosyas\u0131n\u0131 veya \u015fablon dizesini i\u015flemek i\u00e7in kullan\u0131l\u0131r.<\/p>\n<p><code>views<\/code> ad\u0131nda bir klas\u00f6r olu\u015fturun ve i\u00e7ine <code>hello_page.tpl<\/code> ad\u0131nda bir dosya ekleyin:<\/p>\n<p><code>views\/hello_page.tpl<\/code>:<\/p>\n<pre><code class=\"language-html\"><!DOCTYPE html>\n<html>\n<head>\n    <title>Merhaba Sayfas\u0131<\/title>\n<\/head>\n<body>\n    \n    <p>Bu, Bottle ile olu\u015fturulmu\u015f bir \u015fablon \u00f6rne\u011fidir.<\/p>\n<\/body>\n<\/html><\/code><\/pre>\n<p><code>app.py<\/code>:<\/p>\n<pre><code class=\"language-python\">from bottle import route, run, template\n\n@route('\/greet\/<name>')\ndef greet(name):\n    return template('hello_page', name=name)\n\nrun(host='localhost', port=8080)<\/code><\/pre>\n<p><code>template('hello_page', name=name)<\/code> ifadesi, <code>views<\/code> klas\u00f6r\u00fcndeki <code>hello_page.tpl<\/code> dosyas\u0131n\u0131 arar ve <code>name<\/code> de\u011fi\u015fkenini \u015fablona aktar\u0131r.<\/p>\n<h5>Di\u011fer \u015eablon Motorlar\u0131yla Entegrasyon (\u00d6rn: Jinja2)<\/h5>\n<p>\u00d6nce Jinja2&#8217;yi kurun: <code>pip install jinja2<\/code><\/p>\n<p><code>app.py<\/code>:<\/p>\n<pre><code class=\"language-python\">from bottle import route, run, Jinja2Template\nfrom jinja2 import Environment, FileSystemLoader\n\n<h2>Jinja2 ortam\u0131n\u0131 yap\u0131land\u0131r<\/h2>\njinja2_env = Environment(loader=FileSystemLoader('.\/views'))\nJinja2Template.defaults = {'env': jinja2_env}\n\n@route('\/jinja_greet\/<name>')\ndef jinja_greet(name):\n    return Jinja2Template('hello_page.html').render(name=name)\n\nrun(host='localhost', port=8080)<\/code><\/pre>\n<p><code>views\/hello_page.html<\/code>:<\/p>\n<pre><code class=\"language-html\"><!DOCTYPE html>\n<html>\n<head>\n    <title>Jinja2 Merhaba Sayfas\u0131<\/title>\n<\/head>\n<body>\n    \n    <p>Bu, Jinja2 ile olu\u015fturulmu\u015f bir \u015fablon \u00f6rne\u011fidir.<\/p>\n<\/body>\n<\/html><\/code><\/pre>\n<h4>Statik Dosyalar (Static Files)<\/h4>\n<p>CSS, JavaScript, resimler gibi statik dosyalar\u0131 sunmak i\u00e7in <code>static_file()<\/code> fonksiyonu kullan\u0131l\u0131r.<\/p>\n<pre><code class=\"language-python\">from bottle import route, run, static_file\nimport os\n\n<h2>Statik dosyalar\u0131n\u0131z\u0131n bulundu\u011fu dizin<\/h2>\nSTATIC_ROOT = '.\/static'\n\n@route('\/static\/<filepath:path>')\ndef serve_static(filepath):\n    return static_file(filepath, root=STATIC_ROOT)\n\n@route('\/')\ndef index():\n    return '''\n        <!DOCTYPE html>\n        <html>\n        <head>\n            <title>Statik Dosya \u00d6rne\u011fi<\/title>\n            <link rel=\"stylesheet\" href=\"\/static\/style.css\">\n        <\/head>\n        <body>\n            \n            <img decoding=\"async\" src=\"\/static\/logo.png\" alt=\"Logo\">\n            <script src=\"\/static\/script.js\"><\/script>\n        <\/body>\n        <\/html>\n    '''\n\nrun(host='localhost', port=8080)<\/code><\/pre>\n<p><code>static<\/code> ad\u0131nda bir klas\u00f6r olu\u015fturun ve i\u00e7ine <code>style.css<\/code>, <code>script.js<\/code> ve <code>logo.png<\/code> gibi dosyalar koyun.<\/p>\n<p><code>.\/static\/style.css<\/code>:<\/p>\n<pre><code class=\"language-css\">body {\n    font-family: Arial, sans-serif;\n    background-color: #f0f0f0;\n    color: #333;\n}\nh1 {\n    color: #0056b3;\n}<\/code><\/pre>\n<p><code>.\/static\/script.js<\/code>:<\/p>\n<pre><code class=\"language-javascript\">document.addEventListener('DOMContentLoaded', function() {\n    console.log('JavaScript dosyas\u0131 y\u00fcklendi!');\n});<\/code><\/pre>\n<p>Bu yap\u0131land\u0131rma, <code>\/static\/<\/code> ile ba\u015flayan t\u00fcm istekleri <code>STATIC_ROOT<\/code> dizinindeki dosyalara y\u00f6nlendirir.<\/p>\n<h3>Veritaban\u0131 Entegrasyonu<\/h3>\n<p>Bottle, herhangi bir veritaban\u0131 soyutlama katman\u0131 (ORM) veya veritaban\u0131 s\u00fcr\u00fcc\u00fcs\u00fc ile gelmez. Bu, Bottle&#8217;\u0131n minimalist felsefesinin bir par\u00e7as\u0131d\u0131r. Geli\u015ftiriciler, projelerinin ihtiya\u00e7lar\u0131na en uygun veritaban\u0131 k\u00fct\u00fcphanesini se\u00e7mekte \u00f6zg\u00fcrd\u00fcr. SQLite, PostgreSQL, MySQL gibi ili\u015fkisel veritabanlar\u0131 veya MongoDB, Redis gibi NoSQL veritabanlar\u0131 ile \u00e7al\u0131\u015fabilirsiniz.<\/p>\n<h4>SQLite ile Basit Bir \u00d6rnek<\/h4>\n<p>SQLite, Python ile varsay\u0131lan olarak gelen hafif, dosya tabanl\u0131 bir veritaban\u0131d\u0131r ve k\u00fc\u00e7\u00fck projeler i\u00e7in harikad\u0131r.<\/p>\n<pre><code class=\"language-python\">from bottle import route, run, template, request\nimport sqlite3\n\nDB_PATH = 'mydatabase.db'\n\ndef get_db_connection():\n    conn = sqlite3.connect(DB_PATH)\n    conn.row_factory = sqlite3.Row # Kolon isimleriyle verilere eri\u015fim sa\u011flar\n    return conn\n\n<h2>Veritaban\u0131 tablosunu olu\u015ftur<\/h2>\ndef init_db():\n    conn = get_db_connection()\n    cursor = conn.cursor()\n    cursor.execute('''\n        CREATE TABLE IF NOT EXISTS todos (\n            id INTEGER PRIMARY KEY AUTOINCREMENT,\n            task TEXT NOT NULL,\n            status TEXT NOT NULL DEFAULT 'a\u00e7\u0131k'\n        )\n    ''')\n    conn.commit()\n    conn.close()\n\n<h2>Uygulama ba\u015flamadan \u00f6nce veritaban\u0131n\u0131 ba\u015flat<\/h2>\ninit_db()\n\n@route('\/todos')\ndef todo_list():\n    conn = get_db_connection()\n    cursor = conn.cursor()\n    cursor.execute(\"SELECT id, task, status FROM todos\")\n    rows = cursor.fetchall()\n    conn.close()\n    return template('todo_list', todos=rows)\n\n@route('\/new_todo', method=['GET', 'POST'])\ndef new_todo():\n    if request.method == 'POST':\n        task = request.forms.get('task')\n        if task:\n            conn = get_db_connection()\n            cursor = conn.cursor()\n            cursor.execute(\"INSERT INTO todos (task) VALUES (?)\", (task,))\n            conn.commit()\n            conn.close()\n            return \"G\u00f6rev eklendi!\"\n        return \"G\u00f6rev bo\u015f olamaz.\"\n    else:\n        return '''\n            <form action=\"\/new_todo\" method=\"post\">\n                G\u00f6rev: <input name=\"task\" type=\"text\" \/>\n                <input value=\"Ekle\" type=\"submit\" \/>\n            <\/form>\n        '''\n\nrun(host='localhost', port=8080)<\/code><\/pre>\n<p><code>views\/todo_list.tpl<\/code>:<\/p>\n<pre><code class=\"language-html\"><!DOCTYPE html>\n<html>\n<head>\n    <title>Yap\u0131lacaklar Listesi<\/title>\n<\/head>\n<body>\n    \n    <ul>\n        % for todo in todos:\n            <li>{{ todo['task'] }} (Durum: {{ todo['status'] }})<\/li>\n        % end\n    <\/ul>\n    <p><a href=\"\/new_todo\">Yeni G\u00f6rev Ekle<\/a><\/p>\n<\/body>\n<\/html><\/code><\/pre>\n<p>Bu \u00f6rnek, bir SQLite veritaban\u0131 ile basit bir &#8220;yap\u0131lacaklar&#8221; listesi uygulamas\u0131n\u0131 g\u00f6sterir. <code>get_db_connection()<\/code> fonksiyonu, her istekte yeni bir veritaban\u0131 ba\u011flant\u0131s\u0131 olu\u015fturmak i\u00e7in kullan\u0131l\u0131r. B\u00fcy\u00fck uygulamalarda ba\u011flant\u0131 havuzlar\u0131 veya ORM&#8217;ler (SQLAlchemy, Peewee) kullanmak daha iyi bir yakla\u015f\u0131md\u0131r.<\/p>\n<h3>Form \u0130\u015fleme ve Dosya Y\u00fckleme<\/h3>\n<p>Web uygulamalar\u0131n\u0131n \u00f6nemli bir par\u00e7as\u0131, kullan\u0131c\u0131dan veri almak ve bu verileri i\u015flemektir. Bottle, form verilerini ve dosya y\u00fcklemelerini kolayca y\u00f6netmenizi sa\u011flar.<\/p>\n<h4>Form Verilerini \u0130\u015fleme<\/h4>\n<p>GET istekleri i\u00e7in <code>request.query<\/code>, POST istekleri i\u00e7in <code>request.forms<\/code> kullan\u0131l\u0131r.<\/p>\n<pre><code class=\"language-python\">from bottle import route, request, run\n\n@route('\/register', method=['GET', 'POST'])\ndef register():\n    if request.method == 'POST':\n        username = request.forms.get('username')\n        email = request.forms.get('email')\n        password = request.forms.get('password')\n\n        if not username or not email or not password:\n            return \"L\u00fctfen t\u00fcm alanlar\u0131 doldurun.\"\n\n        # Burada veritaban\u0131na kaydetme veya ba\u015fka i\u015flemler yap\u0131labilir\n        return f\"Kullan\u0131c\u0131 '{username}' ba\u015far\u0131yla kaydedildi! E-posta: {email}\"\n    else:\n        return '''\n            <form action=\"\/register\" method=\"post\">\n                Kullan\u0131c\u0131 Ad\u0131: <input name=\"username\" type=\"text\" \/><br>\n                E-posta: <input name=\"email\" type=\"email\" \/><br>\n                \u015eifre: <input name=\"password\" type=\"password\" \/><br>\n                <input value=\"Kay\u0131t Ol\" type=\"submit\" \/>\n            <\/form>\n        '''\n\nrun(host='localhost', port=8080)<\/code><\/pre>\n<h4>Dosya Y\u00fckleme<\/h4>\n<p><code>request.files<\/code> nesnesi, y\u00fcklenen dosyalara eri\u015fim sa\u011flar.<\/p>\n<pre><code class=\"language-python\">from bottle import route, request, run\nimport os\n\nUPLOAD_DIR = '.\/uploads'\nos.makedirs(UPLOAD_DIR, exist_ok=True) # Y\u00fckleme dizinini olu\u015ftur\n\n@route('\/upload_file', method=['GET', 'POST'])\ndef upload_view():\n    if request.method == 'POST':\n        upload = request.files.get('my_file')\n        if upload:\n            name, ext = os.path.splitext(upload.filename)\n            if ext not in ('.png', '.jpg', '.jpeg', '.gif', '.pdf'):\n                return \"Sadece resim ve PDF dosyalar\u0131na izin verilir.\"\n            \n            # G\u00fcvenli bir dosya ad\u0131 olu\u015fturmak \u00f6nemlidir\n            # \u00d6rne\u011fin, dosya ad\u0131n\u0131 hashleyebilir veya UUID kullanabilirsiniz.\n            # \u015eimdilik basit\u00e7e kaydedelim:\n            save_path = os.path.join(UPLOAD_DIR, upload.filename)\n            \n            try:\n                upload.save(save_path)\n                return f\"Dosya '{upload.filename}' ba\u015far\u0131yla y\u00fcklendi ve kaydedildi: {save_path}\"\n            except Exception as e:\n                return f\"Dosya y\u00fcklenirken bir hata olu\u015ftu: {e}\"\n        return \"Dosya y\u00fcklenemedi. L\u00fctfen bir dosya se\u00e7in.\"\n    else:\n        return '''\n            <form action=\"\/upload_file\" method=\"post\" enctype=\"multipart\/form-data\">\n                Dosya Se\u00e7: <input type=\"file\" name=\"my_file\" \/><br>\n                <input value=\"Y\u00fckle\" type=\"submit\" \/>\n            <\/form>\n        '''\n\nrun(host='localhost', port=8080)<\/code><\/pre>\n<p><strong>G\u00fcvenlik Notu:<\/strong> Dosya y\u00fckleme i\u015flemleri s\u0131ras\u0131nda her zaman dikkatli olunmal\u0131d\u0131r. Y\u00fcklenen dosyalar\u0131n t\u00fcr\u00fcn\u00fc, boyutunu do\u011frulamak ve sunucuda g\u00fcvenli bir \u015fekilde saklamak (\u00f6rne\u011fin, rastgele olu\u015fturulmu\u015f dosya adlar\u0131 kullanarak) k\u00f6t\u00fc niyetli sald\u0131r\u0131lar\u0131 \u00f6nlemek i\u00e7in hayati \u00f6neme sahiptir.<\/p>\n<h3>Hata Y\u00f6netimi<\/h3>\n<p>Bottle, uygulaman\u0131zda meydana gelen hatalar\u0131 yakalamak ve \u00f6zel hata sayfalar\u0131 sunmak i\u00e7in <code>@error()<\/code> dekorat\u00f6r\u00fcn\u00fc kullanman\u0131za olanak tan\u0131r.<\/p>\n<pre><code class=\"language-python\">from bottle import route, run, error, template\n\n@error(404)\ndef error404(error):\n    return template('error_page', code=error.status_code, message=\"Arad\u0131\u011f\u0131n\u0131z sayfa bulunamad\u0131.\")\n\n@error(500)\ndef error500(error):\n    return template('error_page', code=error.status_code, message=\"Sunucuda beklenmeyen bir hata olu\u015ftu.\")\n\n@route('\/bad_route')\ndef bad_route():\n    # Bilerek bir hata olu\u015ftural\u0131m\n    raise ValueError(\"Bu bir test hatas\u0131d\u0131r!\")\n\n@route('\/')\ndef index():\n    return \"Ana sayfa.\"\n\nrun(host='localhost', port=8080)<\/code><\/pre>\n<p><code>views\/error_page.tpl<\/code>:<\/p>\n<pre><code class=\"language-html\"><!DOCTYPE html>\n<html>\n<head>\n    <title>Hata {{code}}<\/title>\n<\/head>\n<body>\n    \n    <p>{{message}}<\/p>\n    <p><a href=\"\/\">Ana Sayfaya D\u00f6n<\/a><\/p>\n<\/body>\n<\/html><\/code><\/pre>\n<p>Bu \u00f6rnekte, bir 404 (Sayfa Bulunamad\u0131) veya 500 (Dahili Sunucu Hatas\u0131) hatas\u0131 meydana geldi\u011finde, <code>error_page.tpl<\/code> \u015fablonu kullan\u0131larak \u00f6zelle\u015ftirilmi\u015f bir hata sayfas\u0131 g\u00f6sterilir. <code>error<\/code> nesnesi, hata kodu ve mesaj\u0131 gibi bilgilere eri\u015fim sa\u011flar.<\/p>\n<h3>Middleware ve Eklentiler (Plugins)<\/h3>\n<p>Bottle&#8217;\u0131n esnek mimarisi, HTTP istek\/yan\u0131t d\u00f6ng\u00fcs\u00fcne ek i\u015flevsellik eklemek i\u00e7in middleware veya eklentiler kullanman\u0131za olanak tan\u0131r.<\/p>\n<h4>Eklentiler<\/h4>\n<p>Eklentiler, Bottle uygulaman\u0131z\u0131n davran\u0131\u015f\u0131n\u0131 de\u011fi\u015ftirmek veya geni\u015fletmek i\u00e7in g\u00fc\u00e7l\u00fc bir yoldur. Bottle, veritaban\u0131 ba\u011flant\u0131 y\u00f6netimi gibi yayg\u0131n g\u00f6revler i\u00e7in yerle\u015fik eklentilere sahiptir ve kendi \u00f6zel eklentilerinizi de yazabilirsiniz.<\/p>\n<h5>Yerle\u015fik Eklenti \u00d6rne\u011fi: SQLite Eklentisi<\/h5>\n<p>Bottle&#8217;\u0131n <code>sqlite<\/code> eklentisi, her istek i\u00e7in bir veritaban\u0131 ba\u011flant\u0131s\u0131 a\u00e7\u0131p kapatma y\u00fck\u00fcn\u00fc ortadan kald\u0131r\u0131r.<\/p>\n<pre><code class=\"language-python\">from bottle import route, run, template\nfrom bottle_sqlite import SQLitePlugin\nimport sqlite3\n\n<h2>Eklentiyi uygulaman\u0131za kurun<\/h2>\napp = Bottle()\napp.install(SQLitePlugin(dbfile='my_plugin_database.db'))\n\n@app.route('\/plugin_todos')\ndef plugin_todo_list(db): # db parametresi eklenti taraf\u0131ndan sa\u011flan\u0131r\n    cursor = db.cursor()\n    cursor.execute(\"CREATE TABLE IF NOT EXISTS todos (id INTEGER PRIMARY KEY AUTOINCREMENT, task TEXT NOT NULL)\")\n    cursor.execute(\"SELECT id, task FROM todos\")\n    rows = cursor.fetchall()\n    return template('plugin_todo_list', todos=rows)\n\n@app.route('\/add_plugin_todo', method='POST')\ndef add_plugin_todo(db):\n    task = request.forms.get('task')\n    if task:\n        db.execute(\"INSERT INTO todos (task) VALUES (?)\", (task,))\n        return \"G\u00f6rev eklendi (plugin ile)!\"\n    return \"G\u00f6rev bo\u015f olamaz.\"\n\nrun(app, host='localhost', port=8080)<\/code><\/pre>\n<p><code>views\/plugin_todo_list.tpl<\/code>:<\/p>\n<pre><code class=\"language-html\"><!DOCTYPE html>\n<html>\n<head>\n    <title>Eklenti ile Yap\u0131lacaklar<\/title>\n<\/head>\n<body>\n    \n    <ul>\n        % for todo in todos:\n            <li>{{ todo[1] }}<\/li>\n        % end\n    <\/ul>\n    <form action=\"\/add_plugin_todo\" method=\"post\">\n        Yeni G\u00f6rev: <input name=\"task\" type=\"text\" \/>\n        <input value=\"Ekle\" type=\"submit\" \/>\n    <\/form>\n<\/body>\n<\/html><\/code><\/pre>\n<p>Bu \u00f6rnekte, <code>SQLitePlugin<\/code>&#8216;i kurduktan sonra, rota fonksiyonlar\u0131na <code>db<\/code> ad\u0131nda bir parametre ekleyerek veritaban\u0131 ba\u011flant\u0131s\u0131na eri\u015febiliriz. Eklenti, ba\u011flant\u0131lar\u0131 otomatik olarak y\u00f6netir.<\/p>\n<h3>Da\u011f\u0131t\u0131m (Deployment)<\/h3>\n<p>Geli\u015ftirme sunucusu (<code>bottle.run()<\/code>) sadece geli\u015ftirme ama\u00e7l\u0131d\u0131r ve \u00fcretim ortam\u0131nda kullan\u0131lmamal\u0131d\u0131r. \u00dcretim ortam\u0131nda Bottle uygulamalar\u0131n\u0131 da\u011f\u0131tmak i\u00e7in WSGI uyumlu bir sunucuya ihtiyac\u0131n\u0131z vard\u0131r.<\/p>\n<h4>Pop\u00fcler WSGI Sunucular\u0131<\/h4>\n<p>*   <strong>Gunicorn:<\/strong> Python i\u00e7in sa\u011flam ve h\u0131zl\u0131 bir WSGI HTTP sunucusu.<br \/>\n*   <strong>uWSGI:<\/strong> \u00c7ok y\u00f6nl\u00fc ve y\u00fcksek performansl\u0131 bir uygulama sunucusu.<br \/>\n*   <strong>CherryPy:<\/strong> Bottle&#8217;\u0131n kendisi de CherryPy sunucusuyla \u00e7al\u0131\u015fabilir.<br \/>\n*   <strong>Waitress:<\/strong> Saf Python&#8217;da yaz\u0131lm\u0131\u015f, kullan\u0131m\u0131 kolay bir WSGI sunucusu.<\/p>\n<h5>Gunicorn ile Da\u011f\u0131t\u0131m \u00d6rne\u011fi<\/h5>\n<p>1.  <strong>Gunicorn&#8217;\u0131 Kurun:<\/strong> <code>pip install gunicorn<\/code><br \/>\n2.  <strong>Uygulama Dosyas\u0131 (<code>app.py<\/code>):<\/strong><\/p>\n<pre><code class=\"language-python\">from bottle import Bottle, route, run\n\n    app = Bottle()\n\n    @app.route('\/')\n    def index():\n        return \"Merhaba, Gunicorn!\"\n\n    # Geli\u015ftirme sunucusunu kald\u0131rmay\u0131 unutmay\u0131n veya sadece test i\u00e7in kullan\u0131n\n    # if __name__ == '__main__':\n    #     run(app, host='localhost', port=8080, debug=True, reloader=True)<\/code><\/pre>\n<p>3.  <strong>Gunicorn ile \u00c7al\u0131\u015ft\u0131r\u0131n:<\/strong> Terminalde <code>app.py<\/code> dosyas\u0131n\u0131n bulundu\u011fu dizinde a\u015fa\u011f\u0131daki komutu \u00e7al\u0131\u015ft\u0131r\u0131n:<\/p>\n<pre><code class=\"language-bash\">gunicorn -w 4 app:app<\/code><\/pre>\n<p>    *   <code>-w 4<\/code>: 4 adet worker (i\u015f\u00e7i) s\u00fcreci ba\u015flat\u0131r.<br \/>\n    *   <code>app:app<\/code>: <code>app.py<\/code> dosyas\u0131ndaki <code>app<\/code> adl\u0131 Bottle uygulamas\u0131n\u0131 belirtir.<\/p>\n<p>Art\u0131k uygulaman\u0131z <code>http:\/\/localhost:8000\/<\/code> adresinde (Gunicorn&#8217;\u0131n varsay\u0131lan portu) Gunicorn taraf\u0131ndan sunulacakt\u0131r. Ger\u00e7ek d\u00fcnya da\u011f\u0131t\u0131mlar\u0131nda, Gunicorn&#8217;\u0131n \u00f6n\u00fcne Nginx veya Apache gibi bir ters proxy sunucu eklemek yayg\u0131n bir uygulamad\u0131r.<\/p>\n<h3>En \u0130yi Uygulamalar ve \u0130leri Konular<\/h3>\n<p>Bottle&#8217;\u0131n basitli\u011fi, geli\u015ftiricilere b\u00fcy\u00fck bir esneklik sunar, ancak bu esneklikle birlikte baz\u0131 en iyi uygulamalar\u0131 takip etmek, uygulaman\u0131z\u0131n daha s\u00fcrd\u00fcr\u00fclebilir ve \u00f6l\u00e7eklenebilir olmas\u0131n\u0131 sa\u011flar.<\/p>\n<h4>Proje Yap\u0131s\u0131<\/h4>\n<p>K\u00fc\u00e7\u00fck uygulamalar i\u00e7in tek bir <code>app.py<\/code> dosyas\u0131 yeterli olabilir, ancak uygulaman\u0131z b\u00fcy\u00fcd\u00fck\u00e7e daha mod\u00fcler bir yap\u0131ya ihtiyac\u0131n\u0131z olacakt\u0131r.<\/p>\n<pre><code class=\"language-\">my_bottle_app\/\n\u251c\u2500\u2500 app.py\n\u251c\u2500\u2500 views\/\n\u2502   \u251c\u2500\u2500 index.tpl\n\u2502   \u2514\u2500\u2500 error.tpl\n\u251c\u2500\u2500 static\/\n\u2502   \u251c\u2500\u2500 css\/\n\u2502   \u2502   \u2514\u2500\u2500 style.css\n\u2502   \u2514\u2500\u2500 js\/\n\u2502       \u2514\u2500\u2500 script.js\n\u251c\u2500\u2500 models.py\n\u251c\u2500\u2500 controllers.py\n\u251c\u2500\u2500 config.py\n\u2514\u2500\u2500 requirements.txt<\/code><\/pre>\n<p>*   <code>app.py<\/code>: Ana uygulama tan\u0131m\u0131 ve ana rotalar.<br \/>\n*   <code>views\/<\/code>: \u015eablon dosyalar\u0131.<br \/>\n*   <code>static\/<\/code>: Statik dosyalar (CSS, JS, resimler).<br \/>\n*   <code>models.py<\/code>: Veritaban\u0131 modelleri (ORM kullan\u0131l\u0131yorsa).<br \/>\n*   <code>controllers.py<\/code>: \u0130\u015f mant\u0131\u011f\u0131 ve rota fonksiyonlar\u0131.<br \/>\n*   <code>config.py<\/code>: Uygulama yap\u0131land\u0131rmas\u0131.<\/p>\n<h4>Mod\u00fcler Uygulamalar (<code>Bottle.mount()<\/code>)<\/h4>\n<p>Bottle, daha b\u00fcy\u00fck uygulamalar\u0131 y\u00f6netmek i\u00e7in alt uygulamalar\u0131 (sub-applications) veya mod\u00fclleri birle\u015ftirmenize olanak tan\u0131r.<\/p>\n<pre><code class=\"language-python\"># admin_app.py\nfrom bottle import Bottle, route\n\nadmin_app = Bottle()\n\n@admin_app.route('\/')\ndef admin_home():\n    return \"Admin Paneli Ana Sayfas\u0131\"\n\n@admin_app.route('\/users')\ndef admin_users():\n    return \"Admin Kullan\u0131c\u0131 Y\u00f6netimi\"\n\n<h2>main_app.py<\/h2>\nfrom bottle import Bottle, route\nfrom admin_app import admin_app # admin_app'i i\u00e7e aktar\u0131n\n\nmain_app = Bottle()\n\n@main_app.route('\/')\ndef home():\n    return \"Ana Uygulama Ana Sayfas\u0131\"\n\n<h2>'\/admin' yolu alt\u0131ndaki t\u00fcm istekleri admin_app'e y\u00f6nlendir<\/h2>\nmain_app.mount('\/admin', admin_app)\n\nif __name__ == '__main__':\n    main_app.run(host='localhost', port=8080)<\/code><\/pre>\n<p>Bu \u00f6rnekte, <code>admin_app<\/code> ad\u0131nda ayr\u0131 bir Bottle uygulamas\u0131 tan\u0131mlan\u0131r ve <code>main_app<\/code> i\u00e7ine <code>\/admin<\/code> \u00f6nekiyle monte edilir. Bu, uygulaman\u0131z\u0131 daha d\u00fczenli tutman\u0131za yard\u0131mc\u0131 olur.<\/p>\n<h4>G\u00fcvenlik<\/h4>\n<p>Bottle, g\u00fcvenlik a\u00e7\u0131klar\u0131n\u0131 otomatik olarak kapatmaz, ancak baz\u0131 temel \u00f6nlemleri uygulaman\u0131z gerekir:<\/p>\n<p>*   <strong>XSS (Cross-Site Scripting):<\/strong> \u015eablon motorunuzun otomatik ka\u00e7\u0131\u015f (auto-escaping) \u00f6zelli\u011fini kulland\u0131\u011f\u0131ndan emin olun. Bottle&#8217;\u0131n yerle\u015fik \u015fablon motoru ve Jinja2 gibi pop\u00fcler motorlar bunu varsay\u0131lan olarak yapar.<br \/>\n*   <strong>CSRF (Cross-Site Request Forgery):<\/strong> POST formlar\u0131 i\u00e7in CSRF jetonlar\u0131 kullan\u0131n. Bottle&#8217;\u0131n yerle\u015fik bir \u00e7\u00f6z\u00fcm\u00fc yoktur, ancak harici k\u00fct\u00fcphaneler (\u00f6rne\u011fin, <code>bottle-csrf<\/code>) entegre edilebilir.<br \/>\n*   <strong>SQL Enjeksiyonu:<\/strong> Veritaban\u0131 sorgular\u0131nda parametreli sorgular\u0131 (prepared statements) kullan\u0131n. Yukar\u0131daki SQLite \u00f6rne\u011finde <code>?<\/code> kullanarak bunu zaten yapt\u0131k. Asla kullan\u0131c\u0131 girdisini do\u011frudan SQL sorgular\u0131na eklemeyin.<br \/>\n*   <strong>Kimlik Do\u011frulama ve Yetkilendirme:<\/strong> Kendi kimlik do\u011frulama sisteminizi uygulayabilir veya <code>bottle-auth<\/code> gibi k\u00fct\u00fcphaneleri kullanabilirsiniz.<br \/>\n*   <strong>Oturum Y\u00f6netimi:<\/strong> Bottle&#8217;\u0131n yerle\u015fik bir oturum y\u00f6netimi yoktur. <code>bottle-session<\/code> gibi eklentiler veya Redis gibi harici bir oturum deposu kullanabilirsiniz.<\/p>\n<h4>Test Etme<\/h4>\n<p>Uygulaman\u0131z\u0131n do\u011fru \u00e7al\u0131\u015ft\u0131\u011f\u0131ndan emin olmak i\u00e7in testler yazmak \u00f6nemlidir. <code>unittest<\/code> veya <code>pytest<\/code> gibi Python test \u00e7er\u00e7evelerini kullanabilirsiniz. Bottle uygulamalar\u0131n\u0131 test etmek i\u00e7in HTTP isteklerini sim\u00fcle edebilirsiniz.<\/p>\n<pre><code class=\"language-python\">from bottle import Bottle\nimport unittest\n\n<h2>Test edilecek uygulama<\/h2>\napp = Bottle()\n\n@app.route('\/')\ndef index():\n    return \"Test Ana Sayfa\"\n\n@app.route('\/hello\/<name>')\ndef hello(name):\n    return f\"Merhaba, {name}!\"\n\nclass TestMyApp(unittest.TestCase):\n    def test_index_route(self):\n        # Uygulamay\u0131 test modunda \u00e7al\u0131\u015ft\u0131r\u0131n\n        response = app.get('\/')\n        self.assertEqual(response.status_code, 200)\n        self.assertEqual(response.text, \"Test Ana Sayfa\")\n\n    def test_hello_route(self):\n        response = app.get('\/hello\/World')\n        self.assertEqual(response.status_code, 200)\n        self.assertEqual(response.text, \"Merhaba, World!\")\n\n    def test_404_route(self):\n        response = app.get('\/nonexistent')\n        self.assertEqual(response.status_code, 404)\n\nif __name__ == '__main__':\n    unittest.main()<\/code><\/pre>\n<p>Bu, Bottle uygulaman\u0131z\u0131 test etmek i\u00e7in temel bir yakla\u015f\u0131md\u0131r. Daha karma\u015f\u0131k testler i\u00e7in <code>WebTest<\/code> gibi k\u00fct\u00fcphaneler kullan\u0131labilir.<\/p>\n<h3>Sonu\u00e7<\/h3>\n<p>Bottle, Python web geli\u015ftirme d\u00fcnyas\u0131nda minimalist, ancak \u015fa\u015f\u0131rt\u0131c\u0131 derecede g\u00fc\u00e7l\u00fc bir ara\u00e7t\u0131r. Tek dosya yap\u0131s\u0131, ba\u011f\u0131ml\u0131l\u0131ks\u0131z do\u011fas\u0131 ve \u00f6\u011frenme kolayl\u0131\u011f\u0131, onu h\u0131zl\u0131 prototipleme, mikroservisler ve k\u00fc\u00e7\u00fck\/orta \u00f6l\u00e7ekli web uygulamalar\u0131 i\u00e7in m\u00fckemmel bir se\u00e7im haline getirir. Bottle, &#8220;az daha \u00e7oktur&#8221; felsefesini benimseyerek, geli\u015ftiricilere \u00e7ekirdek i\u015flevsellik sunar ve geri kalan\u0131n\u0131 kendi ihtiya\u00e7lar\u0131na g\u00f6re \u015fekillendirme \u00f6zg\u00fcrl\u00fc\u011f\u00fc verir.<\/p>\n<p>Bu makalede, Bottle&#8217;\u0131n kurulumundan ba\u015flayarak, y\u00f6nlendirme, istek\/yan\u0131t y\u00f6netimi, \u015fablonlar, statik dosyalar, veritaban\u0131 entegrasyonu, form i\u015fleme, hata y\u00f6netimi, eklentiler ve da\u011f\u0131t\u0131m gibi temel ve ileri d\u00fczey konular\u0131 ele ald\u0131k. Bottle&#8217;\u0131n nas\u0131l \u00e7al\u0131\u015ft\u0131\u011f\u0131n\u0131 ve web uygulamalar\u0131n\u0131z\u0131 geli\u015ftirmek i\u00e7in onu nas\u0131l kullanabilece\u011finizi art\u0131k daha iyi anlam\u0131\u015f olmal\u0131s\u0131n\u0131z.<\/p>\n<p>Bottle&#8217;\u0131 se\u00e7mek, projeniz \u00fczerinde daha fazla kontrol sahibi olmak ve gereksiz karma\u015f\u0131kl\u0131ktan ka\u00e7\u0131nmak anlam\u0131na gelir. \u0130htiya\u00e7lar\u0131n\u0131z basitse ve projenizi s\u0131f\u0131rdan in\u015fa etmenin keyfini \u00e7\u0131karmak istiyorsan\u0131z, Bottle sizin i\u00e7in do\u011fru \u00e7er\u00e7eve olabilir. Kendi web uygulamalar\u0131n\u0131z\u0131 Bottle ile geli\u015ftirmeye ba\u015flamaktan \u00e7ekinmeyin!<\/body><\/p>\n","protected":false},"excerpt":{"rendered":"Bottle Mikro \u00c7er\u00e7evesini Kullanarak Python Web Uygulamalar\u0131 Geli\u015ftirme Rehberi\nPython ekosistemi, web geli\u015ftirme i\u00e7in zengin bir ara\u00e7 yelpazes","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"csco_page_header_type":"","csco_page_load_nextpost":"","csco_page_subscribe_form":"","csco_page_contact_form":"","footnotes":""},"categories":[1403],"tags":[],"class_list":{"0":"post-34078","1":"post","2":"type-post","3":"status-publish","4":"format-standard","6":"category-python","7":"cs-entry","8":"cs-video-wrap"},"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v20.5 (Yoast SEO v25.3.1) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Bottle Mikro \u00c7er\u00e7evesini Kullanarak Python Web Uygulamalar\u0131 Geli\u015ftirme Rehberi - Kodlar\u0131n Gizemli D\u00fcnyas\u0131<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/fatihsoysal.com\/blog\/bottle-mikro-cercevesini-kullanarak-python-web-uygulamalari-gelistirme-rehberi\/\" \/>\n<meta property=\"og:locale\" content=\"tr_TR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Bottle Mikro \u00c7er\u00e7evesini Kullanarak Python Web Uygulamalar\u0131 Geli\u015ftirme Rehberi\" \/>\n<meta property=\"og:description\" content=\"Bottle Mikro \u00c7er\u00e7evesini Kullanarak Python Web Uygulamalar\u0131 Geli\u015ftirme Rehberi Python ekosistemi, web geli\u015ftirme i\u00e7in zengin bir ara\u00e7 yelpazes\" \/>\n<meta property=\"og:url\" content=\"https:\/\/fatihsoysal.com\/blog\/bottle-mikro-cercevesini-kullanarak-python-web-uygulamalari-gelistirme-rehberi\/\" \/>\n<meta property=\"og:site_name\" content=\"Kodlar\u0131n Gizemli D\u00fcnyas\u0131\" \/>\n<meta property=\"article:published_time\" content=\"2025-11-10T19:40:59+00:00\" \/>\n<meta name=\"author\" content=\"Fatih Soysal\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Yazan:\" \/>\n\t<meta name=\"twitter:data1\" content=\"Fatih Soysal\" \/>\n\t<meta name=\"twitter:label2\" content=\"Tahmini okuma s\u00fcresi\" \/>\n\t<meta name=\"twitter:data2\" content=\"21 dakika\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/bottle-mikro-cercevesini-kullanarak-python-web-uygulamalari-gelistirme-rehberi\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/bottle-mikro-cercevesini-kullanarak-python-web-uygulamalari-gelistirme-rehberi\/\"},\"author\":{\"name\":\"Fatih Soysal\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\"},\"headline\":\"Bottle Mikro \u00c7er\u00e7evesini Kullanarak Python Web Uygulamalar\u0131 Geli\u015ftirme Rehberi\",\"datePublished\":\"2025-11-10T19:40:59+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/bottle-mikro-cercevesini-kullanarak-python-web-uygulamalari-gelistirme-rehberi\/\"},\"wordCount\":2433,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\"},\"articleSection\":[\"Python\"],\"inLanguage\":\"tr\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/fatihsoysal.com\/blog\/bottle-mikro-cercevesini-kullanarak-python-web-uygulamalari-gelistirme-rehberi\/#respond\"]}],\"copyrightYear\":\"2025\",\"copyrightHolder\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/bottle-mikro-cercevesini-kullanarak-python-web-uygulamalari-gelistirme-rehberi\/\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/bottle-mikro-cercevesini-kullanarak-python-web-uygulamalari-gelistirme-rehberi\/\",\"name\":\"Bottle Mikro \u00c7er\u00e7evesini Kullanarak Python Web Uygulamalar\u0131 Geli\u015ftirme Rehberi - Kodlar\u0131n Gizemli D\u00fcnyas\u0131\",\"isPartOf\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#website\"},\"datePublished\":\"2025-11-10T19:40:59+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/bottle-mikro-cercevesini-kullanarak-python-web-uygulamalari-gelistirme-rehberi\/#breadcrumb\"},\"inLanguage\":\"tr\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/fatihsoysal.com\/blog\/bottle-mikro-cercevesini-kullanarak-python-web-uygulamalari-gelistirme-rehberi\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/bottle-mikro-cercevesini-kullanarak-python-web-uygulamalari-gelistirme-rehberi\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Anasayfa\",\"item\":\"https:\/\/fatihsoysal.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Bottle Mikro \u00c7er\u00e7evesini Kullanarak Python Web Uygulamalar\u0131 Geli\u015ftirme Rehberi\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#website\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/\",\"name\":\"Fatihsoysal.com\",\"description\":\"Blog - Yaz\u0131l\u0131m D\u00fcnyas\u0131 Tecr\u00fcbelerim\",\"publisher\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/fatihsoysal.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"tr\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\",\"name\":\"Fatih Soysal\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"tr\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png\",\"contentUrl\":\"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png\",\"width\":512,\"height\":512,\"caption\":\"Fatih Soysal\"},\"logo\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/\"},\"description\":\"Kullan\u0131m ve kodlama m\u00fckemmeliyetini odak alan uygulamalar olu\u015fturma deneyimine sahip, profesyonel olarak 15+ y\u0131l \u00fczeri deneyime sahip bir yaz\u0131l\u0131m m\u00fchendisi.\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/author\/fatihsoysal\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Bottle Mikro \u00c7er\u00e7evesini Kullanarak Python Web Uygulamalar\u0131 Geli\u015ftirme Rehberi - Kodlar\u0131n Gizemli D\u00fcnyas\u0131","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/fatihsoysal.com\/blog\/bottle-mikro-cercevesini-kullanarak-python-web-uygulamalari-gelistirme-rehberi\/","og_locale":"tr_TR","og_type":"article","og_title":"Bottle Mikro \u00c7er\u00e7evesini Kullanarak Python Web Uygulamalar\u0131 Geli\u015ftirme Rehberi","og_description":"Bottle Mikro \u00c7er\u00e7evesini Kullanarak Python Web Uygulamalar\u0131 Geli\u015ftirme Rehberi Python ekosistemi, web geli\u015ftirme i\u00e7in zengin bir ara\u00e7 yelpazes","og_url":"https:\/\/fatihsoysal.com\/blog\/bottle-mikro-cercevesini-kullanarak-python-web-uygulamalari-gelistirme-rehberi\/","og_site_name":"Kodlar\u0131n Gizemli D\u00fcnyas\u0131","article_published_time":"2025-11-10T19:40:59+00:00","author":"Fatih Soysal","twitter_card":"summary_large_image","twitter_misc":{"Yazan:":"Fatih Soysal","Tahmini okuma s\u00fcresi":"21 dakika"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/fatihsoysal.com\/blog\/bottle-mikro-cercevesini-kullanarak-python-web-uygulamalari-gelistirme-rehberi\/#article","isPartOf":{"@id":"https:\/\/fatihsoysal.com\/blog\/bottle-mikro-cercevesini-kullanarak-python-web-uygulamalari-gelistirme-rehberi\/"},"author":{"name":"Fatih Soysal","@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1"},"headline":"Bottle Mikro \u00c7er\u00e7evesini Kullanarak Python Web Uygulamalar\u0131 Geli\u015ftirme Rehberi","datePublished":"2025-11-10T19:40:59+00:00","mainEntityOfPage":{"@id":"https:\/\/fatihsoysal.com\/blog\/bottle-mikro-cercevesini-kullanarak-python-web-uygulamalari-gelistirme-rehberi\/"},"wordCount":2433,"commentCount":0,"publisher":{"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1"},"articleSection":["Python"],"inLanguage":"tr","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/fatihsoysal.com\/blog\/bottle-mikro-cercevesini-kullanarak-python-web-uygulamalari-gelistirme-rehberi\/#respond"]}],"copyrightYear":"2025","copyrightHolder":{"@id":"https:\/\/fatihsoysal.com\/blog\/#organization"}},{"@type":"WebPage","@id":"https:\/\/fatihsoysal.com\/blog\/bottle-mikro-cercevesini-kullanarak-python-web-uygulamalari-gelistirme-rehberi\/","url":"https:\/\/fatihsoysal.com\/blog\/bottle-mikro-cercevesini-kullanarak-python-web-uygulamalari-gelistirme-rehberi\/","name":"Bottle Mikro \u00c7er\u00e7evesini Kullanarak Python Web Uygulamalar\u0131 Geli\u015ftirme Rehberi - Kodlar\u0131n Gizemli D\u00fcnyas\u0131","isPartOf":{"@id":"https:\/\/fatihsoysal.com\/blog\/#website"},"datePublished":"2025-11-10T19:40:59+00:00","breadcrumb":{"@id":"https:\/\/fatihsoysal.com\/blog\/bottle-mikro-cercevesini-kullanarak-python-web-uygulamalari-gelistirme-rehberi\/#breadcrumb"},"inLanguage":"tr","potentialAction":[{"@type":"ReadAction","target":["https:\/\/fatihsoysal.com\/blog\/bottle-mikro-cercevesini-kullanarak-python-web-uygulamalari-gelistirme-rehberi\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/fatihsoysal.com\/blog\/bottle-mikro-cercevesini-kullanarak-python-web-uygulamalari-gelistirme-rehberi\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Anasayfa","item":"https:\/\/fatihsoysal.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Bottle Mikro \u00c7er\u00e7evesini Kullanarak Python Web Uygulamalar\u0131 Geli\u015ftirme Rehberi"}]},{"@type":"WebSite","@id":"https:\/\/fatihsoysal.com\/blog\/#website","url":"https:\/\/fatihsoysal.com\/blog\/","name":"Fatihsoysal.com","description":"Blog - Yaz\u0131l\u0131m D\u00fcnyas\u0131 Tecr\u00fcbelerim","publisher":{"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/fatihsoysal.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"tr"},{"@type":["Person","Organization"],"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1","name":"Fatih Soysal","image":{"@type":"ImageObject","inLanguage":"tr","@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/","url":"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png","contentUrl":"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png","width":512,"height":512,"caption":"Fatih Soysal"},"logo":{"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/"},"description":"Kullan\u0131m ve kodlama m\u00fckemmeliyetini odak alan uygulamalar olu\u015fturma deneyimine sahip, profesyonel olarak 15+ y\u0131l \u00fczeri deneyime sahip bir yaz\u0131l\u0131m m\u00fchendisi.","url":"https:\/\/fatihsoysal.com\/blog\/author\/fatihsoysal\/"}]}},"yoast_meta":{"yoast_wpseo_title":"","yoast_wpseo_metadesc":"","yoast_wpseo_canonical":""},"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts\/34078","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/comments?post=34078"}],"version-history":[{"count":1,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts\/34078\/revisions"}],"predecessor-version":[{"id":34079,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts\/34078\/revisions\/34079"}],"wp:attachment":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/media?parent=34078"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/categories?post=34078"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/tags?post=34078"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}