Xuất tệp là một tính năng thường xuyên xảy ra nơi người dùng có thể lấy dữ liệu của họ ra.
Là phần phụ trợ, ứng dụng Django của tôi có thể giúp tôi xuất tệp docx bằng cách sử dụng thư viện có tên python-docx.
Cài đặt python-docx và nhận kiến thức cơ bản
Cài đặt python-docx cực kỳ đơn giản với một lệnh:
pip cài đặt python-docx
Nếu bạn đang làm việc trên Docker và có một tập tin requirement.txt nơi bạn thêm tất cả libs của bạn trên đó, đừng quên thêm “python-docx” phiên bản với nó.
Bạn có thể tải chính xác phiên bản đã cài đặt bằng cách gọi lệnh “pip freeze” để lấy danh sách tên và phiên bản libs, sau đó tìm phiên bản python-docx.
python-docx == 0,8.10
Trước khi đi vào chi tiết về cách chúng tôi tạo chế độ xem để xuất tệp docx bằng python-docx. Sẽ hữu ích nếu bạn có thể xem qua tài liệu chính thức của python-docx trước.
Thực hiện chế độ xem để xuất tệp docx
Như thường lệ, để tạo một API để tải xuống, chúng tôi viết một chế độ xem chỉ cho phép phương thức GET.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | <span class="token keyword">class</span> <span class="token class-name">ExportDocx</span> <span class="token punctuation">(</span> APIView <span class="token punctuation">)</span> <span class="token punctuation">:</span> <span class="token keyword">def</span> <span class="token function">get</span> <span class="token punctuation">(</span> self <span class="token punctuation">,</span> request <span class="token punctuation">,</span> <span class="token operator">*</span> args <span class="token punctuation">,</span> <span class="token operator">**</span> kwargs <span class="token punctuation">)</span> <span class="token punctuation">:</span> <span class="token comment"># create an empty document object</span> document <span class="token operator">=</span> Document <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token comment"># save document info</span> <span class="token builtin">buffer</span> <span class="token operator">=</span> io <span class="token punctuation">.</span> BytesIO <span class="token punctuation">(</span> <span class="token punctuation">)</span> document <span class="token punctuation">.</span> save <span class="token punctuation">(</span> <span class="token builtin">buffer</span> <span class="token punctuation">)</span> <span class="token comment"># save your memory stream</span> <span class="token builtin">buffer</span> <span class="token punctuation">.</span> seek <span class="token punctuation">(</span> <span class="token number">0</span> <span class="token punctuation">)</span> <span class="token comment"># rewind the stream</span> <span class="token comment"># put them to streaming content response </span> <span class="token comment"># within docx content_type</span> response <span class="token operator">=</span> StreamingHttpResponse <span class="token punctuation">(</span> streaming_content <span class="token operator">=</span> <span class="token builtin">buffer</span> <span class="token punctuation">,</span> <span class="token comment"># use the stream's content</span> content_type <span class="token operator">=</span> <span class="token string">'application/vnd.openxmlformats-officedocument.wordprocessingm'</span> <span class="token punctuation">)</span> response <span class="token punctuation">[</span> <span class="token string">'Content-Disposition'</span> <span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token string">'attachment;filename=Test.docx'</span> response <span class="token punctuation">[</span> <span class="token string">"Content-Encoding"</span> <span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token string">'UTF-8'</span> <span class="token keyword">return</span> response |
Sau khi tạo một tài liệu trống, chúng ta cần lưu chúng và gửi nó đến phản hồi. Python-docx có phương thức Document.save () chấp nhận một luồng thay vì tên tệp. Do đó, chúng ta có thể khởi tạo một đối tượng io.BytesIO () để lưu thông tin tài liệu, sau đó kết xuất nó cho người dùng.
Chúng tôi sử dụng StreamingHttpResponse để tải dữ liệu nặng và sử dụng content_type “application / vnd.openxmlformats-officedocument.wordprocessingm” cho tệp docx.
Tại thời điểm này, chúng tôi có thể tải xuống tên tệp .docx Test.docx và xem nội dung trống trong đó.
Xây dựng nội dung chi tiết cho tài liệu
Sau bước tải xuống tệp docx trống, chúng tôi bắt đầu xây dựng nội dung cho docx. Mời bạn theo dõi tài liệu của python-docx.
Về cơ bản, bạn có thể thêm văn bản tiêu đề bằng cách sử dụng phương thức “document.add_heading ()” và một số đoạn văn bằng cách sử dụng phương thức “document.add_paragraph ()”.
Nếu bạn muốn định kiểu văn bản, bạn có thể thêm_run vào một đoạn văn.
Ví dụ: tôi đã tạo phương thức build_document () để xây dựng tất cả nội dung trong tài liệu:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <span class="token keyword">def</span> <span class="token function">build_document</span> <span class="token punctuation">(</span> self <span class="token punctuation">)</span> <span class="token punctuation">:</span> document <span class="token operator">=</span> Document <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token comment"># add a header</span> document <span class="token punctuation">.</span> add_heading <span class="token punctuation">(</span> <span class="token string">"This is a header"</span> <span class="token punctuation">)</span> <span class="token comment"># add a paragraph</span> document <span class="token punctuation">.</span> add_paragraph <span class="token punctuation">(</span> <span class="token string">"This is a normal style paragraph"</span> <span class="token punctuation">)</span> <span class="token comment"># add a paragraph within an italic text then go on with a break.</span> paragraph <span class="token operator">=</span> document <span class="token punctuation">.</span> add_paragraph <span class="token punctuation">(</span> <span class="token punctuation">)</span> run <span class="token operator">=</span> paragraph <span class="token punctuation">.</span> add_run <span class="token punctuation">(</span> <span class="token punctuation">)</span> run <span class="token punctuation">.</span> italic <span class="token operator">=</span> <span class="token boolean">True</span> run <span class="token punctuation">.</span> add_text <span class="token punctuation">(</span> <span class="token string">"text will have italic style"</span> <span class="token punctuation">)</span> run <span class="token punctuation">.</span> add_break <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token keyword">return</span> document |
thì tôi sẽ thay thế việc tạo một tài liệu trống trong dạng xem bằng cách:
document = self.build_document ()
Và đây là kết quả xuất cho bây giờ:
Xây dựng nội dung html bằng cách sử dụng HTMLParser trong tài liệu
Về cơ bản, tôi có thể xuất tệp docx trong nội dung trong đó. Fistly, tôi chỉ cần thêm nó vào trong đoạn văn:
1 2 3 | <span class="token comment"># add paragraph for html content</span> document <span class="token punctuation">.</span> add_paragraph <span class="token punctuation">(</span> <span class="token string">"<p>Nice to see Prep note 2</p>n<ul>n<li>Prep note 2 content 1</li>n<li>Prep note 2 content 2</li>n</ul>"</span> <span class="token punctuation">)</span> |
Nhưng có một màn hình kỳ lạ khi tôi lưu trường dưới dạng html.
Vì vậy, tôi cần tìm ra cách để chuyển đổi nội dung HTML thành văn bản và giữ cho nó kiểu cơ bản như in nghiêng, in đậm hoặc dấu đầu dòng, như sau:
1 2 3 4 | Nice to see Prep note 2 ● Prep note 2 content 1 ● Prep note 2 content 2 |
Sau một số nghiên cứu, tôi biết có một python lib có tên “ html.parser – Phân tích cú pháp HTML và XHTML đơn giản ” và làm theo một ví dụ để tạo một lớp có tên DocumentHTMLParser để xử lý nó như sau:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | <span class="token keyword">from</span> html <span class="token punctuation">.</span> parser <span class="token keyword">import</span> HTMLParser <span class="token keyword">class</span> <span class="token class-name">DocumentHTMLParser</span> <span class="token punctuation">(</span> HTMLParser <span class="token punctuation">)</span> <span class="token punctuation">:</span> <span class="token triple-quoted-string string">""" Document Within HTML Parser """</span> <span class="token keyword">def</span> <span class="token function">__init__</span> <span class="token punctuation">(</span> self <span class="token punctuation">,</span> document <span class="token punctuation">)</span> <span class="token punctuation">:</span> <span class="token triple-quoted-string string">""" Override __init__ method """</span> HTMLParser <span class="token punctuation">.</span> __init__ <span class="token punctuation">(</span> self <span class="token punctuation">)</span> self <span class="token punctuation">.</span> document <span class="token operator">=</span> document self <span class="token punctuation">.</span> paragraph <span class="token operator">=</span> <span class="token boolean">None</span> self <span class="token punctuation">.</span> run <span class="token operator">=</span> <span class="token boolean">None</span> <span class="token keyword">def</span> <span class="token function">add_paragraph_and_feed</span> <span class="token punctuation">(</span> self <span class="token punctuation">,</span> html <span class="token punctuation">)</span> <span class="token punctuation">:</span> <span class="token triple-quoted-string string">""" Custom method where add paragraph and feed """</span> self <span class="token punctuation">.</span> paragraph <span class="token operator">=</span> self <span class="token punctuation">.</span> document <span class="token punctuation">.</span> add_paragraph <span class="token punctuation">(</span> <span class="token punctuation">)</span> self <span class="token punctuation">.</span> run <span class="token operator">=</span> self <span class="token punctuation">.</span> paragraph <span class="token punctuation">.</span> add_run <span class="token punctuation">(</span> <span class="token punctuation">)</span> self <span class="token punctuation">.</span> feed <span class="token punctuation">(</span> html <span class="token punctuation">)</span> <span class="token keyword">def</span> <span class="token function">handle_starttag</span> <span class="token punctuation">(</span> self <span class="token punctuation">,</span> tag <span class="token punctuation">,</span> attrs <span class="token punctuation">)</span> <span class="token punctuation">:</span> <span class="token triple-quoted-string string">""" Override handle_starttag method """</span> self <span class="token punctuation">.</span> run <span class="token operator">=</span> self <span class="token punctuation">.</span> paragraph <span class="token punctuation">.</span> add_run <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token keyword">if</span> tag <span class="token keyword">in</span> <span class="token punctuation">[</span> <span class="token string">"ul"</span> <span class="token punctuation">]</span> <span class="token punctuation">:</span> self <span class="token punctuation">.</span> run <span class="token punctuation">.</span> add_break <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token keyword">if</span> tag <span class="token keyword">in</span> <span class="token punctuation">[</span> <span class="token string">"li"</span> <span class="token punctuation">]</span> <span class="token punctuation">:</span> self <span class="token punctuation">.</span> run <span class="token punctuation">.</span> add_text <span class="token punctuation">(</span> <span class="token string">u' ● '</span> <span class="token punctuation">)</span> <span class="token keyword">def</span> <span class="token function">handle_endtag</span> <span class="token punctuation">(</span> self <span class="token punctuation">,</span> tag <span class="token punctuation">)</span> <span class="token punctuation">:</span> <span class="token triple-quoted-string string">""" Override handle_endtag method """</span> <span class="token keyword">if</span> tag <span class="token keyword">in</span> <span class="token punctuation">[</span> <span class="token string">"li"</span> <span class="token punctuation">]</span> <span class="token punctuation">:</span> self <span class="token punctuation">.</span> run <span class="token punctuation">.</span> add_break <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token keyword">def</span> <span class="token function">handle_data</span> <span class="token punctuation">(</span> self <span class="token punctuation">,</span> data <span class="token punctuation">)</span> <span class="token punctuation">:</span> <span class="token triple-quoted-string string">"""Override handle_data method"""</span> self <span class="token punctuation">.</span> run <span class="token punctuation">.</span> add_text <span class="token punctuation">(</span> data |
Nói chung, đoạn mã trên, chúng ta sẽ ghi đè hàm trong lớp HTMLParser, sau đó sử dụng chạy đoạn văn thành kiểu tùy chỉnh bằng cách bật thẻ bắt đầu. Nếu thẻ cần ngắt ở cuối thì chúng tôi thêm dấu ngắt cho nó.
Sau đó, tôi sử dụng lớp tùy chỉnh này trong chế độ xem của mình để xử lý nội dung html:
1 2 3 4 5 6 7 8 9 10 11 12 13 | <span class="token keyword">def</span> <span class="token function">build_document</span> <span class="token punctuation">(</span> self <span class="token punctuation">,</span> recipes <span class="token punctuation">)</span> <span class="token punctuation">:</span> <span class="token triple-quoted-string string">"""Build content document"""</span> document <span class="token operator">=</span> Document <span class="token punctuation">(</span> <span class="token punctuation">)</span> doc_html_parser <span class="token operator">=</span> DocumentHTMLParser <span class="token punctuation">(</span> document <span class="token punctuation">)</span> <span class="token comment"># like above for header, paragraph</span> <span class="token comment"># with html content, call method add_paragraph_and_feed tui build content</span> html_content <span class="token operator">=</span> <span class="token string">"<p>Nice to see Prep note 2</p>n<ul>n<li>Prep note 2 content 1</li>n<li>Prep note 2 content 2</li>n</ul>"</span> doc_html_parser <span class="token punctuation">.</span> add_paragraph_and_feed <span class="token punctuation">(</span> html_content <span class="token punctuation">)</span> <span class="token keyword">return</span> document |
Và đây là kết quả trên docx của nội dung html:
Xuất trong ứng dụng Django rất thú vị và Python cũng có nhiều thư viện hữu ích để xử lý định dạng nội dung.
Chúng ta chỉ xem qua một ví dụ đơn giản về xuất tệp docx trong ứng dụng Django. Nếu bạn biết cách khác tốt hơn và / hoặc bất kỳ điều gì có vẻ không ổn, vui lòng cho tôi biết trong phần bình luận.
Như thường lệ,nguồn gốc của bài đăng này là trên blog cá nhân của tôi
Cảm ơn bạn,
BeautyOnCode