{"id":34960,"date":"2025-11-24T05:40:43","date_gmt":"2025-11-24T02:40:43","guid":{"rendered":"https:\/\/fatihsoysal.com\/blog\/?p=34960"},"modified":"2025-11-24T05:40:43","modified_gmt":"2025-11-24T02:40:43","slug":"python-markdown-flask-ve-sqlite-ile-dinamik-web-icerikleri-olusturma","status":"publish","type":"post","link":"https:\/\/fatihsoysal.com\/blog\/python-markdown-flask-ve-sqlite-ile-dinamik-web-icerikleri-olusturma\/","title":{"rendered":"Python-Markdown, Flask ve SQLite ile Dinamik Web \u0130\u00e7erikleri Olu\u015fturma"},"content":{"rendered":"<p><body><\/p>\n<h2>Python-Markdown, Flask ve SQLite ile Dinamik Web \u0130\u00e7erikleri Olu\u015fturma<\/h2>\n<h3>Giri\u015f<\/h3>\n<p>Modern web uygulamalar\u0131nda i\u00e7erik y\u00f6netimi, kullan\u0131c\u0131 dostu aray\u00fczler ve esnek depolama \u00e7\u00f6z\u00fcmleri b\u00fcy\u00fck \u00f6nem ta\u015f\u0131r. Bu makalede, Python ekosisteminin g\u00fc\u00e7l\u00fc ara\u00e7lar\u0131n\u0131 bir araya getirerek dinamik ve y\u00f6netilebilir web i\u00e7erikleri olu\u015fturmay\u0131 inceleyece\u011fiz: Hafif ve esnek web \u00e7at\u0131s\u0131 Flask, metin bi\u00e7imlendirme i\u00e7in pop\u00fcler Markdown s\u00f6zdizimini HTML&#8217;e \u00e7eviren Python-Markdown k\u00fct\u00fcphanesi ve sunucusuz, basit bir veritaban\u0131 \u00e7\u00f6z\u00fcm\u00fc olan SQLite. Bu \u00fc\u00e7l\u00fcy\u00fc entegre ederek, kullan\u0131c\u0131lar\u0131n Markdown format\u0131nda i\u00e7erik girmesine, bu i\u00e7eri\u011fin veritaban\u0131nda saklanmas\u0131na ve web sayfas\u0131nda HTML olarak g\u00f6r\u00fcnt\u00fclenmesine olanak tan\u0131yan bir web uygulamas\u0131 geli\u015ftirece\u011fiz. Bu yakla\u015f\u0131m, bloglar, dok\u00fcmantasyon siteleri veya basit i\u00e7erik y\u00f6netim sistemleri (CMS) i\u00e7in ideal bir temel sunar.<\/p>\n<p>Flask, mikro-\u00e7er\u00e7eve yap\u0131s\u0131yla h\u0131zl\u0131 prototipleme ve k\u00fc\u00e7\u00fck\/orta \u00f6l\u00e7ekli uygulamalar i\u00e7in m\u00fckemmel bir se\u00e7imdir. Markdown, teknik yazarlar ve i\u00e7erik olu\u015fturucular aras\u0131nda yayg\u0131n olarak kullan\u0131lan, okunmas\u0131 ve yazmas\u0131 kolay bir bi\u00e7imlendirme dilidir. Python-Markdown, bu Markdown i\u00e7eri\u011fini programatik olarak web taray\u0131c\u0131lar\u0131n\u0131n anlayabilece\u011fi HTML&#8217;e d\u00f6n\u00fc\u015ft\u00fcr\u00fcr. SQLite ise, ayr\u0131 bir veritaban\u0131 sunucusu gerektirmeyen, dosya tabanl\u0131 bir veritaban\u0131 motoru olup, geli\u015ftirme a\u015famas\u0131nda ve k\u00fc\u00e7\u00fck \u00f6l\u00e7ekli uygulamalarda kolayca kullan\u0131labilir. Bu makale boyunca, bu teknolojileri ad\u0131m ad\u0131m nas\u0131l bir araya getirece\u011fimizi, temel bir i\u00e7erik ekleme, listeleme ve g\u00f6r\u00fcnt\u00fcleme uygulamas\u0131n\u0131 nas\u0131l geli\u015ftirece\u011fimizi detayl\u0131 bir \u015fekilde a\u00e7\u0131klayaca\u011f\u0131z.<\/p>\n<h3>Geli\u015ftirme Ortam\u0131n\u0131n Haz\u0131rlanmas\u0131<\/h3>\n<p>Herhangi bir Python projesine ba\u015flamadan \u00f6nce, ba\u011f\u0131ml\u0131l\u0131k \u00e7ak\u0131\u015fmalar\u0131n\u0131 \u00f6nlemek ve projenin temiz kalmas\u0131n\u0131 sa\u011flamak i\u00e7in sanal bir ortam olu\u015fturmak iyi bir uygulamad\u0131r.<\/p>\n<h4>Sanal Ortam Olu\u015fturma ve K\u00fct\u00fcphanelerin Kurulumu<\/h4>\n<p>\u00d6ncelikle projemiz i\u00e7in bir dizin olu\u015ftural\u0131m ve bu dizine ge\u00e7elim:<\/p>\n<pre><code class=\"language-bash\">mkdir flask_markdown_app\ncd flask_markdown_app<\/code><\/pre>\n<p>\u015eimdi, bir sanal ortam olu\u015ftural\u0131m ve onu etkinle\u015ftirelim:<\/p>\n<pre><code class=\"language-bash\">python3 -m venv venv\n<h2>Linux\/macOS<\/h2>\nsource venv\/bin\/activate\n<h2>Windows<\/h2>\nvenv\\Scripts\\activate<\/code><\/pre>\n<p>Sanal ortam etkinle\u015ftirildikten sonra, gerekli Python k\u00fct\u00fcphanelerini y\u00fckleyebiliriz. Bu projemiz i\u00e7in Flask, Python-Markdown ve veritaban\u0131 etkile\u015fimi i\u00e7in Flask-SQLAlchemy k\u00fct\u00fcphanelerine ihtiyac\u0131m\u0131z olacak:<\/p>\n<pre><code class=\"language-bash\">pip install Flask Flask-SQLAlchemy Markdown<\/code><\/pre>\n<p>Bu komutlar, Flask web \u00e7at\u0131s\u0131n\u0131, SQLAlchemy&#8217;nin Flask entegrasyonunu ve Markdown metinlerini HTML&#8217;e \u00e7evirecek olan Python-Markdown k\u00fct\u00fcphanesini sanal ortam\u0131n\u0131za kuracakt\u0131r.<\/p>\n<h3>Temel Flask Uygulamas\u0131 Olu\u015fturma<\/h3>\n<p>\u015eimdi, projemizin iskeletini olu\u015fturarak Flask uygulamas\u0131n\u0131 ba\u015flatal\u0131m. <code>app.py<\/code> ad\u0131nda bir dosya olu\u015ftural\u0131m ve i\u00e7ine temel Flask uygulamas\u0131n\u0131 yazal\u0131m:<\/p>\n<pre><code class=\"language-python\"># app.py\nfrom flask import Flask, render_template, request, redirect, url_for\nfrom flask_sqlalchemy import SQLAlchemy\nimport markdown\nfrom markupsafe import Markup\nimport datetime\n\napp = Flask(__name__)\napp.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:\/\/\/site.db'\napp.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False\ndb = SQLAlchemy(app)\n\n<h2>Veritaban\u0131 modeli burada tan\u0131mlanacak<\/h2>\n\n<h2>Ana sayfa ve di\u011fer rotalar burada tan\u0131mlanacak<\/h2>\n\nif __name__ == '__main__':\n    with app.app_context():\n        db.create_all() # Uygulama ba\u015flat\u0131ld\u0131\u011f\u0131nda veritaban\u0131 tablolar\u0131n\u0131 olu\u015ftur\n    app.run(debug=True)<\/code><\/pre>\n<p>Bu kod par\u00e7ac\u0131\u011f\u0131, Flask uygulamas\u0131n\u0131 ba\u015flat\u0131r, SQLite veritaban\u0131n\u0131n yolunu yap\u0131land\u0131r\u0131r ve Flask-SQLAlchemy objesini olu\u015fturur. <code>debug=True<\/code> ayar\u0131, geli\u015ftirme a\u015famas\u0131nda hatalar\u0131n ayr\u0131nt\u0131l\u0131 bir \u015fekilde g\u00f6sterilmesini ve kodda yap\u0131lan de\u011fi\u015fikliklerin otomatik olarak alg\u0131lan\u0131p uygulaman\u0131n yeniden y\u00fcklenmesini sa\u011flar. <code>db.create_all()<\/code> komutu, tan\u0131mlad\u0131\u011f\u0131m\u0131z veritaban\u0131 modellerine g\u00f6re tablolar\u0131 olu\u015fturur. Bu komutun <code>app.app_context()<\/code> i\u00e7inde \u00e7al\u0131\u015ft\u0131r\u0131lmas\u0131 \u00f6nemlidir, \u00e7\u00fcnk\u00fc veritaban\u0131 i\u015flemleri bir uygulama ba\u011flam\u0131 gerektirir.<\/p>\n<h3>Veritaban\u0131 Yap\u0131s\u0131 ve Modeli<\/h3>\n<p>\u0130\u00e7eriklerimizi saklamak i\u00e7in bir veritaban\u0131 tablosuna ihtiyac\u0131m\u0131z var. Flask-SQLAlchemy kullanarak bu tabloyu bir Python s\u0131n\u0131f\u0131 olarak tan\u0131mlayaca\u011f\u0131z. Bu s\u0131n\u0131f, her bir i\u00e7eri\u011fin (\u00f6rne\u011fin bir blog yaz\u0131s\u0131) hangi \u00f6zelliklere sahip olaca\u011f\u0131n\u0131 belirler.<\/p>\n<h4><code>Content<\/code> Modeli Tan\u0131mlama<\/h4>\n<p><code>app.py<\/code> dosyam\u0131zda, <code>db = SQLAlchemy(app)<\/code> sat\u0131r\u0131n\u0131n alt\u0131na a\u015fa\u011f\u0131daki <code>Content<\/code> modelini ekleyelim:<\/p>\n<pre><code class=\"language-python\"># app.py (devam\u0131)\n\nclass Content(db.Model):\n    id = db.Column(db.Integer, primary_key=True)\n    title = db.Column(db.String(100), nullable=False)\n    markdown_content = db.Column(db.Text, nullable=False)\n    html_content = db.Column(db.Text, nullable=False)\n    created_at = db.Column(db.DateTime, default=datetime.datetime.now)\n\n    def __repr__(self):\n        return f\"Content('{self.title}', '{self.created_at}')\"<\/code><\/pre>\n<p>Bu <code>Content<\/code> modeli \u015fu s\u00fctunlara sahiptir:<br \/>\n*   <code>id<\/code>: Her i\u00e7eri\u011fin benzersiz kimli\u011fi (otomatik artan birincil anahtar).<br \/>\n*   <code>title<\/code>: \u0130\u00e7eri\u011fin ba\u015fl\u0131\u011f\u0131 (en fazla 100 karakter, bo\u015f b\u0131rak\u0131lamaz).<br \/>\n*   <code>markdown_content<\/code>: Kullan\u0131c\u0131n\u0131n girdi\u011fi orijinal Markdown metni (bo\u015f b\u0131rak\u0131lamaz).<br \/>\n*   <code>html_content<\/code>: <code>markdown_content<\/code>&#8216;in Python-Markdown ile d\u00f6n\u00fc\u015ft\u00fcr\u00fclm\u00fc\u015f HTML versiyonu (bo\u015f b\u0131rak\u0131lamaz). Bu, her seferinde d\u00f6n\u00fc\u015ft\u00fcrme yapma ihtiyac\u0131n\u0131 ortadan kald\u0131rarak performans\u0131 art\u0131r\u0131r.<br \/>\n*   <code>created_at<\/code>: \u0130\u00e7eri\u011fin olu\u015fturulma zaman\u0131 (varsay\u0131lan olarak ge\u00e7erli zaman).<\/p>\n<p><code>__repr__<\/code> metodu, bir <code>Content<\/code> objesi yazd\u0131r\u0131ld\u0131\u011f\u0131nda daha anlaml\u0131 bir \u00e7\u0131kt\u0131 vermesini sa\u011flar.<\/p>\n<h3>\u0130\u00e7erik Ekleme Aray\u00fcz\u00fc<\/h3>\n<p>Kullan\u0131c\u0131lar\u0131n Markdown i\u00e7eri\u011fi girmesi i\u00e7in bir form ve bu formu i\u015fleyecek bir Flask rotas\u0131 olu\u015fturmam\u0131z gerekiyor.<\/p>\n<h4>\u0130\u00e7erik Ekleme Rotas\u0131 ve Formu<\/h4>\n<p><code>app.py<\/code> dosyam\u0131za <code>add_content<\/code> ad\u0131nda bir rota ekleyelim:<\/p>\n<pre><code class=\"language-python\"># app.py (devam\u0131)\n\n@app.route('\/add', methods=['GET', 'POST'])\ndef add_content():\n    if request.method == 'POST':\n        title = request.form['title']\n        markdown_text = request.form['markdown_content']\n        \n        # Markdown'\u0131 HTML'e \u00e7evir\n        html_text = markdown.markdown(markdown_text, extensions=['fenced_code', 'tables'])\n        \n        # Yeni i\u00e7erik objesini olu\u015ftur\n        new_content = Content(title=title, markdown_content=markdown_text, html_content=html_text)\n        \n        # Veritaban\u0131na ekle ve kaydet\n        db.session.add(new_content)\n        db.session.commit()\n        \n        return redirect(url_for('index')) # Ana sayfaya y\u00f6nlendir\n    \n    return render_template('add_content.html')<\/code><\/pre>\n<p>Bu rota, <code>GET<\/code> iste\u011fi geldi\u011finde <code>add_content.html<\/code> \u015fablonunu render eder. <code>POST<\/code> iste\u011fi geldi\u011finde ise formdan gelen <code>title<\/code> ve <code>markdown_content<\/code> verilerini al\u0131r. <code>markdown.markdown()<\/code> fonksiyonu ile Markdown metnini HTML&#8217;e \u00e7eviririz. Burada <code>extensions=['fenced_code', 'tables']<\/code> gibi uzant\u0131lar kullanarak kod bloklar\u0131n\u0131 ve tablolar\u0131 destekleyebiliriz. Daha sonra, yeni bir <code>Content<\/code> objesi olu\u015fturulur, veritaban\u0131na eklenir ve kaydedilir. Son olarak, kullan\u0131c\u0131 ana sayfaya y\u00f6nlendirilir.<\/p>\n<h4><code>add_content.html<\/code> \u015eablonu<\/h4>\n<p><code>templates<\/code> ad\u0131nda bir klas\u00f6r olu\u015ftural\u0131m ve i\u00e7ine <code>add_content.html<\/code> dosyas\u0131n\u0131 ekleyelim:<\/p>\n<pre><code class=\"language-html\"><!-- templates\/add_content.html -->\n{% extends \"base.html\" %}\n\n{% block title %}\u0130\u00e7erik Ekle{% endblock %}\n\n{% block content %}\n    <div class=\"container mt-4\">\n        \n        <form method=\"POST\">\n            <div class=\"mb-3\">\n                <label for=\"title\" class=\"form-label\">Ba\u015fl\u0131k<\/label>\n                <input type=\"text\" class=\"form-control\" id=\"title\" name=\"title\" required>\n            <\/div>\n            <div class=\"mb-3\">\n                <label for=\"markdown_content\" class=\"form-label\">Markdown \u0130\u00e7eri\u011fi<\/label>\n                <textarea class=\"form-control\" id=\"markdown_content\" name=\"markdown_content\" rows=\"10\" required><\/textarea>\n                <small class=\"form-text text-muted\">Markdown s\u00f6zdizimini kullanarak metin girin.<\/small>\n            <\/div>\n            <button type=\"submit\" class=\"btn btn-primary\">\u0130\u00e7eri\u011fi Kaydet<\/button>\n        <\/form>\n    <\/div>\n{% endblock %}<\/code><\/pre>\n<p>Bu \u015fablon, Bootstrap s\u0131n\u0131flar\u0131n\u0131 kullanarak basit bir form olu\u015fturur. Kullan\u0131c\u0131 <code>title<\/code> ve <code>markdown_content<\/code> alanlar\u0131n\u0131 doldurarak i\u00e7eri\u011fi kaydedebilir.<\/p>\n<h3>\u0130\u00e7erik Listeleme ve G\u00f6r\u00fcnt\u00fcleme<\/h3>\n<p>Uygulamam\u0131z\u0131n ana sayfas\u0131, kaydedilen t\u00fcm i\u00e7eriklerin ba\u015fl\u0131klar\u0131n\u0131 listeleyecek ve her bir ba\u015fl\u0131\u011fa t\u0131klan\u0131ld\u0131\u011f\u0131nda ilgili i\u00e7eri\u011fin detay sayfas\u0131n\u0131 g\u00f6sterecek.<\/p>\n<h4>Ana Sayfa Rotas\u0131<\/h4>\n<p><code>app.py<\/code> dosyam\u0131za <code>index<\/code> ad\u0131nda bir rota ekleyelim:<\/p>\n<pre><code class=\"language-python\"># app.py (devam\u0131)\n\n@app.route('\/')\ndef index():\n    contents = Content.query.order_by(Content.created_at.desc()).all()\n    return render_template('index.html', contents=contents)<\/code><\/pre>\n<p>Bu rota, veritaban\u0131ndaki t\u00fcm <code>Content<\/code> objelerini <code>created_at<\/code> s\u00fctununa g\u00f6re azalan s\u0131rada (yani en yeni i\u00e7erik en \u00fcstte) \u00e7eker ve bunlar\u0131 <code>index.html<\/code> \u015fablonuna g\u00f6nderir.<\/p>\n<h4><code>index.html<\/code> \u015eablonu<\/h4>\n<p><code>templates<\/code> klas\u00f6r\u00fcne <code>index.html<\/code> dosyas\u0131n\u0131 ekleyelim:<\/p>\n<pre><code class=\"language-html\"><!-- templates\/index.html -->\n{% extends \"base.html\" %}\n\n{% block title %}Ana Sayfa{% endblock %}\n\n{% block content %}\n    <div class=\"container mt-4\">\n        \n        <p><a href=\"{{ url_for('add_content') }}\" class=\"btn btn-success\">Yeni \u0130\u00e7erik Ekle<\/a><\/p>\n        {% if contents %}\n            <ul class=\"list-group\">\n                {% for content in contents %}\n                    <li class=\"list-group-item d-flex justify-content-between align-items-center\">\n                        <a href=\"{{ url_for('content_detail', content_id=content.id) }}\">{{ content.title }}<\/a>\n                        <small class=\"text-muted\">{{ content.created_at.strftime('%d.%m.%Y %H:%M') }}<\/small>\n                    <\/li>\n                {% endfor %}\n            <\/ul>\n        {% else %}\n            <p>Hen\u00fcz hi\u00e7 i\u00e7erik eklenmemi\u015f. <a href=\"{{ url_for('add_content') }}\">\u0130lk i\u00e7eri\u011fi ekleyin<\/a>.<\/p>\n        {% endif %}\n    <\/div>\n{% endblock %}<\/code><\/pre>\n<p>Bu \u015fablon, <code>contents<\/code> listesini d\u00f6ng\u00fcye alarak her bir i\u00e7eri\u011fin ba\u015fl\u0131\u011f\u0131n\u0131 g\u00f6r\u00fcnt\u00fcler. Her ba\u015fl\u0131k, <code>content_detail<\/code> rotas\u0131na giden bir ba\u011flant\u0131d\u0131r.<\/p>\n<h4>\u0130\u00e7erik Detay Sayfas\u0131 Rotas\u0131<\/h4>\n<p>Her i\u00e7eri\u011fin detay\u0131n\u0131 g\u00f6stermek i\u00e7in bir rota daha ekleyelim:<\/p>\n<pre><code class=\"language-python\"># app.py (devam\u0131)\n\n@app.route('\/content\/<int:content_id>')\ndef content_detail(content_id):\n    content = Content.query.get_or_404(content_id)\n    return render_template('detail.html', content=content)<\/code><\/pre>\n<p>Bu rota, URL&#8217;den <code>content_id<\/code> parametresini al\u0131r, bu ID&#8217;ye sahip i\u00e7eri\u011fi veritaban\u0131ndan \u00e7eker. E\u011fer i\u00e7erik bulunamazsa, Flask otomatik olarak 404 hatas\u0131 d\u00f6nd\u00fcr\u00fcr. Bulunan i\u00e7erik, <code>detail.html<\/code> \u015fablonuna g\u00f6nderilir.<\/p>\n<h4><code>detail.html<\/code> \u015eablonu<\/h4>\n<p><code>templates<\/code> klas\u00f6r\u00fcne <code>detail.html<\/code> dosyas\u0131n\u0131 ekleyelim:<\/p>\n<pre><code class=\"language-html\"><!-- templates\/detail.html -->\n{% extends \"base.html\" %}\n\n{% block title %}{{ content.title }}{% endblock %}\n\n{% block content %}\n    <div class=\"container mt-4\">\n        \n        <small class=\"text-muted\">Olu\u015fturulma Tarihi: {{ content.created_at.strftime('%d.%m.%Y %H:%M') }}<\/small>\n        <hr>\n        <div class=\"markdown-body\">\n            {{ content.html_content | safe }}\n        <\/div>\n        <div class=\"mt-4\">\n            <a href=\"{{ url_for('edit_content', content_id=content.id) }}\" class=\"btn btn-warning btn-sm\">D\u00fczenle<\/a>\n            <form action=\"{{ url_for('delete_content', content_id=content.id) }}\" method=\"POST\" class=\"d-inline\">\n                <button type=\"submit\" class=\"btn btn-danger btn-sm\" onclick=\"return confirm('Bu i\u00e7eri\u011fi silmek istedi\u011finizden emin misiniz?');\">Sil<\/button>\n            <\/form>\n            <a href=\"{{ url_for('index') }}\" class=\"btn btn-secondary btn-sm\">Geri D\u00f6n<\/a>\n        <\/div>\n    <\/div>\n{% endblock %}<\/code><\/pre>\n<p>Bu \u015fablonda en \u00f6nemli k\u0131s\u0131m <code>{{ content.html_content | safe }}<\/code> sat\u0131r\u0131d\u0131r. Flask ve Jinja2, varsay\u0131lan olarak \u015fablonlara g\u00f6nderilen HTML i\u00e7eri\u011fini g\u00fcvenlik amac\u0131yla ka\u00e7\u0131r\u0131r (escape). Ancak bizim <code>html_content<\/code> s\u00fctunumuz zaten Markdown&#8217;dan d\u00f6n\u00fc\u015ft\u00fcr\u00fclm\u00fc\u015f ve g\u00fcvenli kabul etti\u011fimiz HTML oldu\u011fu i\u00e7in, <code>| safe<\/code> filtresini kullanarak Jinja2&#8217;ye bu i\u00e7eri\u011fi oldu\u011fu gibi render etmesini s\u00f6yleriz. <strong>Ancak bu, kullan\u0131c\u0131 taraf\u0131ndan girilen ham HTML&#8217;i do\u011frudan g\u00f6stermek i\u00e7in riskli bir y\u00f6ntem olabilir. Daha g\u00fcvenli uygulamalar i\u00e7in HTML temizleme k\u00fct\u00fcphaneleri (\u00f6rne\u011fin <code>Bleach<\/code>) kullanmak \u00f6nemlidir.<\/strong> Bizim senaryomuzda, Markdown&#8217;dan d\u00f6n\u00fc\u015ft\u00fcr\u00fclen HTML&#8217;in nispeten g\u00fcvenli oldu\u011funu varsay\u0131yoruz.<\/p>\n<h3>\u0130\u00e7erik D\u00fczenleme ve Silme<\/h3>\n<p>Uygulamam\u0131z\u0131 daha i\u015flevsel hale getirmek i\u00e7in i\u00e7erikleri d\u00fczenleme ve silme \u00f6zelliklerini ekleyelim.<\/p>\n<h4>\u0130\u00e7erik D\u00fczenleme Rotas\u0131<\/h4>\n<p><code>app.py<\/code> dosyam\u0131za <code>edit_content<\/code> rotas\u0131n\u0131 ekleyelim:<\/p>\n<pre><code class=\"language-python\"># app.py (devam\u0131)\n\n@app.route('\/content\/<int:content_id>\/edit', methods=['GET', 'POST'])\ndef edit_content(content_id):\n    content = Content.query.get_or_404(content_id)\n    if request.method == 'POST':\n        content.title = request.form['title']\n        content.markdown_content = request.form['markdown_content']\n        content.html_content = markdown.markdown(content.markdown_content, extensions=['fenced_code', 'tables'])\n        db.session.commit()\n        return redirect(url_for('content_detail', content_id=content.id))\n    return render_template('edit_content.html', content=content)<\/code><\/pre>\n<p>Bu rota da <code>add_content<\/code> rotas\u0131na benzer \u00e7al\u0131\u015f\u0131r. <code>GET<\/code> iste\u011fi geldi\u011finde, mevcut i\u00e7eri\u011fin bilgilerini \u00f6nceden doldurulmu\u015f bir formla <code>edit_content.html<\/code> \u015fablonunu render eder. <code>POST<\/code> iste\u011fi geldi\u011finde ise formdan gelen yeni verileri kullanarak i\u00e7eri\u011fi g\u00fcnceller, Markdown&#8217;\u0131 tekrar HTML&#8217;e \u00e7evirir ve veritaban\u0131na kaydeder.<\/p>\n<h4><code>edit_content.html<\/code> \u015eablonu<\/h4>\n<p><code>templates<\/code> klas\u00f6r\u00fcne <code>edit_content.html<\/code> dosyas\u0131n\u0131 ekleyelim:<\/p>\n<pre><code class=\"language-html\"><!-- templates\/edit_content.html -->\n{% extends \"base.html\" %}\n\n{% block title %}\u0130\u00e7eri\u011fi D\u00fczenle{% endblock %}\n\n{% block content %}\n    <div class=\"container mt-4\">\n        \n        <form method=\"POST\">\n            <div class=\"mb-3\">\n                <label for=\"title\" class=\"form-label\">Ba\u015fl\u0131k<\/label>\n                <input type=\"text\" class=\"form-control\" id=\"title\" name=\"title\" value=\"{{ content.title }}\" required>\n            <\/div>\n            <div class=\"mb-3\">\n                <label for=\"markdown_content\" class=\"form-label\">Markdown \u0130\u00e7eri\u011fi<\/label>\n                <textarea class=\"form-control\" id=\"markdown_content\" name=\"markdown_content\" rows=\"10\" required>{{ content.markdown_content }}<\/textarea>\n            <\/div>\n            <button type=\"submit\" class=\"btn btn-primary\">De\u011fi\u015fiklikleri Kaydet<\/button>\n            <a href=\"{{ url_for('content_detail', content_id=content.id) }}\" class=\"btn btn-secondary\">\u0130ptal<\/a>\n        <\/form>\n    <\/div>\n{% endblock %}<\/code><\/pre>\n<p>Bu \u015fablon, d\u00fczenlenecek i\u00e7eri\u011fin mevcut ba\u015fl\u0131\u011f\u0131n\u0131 ve Markdown metnini form alanlar\u0131na <code>value<\/code> ve <code>textarea<\/code> i\u00e7eri\u011fi olarak yerle\u015ftirir.<\/p>\n<h4>\u0130\u00e7erik Silme Rotas\u0131<\/h4>\n<p><code>app.py<\/code> dosyam\u0131za <code>delete_content<\/code> rotas\u0131n\u0131 ekleyelim:<\/p>\n<pre><code class=\"language-python\"># app.py (devam\u0131)\n\n@app.route('\/content\/<int:content_id>\/delete', methods=['POST'])\ndef delete_content(content_id):\n    content = Content.query.get_or_404(content_id)\n    db.session.delete(content)\n    db.session.commit()\n    return redirect(url_for('index'))<\/code><\/pre>\n<p>Bu rota, yaln\u0131zca <code>POST<\/code> iste\u011fi kabul eder. Bu, yanl\u0131\u015fl\u0131kla silmeleri \u00f6nlemek i\u00e7in iyi bir g\u00fcvenlik uygulamas\u0131d\u0131r. \u0130\u00e7eri\u011fi veritaban\u0131ndan siler ve ana sayfaya y\u00f6nlendirir.<\/p>\n<h3>Flask \u015eablonlar\u0131 (Jinja2) ile Entegrasyon<\/h3>\n<p>Uygulamam\u0131z\u0131n t\u00fcm sayfalar\u0131 i\u00e7in ortak bir g\u00f6r\u00fcn\u00fcm sa\u011flamak amac\u0131yla bir <code>base.html<\/code> \u015fablonu olu\u015fturaca\u011f\u0131z ve di\u011fer \u015fablonlar\u0131m\u0131z bu temel \u015fablondan miras alacak. Bu, kod tekrar\u0131n\u0131 azalt\u0131r ve stil tutarl\u0131l\u0131\u011f\u0131n\u0131 sa\u011flar.<\/p>\n<h4><code>base.html<\/code> \u015eablonu<\/h4>\n<p><code>templates<\/code> klas\u00f6r\u00fcne <code>base.html<\/code> dosyas\u0131n\u0131 ekleyelim:<\/p>\n<pre><code class=\"language-html\"><!-- templates\/base.html -->\n<!DOCTYPE html>\n<html lang=\"tr\">\n<head>\n    <meta charset=\"UTF-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n    <title>{% block title %}Flask Markdown App{% endblock %}<\/title>\n    <!-- Bootstrap CSS -->\n    <link href=\"https:\/\/cdn.jsdelivr.net\/npm\/bootstrap@5.3.3\/dist\/css\/bootstrap.min.css\" rel=\"stylesheet\" integrity=\"sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH\" crossorigin=\"anonymous\">\n    <style>\n        \/<em> Markdown i\u00e7eri\u011fi i\u00e7in temel stil ayarlamalar\u0131 <\/em>\/\n        .markdown-body {\n            font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, \"Noto Sans\", sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\";\n            line-height: 1.6;\n            word-wrap: break-word;\n        }\n        .markdown-body h1, .markdown-body h2, .markdown-body h3, .markdown-body h4, .markdown-body h5, .markdown-body h6 {\n            margin-top: 1em;\n            margin-bottom: 0.5em;\n            font-weight: 600;\n            line-height: 1.25;\n        }\n        .markdown-body p {\n            margin-bottom: 1em;\n        }\n        .markdown-body pre, .markdown-body code {\n            font-family: SFMono-Regular, Consolas, \"Liberation Mono\", Menlo, Courier, monospace;\n            background-color: #f6f8fa;\n            border-radius: 3px;\n            padding: 0.2em 0.4em;\n            font-size: 85%;\n        }\n        .markdown-body pre {\n            padding: 16px;\n            overflow: auto;\n            line-height: 1.45;\n            background-color: #f6f8fa;\n            border-radius: 6px;\n        }\n        .markdown-body pre code {\n            padding: 0;\n            background-color: transparent;\n            font-size: 100%;\n        }\n        .markdown-body table {\n            width: 100%;\n            border-collapse: collapse;\n            margin-bottom: 1em;\n        }\n        .markdown-body th, .markdown-body td {\n            border: 1px solid #dfe2e5;\n            padding: 6px 13px;\n        }\n        .markdown-body th {\n            font-weight: 600;\n        }\n        .markdown-body blockquote {\n            padding: 0 1em;\n            color: #6a737d;\n            border-left: 0.25em solid #dfe2e5;\n            margin-left: 0;\n        }\n        .markdown-body ul, .markdown-body ol {\n            padding-left: 2em;\n        }\n    <\/style>\n<\/head>\n<body>\n    <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n        <div class=\"container\">\n            <a class=\"navbar-brand\" href=\"{{ url_for('index') }}\">Flask Markdown App<\/a>\n            <button class=\"navbar-toggler\" type=\"button\" data-bs-toggle=\"collapse\" data-bs-target=\"#navbarNav\" aria-controls=\"navbarNav\" aria-expanded=\"false\" aria-label=\"Toggle navigation\">\n                <span class=\"navbar-toggler-icon\"><\/span>\n            <\/button>\n            <div class=\"collapse navbar-collapse\" id=\"navbarNav\">\n                <ul class=\"navbar-nav\">\n                    <li class=\"nav-item\">\n                        <a class=\"nav-link\" href=\"{{ url_for('index') }}\">Anasayfa<\/a>\n                    <\/li>\n                    <li class=\"nav-item\">\n                        <a class=\"nav-link\" href=\"{{ url_for('add_content') }}\">\u0130\u00e7erik Ekle<\/a>\n                    <\/li>\n                <\/ul>\n            <\/div>\n        <\/div>\n    <\/nav>\n\n    <div class=\"container\">\n        {% block content %}{% endblock %}\n    <\/div>\n\n    <!-- Bootstrap JS -->\n    <script src=\"https:\/\/cdn.jsdelivr.net\/npm\/bootstrap@5.3.3\/dist\/js\/bootstrap.bundle.min.js\" integrity=\"sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz\" crossorigin=\"anonymous\"><\/script>\n<\/body>\n<\/html><\/code><\/pre>\n<p>Bu <code>base.html<\/code> \u015fablonu:<br \/>\n*   Temel HTML yap\u0131s\u0131n\u0131, meta etiketlerini ve dil ayar\u0131n\u0131 i\u00e7erir.<br \/>\n*   Bootstrap CSS ve JS dosyalar\u0131n\u0131 CDN \u00fczerinden dahil eder, b\u00f6ylece uygulamam\u0131z modern bir g\u00f6r\u00fcn\u00fcme sahip olur.<br \/>\n*   Bir navigasyon \u00e7ubu\u011fu (navbar) ve bir <code>div.container<\/code> i\u00e7erir.<br \/>\n*   <code>{% block title %}<\/code> ve <code>{% block content %}<\/code> bloklar\u0131 tan\u0131mlar. Bu bloklar, miras alan \u015fablonlar taraf\u0131ndan doldurulacakt\u0131r.<br \/>\n*   <code>url_for<\/code> fonksiyonunu kullanarak Flask rotalar\u0131na dinamik ba\u011flant\u0131lar olu\u015fturur.<\/p>\n<h3>G\u00fcvenlik ve \u0130yile\u015ftirmeler<\/h3>\n<p>Kullan\u0131c\u0131dan al\u0131nan i\u00e7eri\u011fi do\u011frudan HTML olarak g\u00f6stermek her zaman potansiyel g\u00fcvenlik riskleri ta\u015f\u0131r.<\/p>\n<h4>XSS Sald\u0131r\u0131lar\u0131na Kar\u015f\u0131 Korunma<\/h4>\n<p>Bizim uygulamam\u0131zda <code>markdown.markdown()<\/code> fonksiyonu Markdown&#8217;\u0131 HTML&#8217;e \u00e7evirirken, varsay\u0131lan olarak baz\u0131 potansiyel zararl\u0131 HTML etiketlerini (\u00f6rne\u011fin <code><script><\/code>) ka\u00e7\u0131r\u0131r veya kald\u0131r\u0131r. Ancak tam g\u00fcvenlik i\u00e7in, \u00f6zellikle kullan\u0131c\u0131lar\u0131n ham HTML girebildi\u011fi veya Markdown uzant\u0131lar\u0131n\u0131n \u00e7ok esnek oldu\u011fu durumlarda, <code>Bleach<\/code> gibi bir HTML temizleme k\u00fct\u00fcphanesi kullanmak iyi bir uygulamad\u0131r.<\/p>\n<p>\u00d6rne\u011fin, <code>html_text = markdown.markdown(markdown_text, extensions=['fenced_code', 'tables'])<\/code> sat\u0131r\u0131ndan sonra, bu HTML'i temizlemek i\u00e7in <code>bleach<\/code> kullanabilirdik:<\/p>\n<pre><code class=\"language-python\">import bleach\n<h2>...<\/h2>\nhtml_text = markdown.markdown(markdown_text, extensions=['fenced_code', 'tables'])\ncleaned_html = bleach.clean(\n    html_text,\n    tags=['p', 'a', 'strong', 'em', 'h1', 'h2', 'h3', 'ul', 'ol', 'li', 'blockquote', 'code', 'pre', 'table', 'thead', 'tbody', 'tr', 'th', 'td'],\n    attributes={'a': ['href', 'title']},\n    strip=True\n)\n<h2>new_content = Content(..., html_content=cleaned_html)<\/code><\/pre>\n<\/h2>\n<p>Bu, sadece izin verilen etiketlerin ve niteliklerin kalmas\u0131n\u0131 sa\u011flar, b\u00f6ylece k\u00f6t\u00fc niyetli kodlar\u0131n enjekte edilmesini engeller.<\/p>\n<h4>Di\u011fer \u0130yile\u015ftirmeler<\/h4>\n<p>*   <strong>Hata Y\u00f6netimi:<\/strong> Form do\u011frulama, veritaban\u0131 hatalar\u0131 ve 404\/500 sayfalar\u0131 gibi durumlar i\u00e7in daha sa\u011flam hata y\u00f6netimi eklenmelidir. Flask-WTF gibi k\u00fct\u00fcphaneler form do\u011frulamas\u0131n\u0131 kolayla\u015ft\u0131r\u0131r.<br \/>\n*   <strong>Sayfaland\u0131rma:<\/strong> \u00c7ok say\u0131da i\u00e7erik oldu\u011funda, ana sayfada t\u00fcm i\u00e7erikleri tek seferde \u00e7ekmek performans sorunlar\u0131na yol a\u00e7abilir. Flask-SQLAlchemy'nin <code>paginate<\/code> y\u00f6ntemini kullanarak sayfaland\u0131rma eklemek performans\u0131 art\u0131r\u0131r.<br \/>\n*   <strong>Markdown Uzant\u0131lar\u0131:<\/strong> Python-Markdown k\u00fct\u00fcphanesi, <code>fenced_code<\/code>, <code>tables<\/code>, <code>toc<\/code> (i\u00e7indekiler tablosu), <code>admonition<\/code> (uyar\u0131 bloklar\u0131) gibi bir\u00e7ok uzant\u0131y\u0131 destekler. Bu uzant\u0131lar\u0131 <code>markdown.markdown()<\/code> fonksiyonuna <code>extensions<\/code> parametresi ile ge\u00e7erek uygulaman\u0131z\u0131n Markdown yeteneklerini geni\u015fletebilirsiniz.<br \/>\n*   <strong>Kullan\u0131c\u0131 Kimlik Do\u011frulama ve Yetkilendirme:<\/strong> \u0130\u00e7erik ekleme, d\u00fczenleme ve silme i\u015flemlerinin sadece yetkili kullan\u0131c\u0131lar taraf\u0131ndan yap\u0131lmas\u0131n\u0131 sa\u011flamak i\u00e7in Flask-Login gibi k\u00fct\u00fcphanelerle kullan\u0131c\u0131 y\u00f6netimi entegre edilebilir.<br \/>\n*   <strong>Daha \u0130yi UI\/UX:<\/strong> Bootstrap gibi bir CSS \u00e7at\u0131s\u0131 kullanmak ba\u015flang\u0131\u00e7 i\u00e7in harika olsa da, \u00f6zel CSS ve JavaScript ile daha zengin bir kullan\u0131c\u0131 deneyimi sunulabilir.<\/p>\n<h3>Sonu\u00e7<\/h3>\n<p>Bu makalede, Flask, Python-Markdown ve SQLite'\u0131 bir araya getirerek dinamik web i\u00e7erikleri olu\u015fturma s\u00fcrecini ad\u0131m ad\u0131m ele ald\u0131k. Geli\u015ftirme ortam\u0131n\u0131n haz\u0131rlanmas\u0131ndan ba\u015flayarak, veritaban\u0131 modelini tan\u0131mlad\u0131k, i\u00e7erik ekleme, listeleme, g\u00f6r\u00fcnt\u00fcleme, d\u00fczenleme ve silme i\u015flevlerini ger\u00e7ekle\u015ftiren Flask rotalar\u0131n\u0131 ve Jinja2 \u015fablonlar\u0131n\u0131 olu\u015fturduk. Ayr\u0131ca, Markdown i\u00e7eri\u011fini HTML'e d\u00f6n\u00fc\u015ft\u00fcrme ve g\u00fcvenlik hususlar\u0131 \u00fczerinde durduk.<\/p>\n<p>Bu entegrasyon, geli\u015ftiricilere hem esneklik hem de h\u0131z sunar. Flask'\u0131n minimal yap\u0131s\u0131, projenizi ihtiya\u00e7lar\u0131n\u0131za g\u00f6re \u015fekillendirmenize olanak tan\u0131rken, Python-Markdown i\u00e7erik olu\u015fturmay\u0131 kolayla\u015ft\u0131r\u0131r ve SQLite basit bir depolama \u00e7\u00f6z\u00fcm\u00fc sunar. Geli\u015ftirdi\u011fimiz bu temel uygulama, bir blog, bir bilgi bankas\u0131 veya basit bir dok\u00fcmantasyon platformu gibi daha karma\u015f\u0131k i\u00e7erik y\u00f6netim sistemleri i\u00e7in sa\u011flam bir ba\u015flang\u0131\u00e7 noktas\u0131 olabilir. G\u00fcvenlik ve performans iyile\u015ftirmelerini g\u00f6z \u00f6n\u00fcnde bulundurarak bu yap\u0131y\u0131 daha da ileriye ta\u015f\u0131yabilir, uygulaman\u0131z\u0131 ger\u00e7ek d\u00fcnya senaryolar\u0131na uygun hale getirebilirsiniz. Bu makalede edinilen bilgilerle, Python tabanl\u0131 web geli\u015ftirmede dinamik i\u00e7erik y\u00f6netiminin temellerini atm\u0131\u015f oldunuz.<br \/>\n<\/body><\/p>\n","protected":false},"excerpt":{"rendered":"Python-Markdown, Flask ve SQLite ile Dinamik Web \u0130\u00e7erikleri Olu\u015fturma\nGiri\u015f\nModern web uygulamalar\u0131nda i\u00e7erik y\u00f6netimi, kullan\u0131c\u0131 dostu ara","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-34960","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>Python-Markdown, Flask ve SQLite ile Dinamik Web \u0130\u00e7erikleri Olu\u015fturma - 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\/python-markdown-flask-ve-sqlite-ile-dinamik-web-icerikleri-olusturma\/\" \/>\n<meta property=\"og:locale\" content=\"tr_TR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Python-Markdown, Flask ve SQLite ile Dinamik Web \u0130\u00e7erikleri Olu\u015fturma\" \/>\n<meta property=\"og:description\" content=\"Python-Markdown, Flask ve SQLite ile Dinamik Web \u0130\u00e7erikleri Olu\u015fturma Giri\u015f Modern web uygulamalar\u0131nda i\u00e7erik y\u00f6netimi, kullan\u0131c\u0131 dostu ara\" \/>\n<meta property=\"og:url\" content=\"https:\/\/fatihsoysal.com\/blog\/python-markdown-flask-ve-sqlite-ile-dinamik-web-icerikleri-olusturma\/\" \/>\n<meta property=\"og:site_name\" content=\"Kodlar\u0131n Gizemli D\u00fcnyas\u0131\" \/>\n<meta property=\"article:published_time\" content=\"2025-11-24T02:40:43+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=\"14 dakika\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/python-markdown-flask-ve-sqlite-ile-dinamik-web-icerikleri-olusturma\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/python-markdown-flask-ve-sqlite-ile-dinamik-web-icerikleri-olusturma\/\"},\"author\":{\"name\":\"Fatih Soysal\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\"},\"headline\":\"Python-Markdown, Flask ve SQLite ile Dinamik Web \u0130\u00e7erikleri Olu\u015fturma\",\"datePublished\":\"2025-11-24T02:40:43+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/python-markdown-flask-ve-sqlite-ile-dinamik-web-icerikleri-olusturma\/\"},\"wordCount\":1937,\"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\/python-markdown-flask-ve-sqlite-ile-dinamik-web-icerikleri-olusturma\/#respond\"]}],\"copyrightYear\":\"2025\",\"copyrightHolder\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/python-markdown-flask-ve-sqlite-ile-dinamik-web-icerikleri-olusturma\/\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/python-markdown-flask-ve-sqlite-ile-dinamik-web-icerikleri-olusturma\/\",\"name\":\"Python-Markdown, Flask ve SQLite ile Dinamik Web \u0130\u00e7erikleri Olu\u015fturma - Kodlar\u0131n Gizemli D\u00fcnyas\u0131\",\"isPartOf\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#website\"},\"datePublished\":\"2025-11-24T02:40:43+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/python-markdown-flask-ve-sqlite-ile-dinamik-web-icerikleri-olusturma\/#breadcrumb\"},\"inLanguage\":\"tr\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/fatihsoysal.com\/blog\/python-markdown-flask-ve-sqlite-ile-dinamik-web-icerikleri-olusturma\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/python-markdown-flask-ve-sqlite-ile-dinamik-web-icerikleri-olusturma\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Anasayfa\",\"item\":\"https:\/\/fatihsoysal.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Python-Markdown, Flask ve SQLite ile Dinamik Web \u0130\u00e7erikleri Olu\u015fturma\"}]},{\"@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":"Python-Markdown, Flask ve SQLite ile Dinamik Web \u0130\u00e7erikleri Olu\u015fturma - 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\/python-markdown-flask-ve-sqlite-ile-dinamik-web-icerikleri-olusturma\/","og_locale":"tr_TR","og_type":"article","og_title":"Python-Markdown, Flask ve SQLite ile Dinamik Web \u0130\u00e7erikleri Olu\u015fturma","og_description":"Python-Markdown, Flask ve SQLite ile Dinamik Web \u0130\u00e7erikleri Olu\u015fturma Giri\u015f Modern web uygulamalar\u0131nda i\u00e7erik y\u00f6netimi, kullan\u0131c\u0131 dostu ara","og_url":"https:\/\/fatihsoysal.com\/blog\/python-markdown-flask-ve-sqlite-ile-dinamik-web-icerikleri-olusturma\/","og_site_name":"Kodlar\u0131n Gizemli D\u00fcnyas\u0131","article_published_time":"2025-11-24T02:40:43+00:00","author":"Fatih Soysal","twitter_card":"summary_large_image","twitter_misc":{"Yazan:":"Fatih Soysal","Tahmini okuma s\u00fcresi":"14 dakika"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/fatihsoysal.com\/blog\/python-markdown-flask-ve-sqlite-ile-dinamik-web-icerikleri-olusturma\/#article","isPartOf":{"@id":"https:\/\/fatihsoysal.com\/blog\/python-markdown-flask-ve-sqlite-ile-dinamik-web-icerikleri-olusturma\/"},"author":{"name":"Fatih Soysal","@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1"},"headline":"Python-Markdown, Flask ve SQLite ile Dinamik Web \u0130\u00e7erikleri Olu\u015fturma","datePublished":"2025-11-24T02:40:43+00:00","mainEntityOfPage":{"@id":"https:\/\/fatihsoysal.com\/blog\/python-markdown-flask-ve-sqlite-ile-dinamik-web-icerikleri-olusturma\/"},"wordCount":1937,"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\/python-markdown-flask-ve-sqlite-ile-dinamik-web-icerikleri-olusturma\/#respond"]}],"copyrightYear":"2025","copyrightHolder":{"@id":"https:\/\/fatihsoysal.com\/blog\/#organization"}},{"@type":"WebPage","@id":"https:\/\/fatihsoysal.com\/blog\/python-markdown-flask-ve-sqlite-ile-dinamik-web-icerikleri-olusturma\/","url":"https:\/\/fatihsoysal.com\/blog\/python-markdown-flask-ve-sqlite-ile-dinamik-web-icerikleri-olusturma\/","name":"Python-Markdown, Flask ve SQLite ile Dinamik Web \u0130\u00e7erikleri Olu\u015fturma - Kodlar\u0131n Gizemli D\u00fcnyas\u0131","isPartOf":{"@id":"https:\/\/fatihsoysal.com\/blog\/#website"},"datePublished":"2025-11-24T02:40:43+00:00","breadcrumb":{"@id":"https:\/\/fatihsoysal.com\/blog\/python-markdown-flask-ve-sqlite-ile-dinamik-web-icerikleri-olusturma\/#breadcrumb"},"inLanguage":"tr","potentialAction":[{"@type":"ReadAction","target":["https:\/\/fatihsoysal.com\/blog\/python-markdown-flask-ve-sqlite-ile-dinamik-web-icerikleri-olusturma\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/fatihsoysal.com\/blog\/python-markdown-flask-ve-sqlite-ile-dinamik-web-icerikleri-olusturma\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Anasayfa","item":"https:\/\/fatihsoysal.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Python-Markdown, Flask ve SQLite ile Dinamik Web \u0130\u00e7erikleri Olu\u015fturma"}]},{"@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\/34960","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=34960"}],"version-history":[{"count":1,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts\/34960\/revisions"}],"predecessor-version":[{"id":34961,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts\/34960\/revisions\/34961"}],"wp:attachment":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/media?parent=34960"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/categories?post=34960"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/tags?post=34960"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}