تولید خودکار فایل Word در جنگو
در بسیاری از پروژههای تحت وب، به ویژه سیستمهای مدیریتی و اتوماسیون اداری، نیاز به تولید فایلهای قابل دانلود از دادههای ذخیرهشده در پایگاهداده است. یکی از رایجترین این خروجیها، فایلهای Word با فرمت .docx میباشد که در گزارشگیری، تولید قراردادها، فاکتورها و مستندات رسمی به کار برده میشود. در فریمورک Django به علت ساختار منعطف و قابلیت توسعه بالا، میتوان بهراحتی چنین قابلیتی را اجرا کرد.
پیشنهاد نویسنده: پروژه سایت دایرکتوری لینک با Python + Django
تولید فایل داکیومنت با جنگو
معرفی مسئله
در بسیاری از سیستمهای واقعی مانند:
- سیستمهای گزارشگیری.
- CRM.
- تولید قرارداد.
- تولید مستندات.
نیاز داریم دادههای دیتابیس به فایل Word تبدیل کنیم.
فریمورک جنگو بهتنهایی همچنین قابلیتی را ندارد، اما با انجام دادن چندین کار، میتوانید که همچین سیستم قدرتمند و حرفهای را بسازید.
معماری سیستم
User → CreateView → Form → Model → DOCX Generator → File Output
هر بخش وظیفه مشخصی دارد:
- Model: ذخیره داده.
- Form: دریافت ورودی از کاربر.
- View: کنترل جریان.
- DOCX Creator: ساخت فایل Word.
مدل داده models.py
مدل ما ساختار محتوای Word را تعریف میکند.
from django.db import models from django.core.validators import MinValueValidator, MaxValueValidator class DocumentCreator(models.Model): heading_text = models.CharField(max_length=200) heading_level = models.IntegerField(validators=[MinValueValidator(1), MaxValueValidator(6)]) paragraph_text = models.TextField(blank=True)
بعد از ساخت مدلها در Django، برای اعمال تغییرات در دیتابیس ابتدا باید آنها را به migration تبدیل نماییم. برای این کار از دستور زیر استفاده کنید:
python manage.py makemigrations
این دستور تغییرات مدلها را شناسایی میکند و فایلهای migration مربوطه را ایجاد میکند.
در مرحلهی بعد، برای اعمال این تغییرات روی دیتابیس از دستور زیر استفاده کنید:
python manage.py. migration
اکنون مدل شما آماده به استفاده میباشد.
توضیح مدل (models.py)
این مدل ساختار دادهای را مشخص میکند که در نهایت به فایل Word تبدیل میشود. هر رکورد شامل یک عنوان، سطح عنوان و متن پاراگراف است.
اولین فیلد این مدل heading_text برای ذخیره عنوان و نام فایل استفاده میشود و CharField است، با گذاشتن عبارت max_length=200 مشخص میکنیم که حداکثر کاراکتری که میتوان برای این فیلد گذاشت، 200 کاراکتر است.
فیلد heading_level تعیین میکند که عنوان در فایل Word چه سطحی داشته باشد (از 1 تا 6). برای این فیلد از Validator استفاده میشود تا مقدار خارج از این بازه وارد نگردد و ساختار فایل Word استاندارد باقی بماند.
فیلد paragraph_text متن اصلی هر بخش را نگه میدارد و از نوع TextField است تا امکان ذخیره متنهای طولانی وجود داشته باشد. با گذاشتن blank=True میتوان این فیلد را خالی هم نگه داشت.
در نهایت تابع __str__ سبب میشود تا در هنگام نمایش این مدل در پنل مدیریت Django یا محیطهای دیگر، عنوان آن بهجای نام پیشفرض نمایش داده شود.
فرم ورودی forms.py
from django import forms
from .models import documet_creater
class DocumentCreatorForm(forms.ModelForm):
class Meta:
model = documet_creater
fields = ['heading_text', 'heading_level', 'paragraph_text']
نکته: این فایل به صورت پیشفرض در جنگو نیست، ابتدا باید این فایل را در app بسازیم.
توضیح فرم (forms.py)
این بخش مربوط به فرم در Django است و برای دریافت اطلاعات از کاربر و اتصال مستقیم آن به مدل استفاده میشود.
در اینجا یک ModelForm ساخته شده که به مدل documet_creater متصل میشود. این یعنی فریمورک جنگو بهصورت خودکار فیلدهای فرم را براساس فیلدهای مدل تولید مینماید.
در کلاس Meta مشخص میشود که این فرم مربوط به کدام مدل است و چه فیلدهایی باید در فرم نمایش داده شوند. در اینجا سه فیلد heading_text، heading_level و paragraph_text انتخاب شدهاند تا کاربر بتواند عنوان، سطح عنوان و متن مربوط به هر بخش را وارد نماید.
در نتیجه این فرم نقش رابط بین کاربر و دیتابیس را دارد و دادههای وارد شده را آماده ذخیره در مدل میکند.
ساخت فایل Word (docs_creators.py)
در ابتدا کتابخانه زیر را با استفاده از دستور زیر نصب نمایید:
pip install python-docx
کد زیر فایلهای داکیومنت را میسازد:
from pathlib import Path
from docx import Document
def create_doc_from_instance(instance, output_dir: Path):
if not instance:
return None
doc = Document()
try:
level = int(instance.heading_level)
except Exception:
level = 1
level = max(1, min(level, 6))
heading = str(instance.heading_text or "document")
doc.add_heading(heading, level=level)
paragraph_text = instance.paragraph_text or ""
for line in paragraph_text.splitlines():
if line.strip():
doc.add_paragraph(line)
safe_name = "".join(
c for c in heading if c.isalnum() or c in (" ", "_", "-")
).strip()
output_dir = Path(output_dir)
output_dir.mkdir(parents=True, exist_ok=True)
file_path = output_dir / f"{safe_name}.docx"
doc.save(file_path)
return file_path
در این بخش فایل .docx ساخته میشود:
- عنوان —-> heading
- متن —-> paragraph
- ذخیره فایل در مسیر مشخص.
نکات مهم:
- جلوگیری از نام فایل خطرناک.
- ساخت پوشه در صورت نبود.
- کنترل level بین 1 تا 6.
نکته: این فایل به صورت پیشفرض در جنگو نیست، ابتدا باید این فایل را در app بسازیم.
توضیح docs_creators.py
این فایل مسئول تبدیل دادههای ذخیرهشده در مدل به یک فایل Word با فرمت .docx میباشد. در واقع منطق اصلی ساخت سند در اینجا قرار دارد.
تابع اصلی این فایل یک instance از مدل را دریافت میکند و براساس اطلاعات آن، یک فایل Word ایجاد میکند. ابتدا یک سند خالی ساخته میشود و سپس عنوان و متن به آن اضافه میگردد.
برای عنوان از heading_text استفاده میشود و سطح آن با heading_level مشخص میشود تا در Word به شکل Heading مناسب نمایش داده شود. سپس متن موجود در paragraph_text به خطوط جداگانه تقسیم شده و هر خط بهعنوان یک پاراگراف مستقل به فایل اضافه میشود.
در مرحله بعد یک نام امن برای فایل ساخته میشود تا کاراکترهای غیرمجاز از آن حذف شوند و مشکلی در ذخیرهسازی فایل به وجود نیاید. سپس مسیر ذخیرهسازی مشخص شده و در صورتی که پوشه مقصد وجود نداشته باشد، بهصورت خودکار ایجاد میشود.
در نهایت فایل با فرمت .docx ذخیره شده و مسیر آن به عنوان خروجی برگردانده میشود. این فرآیند باعث میشود تبدیل دادههای دیتابیس به فایل Word بهصورت کاملاً خودکار انجام شود.
ویو اصلی views.py
from pathlib import Path
from django.views.generic import CreateView
from .models import DocumentCreator
from .forms import DocumentCreatorForm
from .docs_creators import create_doc_from_instance
class DocumentCreatorView(CreateView):
model = DocumentCreator
form_class = DocumentCreatorForm
template_name = "create_document.html"
success_url = "/admin/products/product/"
def form_valid(self, form):
response = super().form_valid(form)
try:
create_doc_from_instance(
self.object,
output_dir=Path("media/docs")
)
except Exception:
pass
return response
جریان کار:
- کاربر فرم را پر میکند.
- داده ذخیره میشود.
- فایل Word ساخته میشود.
نکات امنیتی مهم
جلوگیری از crash برنامه:
try: ... except Exception: pass
جلوگیری از path injection:
safe_name = "".join(c for c in heading if c.isalnum())
محدود کردن heading level
بین 1 تا 6
خروجی نهایی پروژه
بعد از submit فرم:
media/docs/ My_Document.docx
قالب HTML فرم (template)
در این بخش قالب HTML مربوط به فرم ساخت سند در Django قرار دارد. این صفحه وظیفه دارد فرم را به کاربر نمایش دهد و اطلاعات وارد شده را برای پردازش به سرور ارسال کند.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Create Document</title>
</head>
<body>
{% block content %}
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Create Document</button>
</form>
{% endblock %}
</body>
</html>
در این قالب از form.as_p استفاده شده است تا فیلدهای فرم بهصورت خودکار و در قالب پاراگراف نمایش داده شوند. همچنین تگ {% csrf_token %} برای افزایش امنیت فرم و جلوگیری از حملات CSRF ضروری است.
بلوک {% block content %} نیز امکان توسعه قالب و استفاده از inheritance در صفحات دیگر را فراهم میکند و باعث میشود ساختار پروژه قابل توسعهتر و حرفهایتر باشد.
شما میتوانید با استفاده از CSS و فریمورکها و Javascript ظاهر templateهای خود را زیبا کنید.
این نوع پیادهسازیها میتوانند در بسیاری از سیستمهای واقعی مورد استفاده قرار بگیرند و پایهای برای توسعه امکانات پیشرفتهتر باشند. درک این جریان کاری کمک میکند تا دید بهتری نسبت به معماری پروژههای Django و نحوه اتصال آن به ابزارهای خارجی داشته باشیم.
اگر سوالات بیشتری در ارتباط با این موضوع داشتید، حتما در بخش نظرات این نوشته برای ما بنویسید.



















ارسال پاسخ