البرمجة

بناء تطبيق لاختصار الروابط بـ Flask

بناء تطبيق لاختصار الرّوابط باستعمال لغة بايثون وإطار العمل Flask – الجزء الثاني

يمثّل اختصار الروابط واحدة من أكثر الوظائف المطلوبة في الوقت الرّاهن، نظرًا لحاجة المستخدمين والمؤسسات إلى مشاركة روابط قصيرة وسهلة التذكّر، بدلًا من تلك الطويلة والمعقّدة. في الجزء الأوّل من هذا المشروع، تم بناء الأساسيات: إنشاء التطبيق باستخدام Flask، تعريف قاعدة بيانات بسيطة لحفظ الروابط الأصلية والمختصرة، وبناء واجهات الإدخال والاسترجاع. في هذا المقال، نستكمل ما بدأناه من خلال التوسّع في الجوانب التالية: إضافة واجهة مستخدم متقدّمة، تحسين البنية الأمنية، اعتماد نظام إحصائي لتتبع عدد النقرات على الروابط، وتوسيع وظائف قاعدة البيانات باستخدام SQLAlchemy وميزات Flask الحديثة.


1. تعزيز هيكل المشروع وتنظيم الملفات

مع توسع وظائف التطبيق، تصبح بنية المشروع أحد العوامل الحاسمة في سهولة التطوير والصيانة. يُوصى بتقسيم المشروع على الشكل التالي:

arduino
url_shortener/ │ ├── app/ │ ├── __init__.py │ ├── routes.py │ ├── models.py │ ├── forms.py │ ├── utils.py │ └── templates/ │ ├── base.html │ ├── index.html │ └── stats.html │ ├── static/ │ ├── css/ │ │ └── style.css │ └── js/ │ └── scripts.js │ ├── migrations/ │ ├── config.py ├── run.py └── requirements.txt

هذا النموذج يعتمد مبدأ فصل الاهتمامات، مما يتيح التعامل مع كل جزء من التطبيق على حدة، سواء كان متعلقًا بالمسارات، النماذج، الواجهات، أو الوظائف المساعدة.


2. إنشاء قاعدة البيانات وإدارة العلاقات

في هذا الجزء، سيتم استخدام SQLAlchemy ORM لإدارة الكيانات والتفاعل مع قاعدة البيانات بطريقة كائنية، مما يوفّر أمانًا ومرونة في إدارة البيانات.

models.py

python
from datetime import datetime from flask_sqlalchemy import SQLAlchemy db = SQLAlchemy() class URL(db.Model): id = db.Column(db.Integer, primary_key=True) original_url = db.Column(db.String(2048), nullable=False) short_url = db.Column(db.String(10), unique=True, nullable=False) created_at = db.Column(db.DateTime, default=datetime.utcnow) visit_count = db.Column(db.Integer, default=0)

هذا النموذج يمثّل الرابط المختصر، ويحتوي على عدد النقرات، التاريخ، والرابط الأصلي، بالإضافة إلى المفتاح الأساسي.


3. إعداد واجهة المستخدم باستخدام Jinja وBootstrap

لكي يكون التطبيق صالحًا للاستخدام العام، من الضروري توفير واجهة استخدام مرنة وسلسة. يمكن استخدام إطار Bootstrap لتصميم واجهات متجاوبة.

templates/index.html

html
{% extends "base.html" %} {% block content %} <div class="container mt-5"> <h2>اختصر رابطكh2> <form method="POST"> {{ form.hidden_tag() }} <div class="form-group"> {{ form.original_url.label }} {{ form.original_url(class="form-control") }} div> <button type="submit" class="btn btn-primary mt-2">اختصارbutton> form> {% if short_url %} <div class="alert alert-success mt-4"> رابطك المختصر: <a href="{{ url_for('redirect_to_url', short_url=short_url, _external=True) }}">{{ url_for('redirect_to_url', short_url=short_url, _external=True) }}a> div> {% endif %} div> {% endblock %}

4. توليد الروابط المختصرة بشكل آمن وفريد

ينبغي أن تكون الروابط المختصرة فريدة وعشوائية لتفادي التضارب، ويمكن استخدام مكتبة secrets لتوليد رموز يصعب تخمينها:

utils.py

python
import string import secrets from app.models import URL def generate_short_url(length=6): characters = string.ascii_letters + string.digits while True: short_url = ''.join(secrets.choice(characters) for _ in range(length)) if not URL.query.filter_by(short_url=short_url).first(): break return short_url

5. إدارة المسارات والردود HTTP

المسارات تتحكم في تدفّق البيانات بين المستخدم والتطبيق، ويجب تقسيمها بطريقة تنظّم المعالجة المنطقية:

