جانغو هو إطار عمل عالي المستوى لتطوير الويب بلغة Python يعطي الأولوية للكفاءة والأمان وقابلية التوسع، وليس من المستغرب أن برز Django في الآونة الأخيرة بين أكثر 10 أطر تطوير ويب شيوعًا، فهو يتبع نهج “البطاريات المضمنة”، مما يوفر مجموعة شاملة من الأدوات والمكتبات والميزات المبتكرة للتطوير السريع.
يشتهر Django بمتانته وتوثيقه الممتاز وميزاته المضمنة مثل رسم الخرائط الارتباطية للكائنات (ORM) والمصادقة وواجهة الإدارة. تتيح بنية Django، إلى جانب ميزات مثل التخزين المؤقت وتجميع اتصالات قاعدة البيانات ودعم البرامج الوسيطة، إمكانية تطوير تطبيقات ويب قوية وفعالة.
إيجابيات استخدام Django لتطوير ويب
إن قوة Django وتعدد استخداماته ودعمه المجتمعي الهائل من بين أمور أخرى، تجعله خيارًا ممتازًا لإنشاء مدونة بغض النظر عن حجم المدونة التي سيتم إنشاؤها، يعد Django مناسبًا بشكل مثالي لأنه يسمح لك بالتركيز على إنشاء محتوى جذاب وصياغة مدونة فريدة من نوعها. الخبرات مع الاستفادة من إطار تطوير الويب القوي والناضج.
توفر هذه المقالة دليلاً شاملاً حول تسخير إمكانات Django لإنشاء تطبيق مدونة أنيق وعملي.
المتطلبات الأساسية
قبل الغوص في التفاصيل، من الضروري التأكد من أنك على دراية بالتقنيات التالية مثبتة على جهازك المحلي لاتباع هذا الدليل بفعالية:
- المعرفة الأساسية بـ HTML/CSS
- إتقان متوسط المستوى في إطار تطوير الويب Python و Django
- تثبيت Virtualenv
معلومات حول حول تطبيق المدونة
نحن نعمل على إنشاء تطبيق ويب بسيط ولكنه عملي لنموذج تطبيق المدونة والذي يسمح لنا بإنشاء مواضيع ونشرها.
تتكون من صفحة رئيسية تجمع كل منشورات المدونة في صفحة واحدة بترتيب تنازلي، ويتم تمثيل كل مشاركة بصورة مصغرة وعنوان و محتوى مختصر.
يؤدي النقر على منشور من الصفحة الرئيسية إلى إعادة التوجيه إلى “صفحة تفاصيل” و الذي تحتوي على تفاصيل من منشور مدونة واحد فقط، وتتضمن العنوان الكامل والصورة المميزة والنص الأساسي بالكامل.
يركز تصميم المدونة على البساطة وسهولة القراءة، مما يسمح للمحتوى بأن يحتل مركز الصدارة. فهو يوفر واجهة مستخدم نظيفة وبديهية، مما يسهل على الزائرين تصفح المشاركات وقراءة المقالات كاملة.
الخطوة 1: إعداد مشروع جانغو
لنبدأ سريعًا بإنشاء بيئة افتراضية لتطبيق مدونتنا باستخدام الأمر virtualenv
.
virtualenv blogvenv
ينشئ هذا الأمر بيئة افتراضية، لتمكين تطبيقنا من الحصول على بيئة معزولة ونظيفة، ويجعل إدارة الحزم والتبعيات أسهل ويقلل الوقت والجهد المبذول في تصحيح الأخطاء.
بشكل عام، يؤدي إنشاء بيئات افتراضية للمشاريع/التطبيقات الفردية إلى تعزيز ممارسات التطوير الجيدة وتحسين تنظيم المشروع، مما يسهل صيانة مشروعك والتعاون فيه.
blogvenv\scripts\activate
الآن بعد أن أصبحنا في بيئتنا الافتراضية الجديدة، فلنقم بتثبيت Django و Pillow (حزمة التعامل مع الصور ومعالجتها).
قم بتشغيل الكود أدناه مع فصل Django و Pillow بمسافة لتثبيت كلا التطبيقين باستخدام أمر واحد.
pip install django pillow
يمكننا الآن إنشاء مشروع مدونتنا باستخدام أمر “Django-admin
“.
django-admin startproject blog
يمكننا الآن إنشاء تطبيق “المدونة”.
python manage.py startapp blogapp
أضف الآن تطبيق المدونة إلى قائمة INSTALLED_APPS
في Settings.py
.
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'blogapp'
]
الخطوة 2: قم بإنشاء نموذج منشور المدونة، وقم بتسجيله في لوحة تحكم المشرف
سنقوم الآن بإعداد جداول قاعدة البيانات للتعامل مع أجزاء مختلفة من منشورات مدونتنا models.py
.
from django.db import models
from django.urls import reverse
class Post(models.Model):
title = models.CharField(max_length=128)
body = models.TextField()
headline = models.TextField()
image = models.ImageField(default = "default.jpg", upload_to = "Posts-Images")
slug = models.SlugField(null=False, unique=True)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('detail', kwargs={'slug': self.slug})
يمكننا الآن تسجيل نموذج Post
في لوحة تحكم مسؤول Django وتحديد الشكل الذي نريد أن تظهر به منشوراتنا أيضًا في ملف admin.py
.
from django.contrib import admin
from blogapp.models import Post
class BlogAdmin(admin.ModelAdmin):
list_display = ['title', 'body', 'headline', 'image']
prepopulated_fields = {'slug': ('title',)}
admin.site.register(Post, BlogAdmin)
الخطوة 3: إعداد محرك القالب وعرض الملفات الثابتة وملفات الوسائط
لإعداد محرك القالب، قم بإنشاء دليل جديد يسمى “templates” في دليل المدونة.
بعد ذلك قم بربط دليل “templates”، والذي سيكون موقع قوالب HTML الخاصة بنا، بمحرك قالب Django داخل ملف الإعدادات Settings.py
.
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [BASE_DIR/ 'templates'],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
بالنسبة لخدمة الملفات الثابتة، نقوم بإنشاء دليل باسم “static” في دليل المدونة.
الآن في ملف settings.py
:
STATIC_URL = 'static/'
STATIC_ROOT = 'BASE_DIR/assets'
STATICFILES_DIRS = [
BASE_DIR/'static'
]
الآن بالنسبة لتخزين ملفات الوسائط في مدونتنا، سنضيف MEDIA_URL
و MEDIA_ROOT
في ملف الإعدادات.
MEDIA_URL = '/media/'
MEDIA_ROOT = BASE_DIR/'media'
الخطوة 4: إنشاء القوالب لاستخدامها
بالنسبة لتطبيق blogapp، نحتاج إلى قالبين، الأول لصفحة Index.html
التي تجمع كل منشورات مدونتنا و صفحة Detail.html
، التي تعرض منشورًا واحدًا.
لتسهيل العمل، سنقوم أولاً بإنشاء قالب أصلي لـ base.html
حتى نتمكن من توسيعه من ملف Index.html
و detail.html
لتجنب التكرار ولإعادة استخدام الكود الخاص بنا بشكل صحيح.
قم بكتابة الكود التالي في ملف base.html
:
{% load static %}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Blog App</title>
<link
rel="stylesheet"
type="text/css"
href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css"
integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65"
crossorigin="anonymous">
<link rel="stylesheet" type="text/css" href="../static/style.css">
<link rel="stylesheet" type="text/css" href="https://use.fontawesome.com/releases/v5.7.2/css/all.css">
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<div class="container-fluid">
<a class="navbar-brand" href="{% url 'home' %}">BlogApp</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="#">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Community</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Contribute</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">About</a>
</li>
</ul>
<form class="d-flex">
<input class="form-control me-2" type="search" placeholder="Search" aria-label="Search">
<button class="btn btn-outline-success" type="submit">Search</button>
</form>
</div>
</div>
</nav>
{% block content %}
{% endblock content %}
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/js/bootstrap.bundle.min.js">
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js">
</body>
</html>
قم بكتابة الكود التالي في ملف Index.html
:
{% extends "base.html" %}
{% load static %}
{% block content %}
{% for post in posts %}
<div class="container mt-4 posts">
<div class="card p-3">
<div class="row">
<div class="col-md-4">
<div class="position-relative snipimage">
<a href="{{post.get_absolute_url}}"><img src="{{post.image.url}}" class="rounded img-fluid w-100 img-responsive"></a>
</div>
</div>
<div class="col-md-8">
<div class="mt-2">
<div class="d-flex justify-content-between align-items-center">
<a href="{{post.get_absolute_url}}"><h5 class="mb-1">{{post.title}}</h5></a>
<span><i class="fa fa-heart text-danger"></i> </span>
</div>
<div class="d-flex justify-content-md-start justify-content-between views-content mt-2">
<div class="d-flex flex-row align-items-center">
<i class="fa fa-eye"></i>
<span class="ms-1 views">570</span>
</div>
<div class="d-flex flex-row align-items-center ms-2">
<i class="fa fa-heart"></i>
<span class="ms-1 views">4565</span>
</div>
</div>
<div class="d-flex flex-row mt-3">
<img src="{% static 'user.jpg' %}" width="50" class="rounded-circle">
<div class="ms-2 d-flex flex-column">
<div class="d-flex flex-row align-items-center">
<h6>Clarkson Pwaveino</h6>
<span class="dots"></span>
</div>
<span class="days-ago">2 days ago</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
{% endfor %}
{% endblock content %}
قم بكتابة الكود التالي في ملف detail.html
:
{% extends "base.html" %}
{% block content %}
<div class="container">
<div class="jumbotron">
<h1 class="display-4">{{post.title}}</h1>
<img src="{{post.image.url}}" class="img-fluid" alt="...">
<p class="lead">{{post.headline}}</p>
<hr class="my-4">
<p>{{post.body}}</p>
<p class="lead">
<a class="jumbo btn btn-outline-success" href="{% url 'home' %}" role="button">Go back</a>
</p>
</div>
</div>
{% endblock content %}
لإضافة القليل من الجماليات الآن، فلنقم بإنشاء ملف style.css في الدليل الثابت وأضف الكود التالي:
body{
background-color:#1e1c2a;
}
.posts{
margin-top: 150px;
}
.card{
border:none;
background-color:#252836;
color:#fff;
border-radius:12px;
}
.user-timing{
right:9px;
bottom:9px;
color:#fff;
}
.views-content{
color:#606271;
}
.views{
font-size:12px;
}
a{
text-decoration: none;
color: #fff;
}
a:hover{
text-decoration: none;
color: #999;
transition: .5s;
}
.dots{
display:flex;
height:10px;
width:10px;
background-color:green;
border-radius:50%;
margin-left:5px;
margin-bottom:6px;
}
.days-ago{
margin-top: -10px;
color: #606271;
}
.snipimage img{
height: 200px;
}
.jumbotron{
margin-top: 120px;
color: #fff;
}
.jumbo{
margin-top: 45px;
}
.img-fluid{
max-width: 70%;
}
الخطوة 5: إنشاء العروض الضرورية ومسارات URL
دعونا نمضي قدمًا وننشئ العرض لإلقاء نظرة على مدونتنا بشكل صحيح.
Views.py
from django.shortcuts import render, get_object_or_404
from .models import Post
def index(request):
posts = Post.objects.all()
context = {'posts': posts}
return render(request, "index.html", context)
def detail(request, slug):
post = get_object_or_404(Post, slug=slug)
context = {'post': post}
return render(request, "detail.html", context)
سنقوم الآن بإنشاء ملف urls.py
جديد لإنشاء مسارات URL لعرضنا.
from django.urls import path
from . import views
urlpatterns = [
path('', views.index, name = "home"),
path('<str:slug>', views.detail, name = "detail"),
]
في ملف urls.py
الموجود في مشروع المدونة ، سنقوم بتضمين مسارات URL من blogpp وسنتضمن MEDIA_URL
و MEDIA_ROOT
المحددين مسبقًا في ملف setting.py
.
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('blogapp.urls')),
]
urlpatterns += static(settings.MEDIA_URL, document_root = settings.MEDIA_ROOT)
الخطوة 6: ترحيل قاعدة البيانات، وإنشاء مستخدم متميز، وملء قاعدة البيانات، واختبارها
سنقوم هنا بإجراء عمليات ترحيل لقاعدة البيانات.
python manage.py makemigrations
python manage.py migrate
قم بإنشاء مستخدم متميز يمكنه الوصول إلى لوحة تحكم إدارة موقع Django.
python manage.py createsuperuser
للاختبار، سنبدأ بتشغيل خادم الويب.
python manage.py runserver
الآن سنقوم بملء قاعدة البيانات الخاصة بنا بثلاث مشاركات.
تهانينا! لقد تعلمت بنجاح كيفية إنشاء مدونة في Django في أقل من 30 دقيقة. قد يبدو إنشاء مدونة من الصفر أمرًا شاقًا، ولكن الآن لديك المعرفة والثقة اللازمة للبدء في تصميم تطبيقات الويب الخاصة بك باستخدام Django.
تذكر أن هذه مدونة أساسية جدًا ويمكنك توسيع وظائفها عن طريق إضافة ميزات رائعة أخرى مثل؛ نظام التعليق، والعلامات، والفئات، وترقيم الصفحات، ووظيفة البحث، والمشاركة الاجتماعية، وملفات تعريف المستخدمين، وغيرها الكثير.
اكتشاف المزيد من بايثون العربي
اشترك للحصول على أحدث التدوينات المرسلة إلى بريدك الإلكتروني.