routes.py

python
from flask import render_template, request, redirect, url_for, flash from app import db from app.forms import URLForm from app.models import URL from app.utils import generate_short_url from flask import Blueprint bp = Blueprint('main', __name__) @bp.route('/', methods=['GET', 'POST']) def index(): form = URLForm() short_url = None if form.validate_on_submit(): original_url = form.original_url.data short_url = generate_short_url() new_link = URL(original_url=original_url, short_url=short_url) db.session.add(new_link) db.session.commit() return render_template('index.html', form=form, short_url=short_url) @bp.route('/') def redirect_to_url(short_url): link = URL.query.filter_by(short_url=short_url).first_or_404() link.visit_count += 1 db.session.commit() return redirect(link.original_url) @bp.route('/stats') def stats(): links = URL.query.order_by(URL.visit_count.desc()).all() return render_template('stats.html', links=links)

6. تتبع وتحليل الإحصائيات

من أجل مراقبة أداء الروابط، يجب توفير لوحة إحصائية توضح عدد النقرات على كل رابط.

templates/stats.html

html
{% extends "base.html" %} {% block content %} <div class="container mt-5"> <h2>إحصائيات الروابطh2> <table class="table table-bordered"> <thead> <tr> <th>الرابط الأصليth> <th>الرابط المختصرth> <th>عدد النقراتth> <th>تاريخ الإنشاءth> tr> thead> <tbody> {% for link in links %} <tr> <td>{{ link.original_url }}td> <td><a href="{{ url_for('main.redirect_to_url', short_url=link.short_url, _external=True) }}">{{ link.short_url }}a>td> <td>{{ link.visit_count }}td> <td>{{ link.created_at.strftime('%Y-%m-%d') }}td> tr> {% endfor %} tbody> table> div> {% endblock %}

7. إعداد بيئة التطوير والتشغيل

لضمان تشغيل مستقر للتطبيق على مختلف الأنظمة، يجب اعتماد بيئة افتراضية وربطها بملف متطلبات.

requirements.txt

nginx
Flask Flask-SQLAlchemy Flask-WTF WTForms

run.py

python
from app import create_app app = create_app() if __name__ == "__main__": app.run(debug=True)

__init__.py

python
from flask import Flask from app.models import db from app.routes import bp def create_app(): app = Flask(__name__) app.config['SECRET_KEY'] = 'your-secret-key' app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///urls.db' app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False db.init_app(app) app.register_blueprint(bp) with app.app_context(): db.create_all() return app

8. تحسين الحماية والأداء

لحماية التطبيق من الاستخدام غير المشروع:

  • يجب استخدام HTTPS في النشر.

  • تحديد الطول الأقصى للروابط المُدخلة.

  • منع إدخال روابط ضارة من خلال فحصها.

  • تطبيق قيود على عدد الطلبات (rate limiting) باستخدام أدوات مثل Flask-Limiter.

  • استخدام headers مثل Content-Security-Policy وX-Frame-Options.


9. نشر التطبيق على الإنترنت

يمكن نشر التطبيق عبر منصات مثل Render, Heroku, أو خوادم مثل Gunicorn مع NGINX. الخطوات الأساسية تشمل:

  • إعداد ملف Procfile (لـ Heroku).

  • استخدام gunicorn كمخدم تطبيق.

  • تحميل المتطلبات عبر pip install -r requirements.txt.

  • إجراء ترحيلات قاعدة البيانات.


جدول توضيحي للوظائف والمكوّنات

الوظيفة الملف المسؤول الوصف العام
تعريف قاعدة البيانات models.py يحتوي على نموذج URL للروابط والزيارات
توليد روابط مختصرة utils.py يُنتج رموزًا فريدة باستعمال خوارزمية تعتمد على secrets
صفحة إدخال الرابط index.html واجهة مستخدم تطلب الرابط الأصلي وتعرض المختصر
تتبّع النقرات redirect_to_url() يُسجّل عدد مرات النقر على الرابط المختصر
عرض الإحصائيات stats.html جدول يعرض الروابط وعدد زياراتها
المسارات routes.py تنظيم الوظائف والربط بين الواجهات الخلفية والأمامية
تهيئة التطبيق __init__.py إعداد Flask وربط قاعدة البيانات والمخططات
تشغيل التطبيق run.py نقطة البدء لتشغيل التطبيق
المتطلبات requirements.txt تحديد المكتبات اللازمة للتشغيل

المراجع

  1. Flask Documentation – https://flask.palletsprojects.com

  2. SQLAlchemy ORM Tutorial – https://docs.sqlalchemy.org/en/20/orm/tutorial.html