Setup Mypy for Django projects

After my last post "How to install a LSP server that supports Django" was shared, I got feedback that some fellows tried to install the LSP, but didn't get the autocomplete working as shown in my screenshot. So I continue with this article.

django-extra-attribute

People often miss the detail that the core power of an LSP server comes from the static type checker (or the compiler in case of compiled languages). When you write window. then hit the Tab key, the LSP server starts to suggest the attributes of the window object. But it can only know which attributes the window object has, if the type of the window variable is inferred successfully and correctly. The later job is done by static type checker, or concretely, Mypy.

So, for a Django project, how do you set up Mypy so type inference works? Basically, it's just like adding Mypy for type checking, but with more honesty. I use the word "honesty" because some projects added Mypy but the team members try to get the green "passed" status by making Mypy skip the type checking, ignoring the errors instead of really fixing them.


How to install a LSP server that supports Django

Before, when developing Django-based projects, I often use VS Code. Because VS Code is getting heavier and heavier (the installation is 1 GiB now), I need to move away from it. But the first thing is to find an independent LSP server that works well enough with Django. VS Code comes with Pylance, its LSP server for Python. But Pylance is proprietary, so for another code editor, I need a different solution.

When we do programming, LSP servers are great tools. They help improve productivity by enabling accurate autocomplete in code editors, allowing us to code faster and make less mistakes. They work best with languages having a strong type system (Rust and functional programming languages, like Gleam), because the type system lets us know, at any point, which type a variable has and what members it contains. For dynamic type languages, LSP servers are often based on static type checkers (because both need to draw type information from the source code). For Python, the situation is a bit hard, because Python is so dynamic and flexible that, its type annotations cannot cover all the cases to help type checkers and LSP servers infer the type of variables. It is especially true for Django. At the time of writing, Mypy is the type checker that supports Django the best. It means that, on the LSP server side, we need one that can take advantage of Mypy. Currently, there are many type checkers + LSP servers for Python, most of which are not written in Python:

  • Pyright: Written in TypeScript.

How to Instruct an AI Agent for People Who'd Rather Not Type

I'm a slow typist, so when programming I really need the autocomplete feature, to avoid typing a lot and making typos. When applying AI to my work, a major limitation is that the prompt input box of agent software lacks an autocomplete feature. That means when I want the assistant to fix this function or that function, I have to type out the full function or variable names, or copy them from elsewhere, instead of just typing the first 2-3 characters and pressing Tab as I do when working purely in a code editor. That's why I've always looked for a way to bring the code editor into my AI agent workflow, leveraging the editor's advantages, and I've found a workable approach.

Before discussing this method, I should reveal that the autocomplete need has already been partially solved by some command-line agents. For example, in Crush, Crush lets you call an external text editor to enter the prompt (with the shortcut Ctrl + o):

Crush-using-external-editor

Then I just need to configure the code editor as Helix to leverage its autocomplete of previously typed words, saving typing effort. In this case, Helix is detached from the project's source code context, so it can only suggest previously typed words, not functions or variables in the source code.


Cách chỉ dẫn trợ lý AI dành cho người ngại đánh chữ

Mình là người gõ chữ chậm nên khi lập trình, mình rất cần tính năng autocomplete, để khỏi phải gõ nhiều và gõ nhầm. Khi áp dụng AI vào công việc, có một hạn chế lớn là khung nhập prompt của các phần mềm agent không có tính năng autocomplete. Nghĩa là khi mình muốn trợ lý sửa hàm này hàm kia, mình phải gõ đầy đủ tên hàm tên biến, hoặc copy chúng từ bên ngoài vào, thay vì chỉ cần gõ 2-3 chữ đầu rồi bấm Tab như cách làm việc thuần tuý trên code editor. Vì vậy mình vẫn luôn tìm cách để có thể lôi được code editor vào quy trình làm việc với agent AI, tận dụng lợi thế của code editor và đã tìm được phương án tạm ổn.

Trước khi bàn đến phương pháp này thì cũng xin hé lộ là nhu cầu autocomplete cũng đã được giải quyết phần nào với một số agent ở chế độ dòng lệnh. Ví dụ trên Crush, Crush cho phép gọi text editor bên ngoài để nhập prompt (với phím tắt Ctrl + o):

Crush-using-external-editor

Khi đó mình chỉ cần cấu hình chọn code editor là Helix để tận dụng tính năng autocomplete một từ đã nhập trước đó để đỡ công gõ. Trong trường hợp này thì Helix bị tách ra khỏi ngữ cảnh source code của dự án nên nó chỉ gợi ý được từ đã nhập chứ không gợi ý được hàm biến trong source code.


Define UI comprising keyboard Shortcut in Blueprint for modern GTK apps

In previous posts, "Define UI comprising Dropdown in Blueprint for modern GTK apps" and "Define UI comprising ListView in Blueprint for modern GTK apps", I presented how to use list widgets in Blueprint. Now we look at a different, but more compact topic, the keyboard shortcut.

In a desktop app, the user is expected to do a lot of work with the keyboard alone, not always reaching for the mouse. So a good app should have many keyboard shortcuts. For example, a Ctrl+V to paste, a Ctrl+S to save, an F1 to show help, etc. Most GUI toolkits have built-in support for this. GTK is no exception. There are two ways to assign a keyboard shortcut to an action in GTK 4:

  • The simplest one is the application's accelerator, set via gtk_application_set_accels_for_action(). You define the action on the application (with the app. prefix), then call that function with a list of accelerator strings. But this is not declarative, you have to write code.
  • A more flexible way is to use a Gtk.ShortcutController, to which you add one or more Gtk.Shortcut objects. Each Shortcut binds a trigger (a key combination) to an action. This is what we will learn in this post, because it is declarative and we can describe the shortcut in the Blueprint file alongside the rest of the UI.


API tỉnh thành có dữ liệu chính thức sau đợt sát nhập

Tháng 7/2025, chính quyền có sự thay đổi mạnh về cấu trúc đơn vị hành chính, khi hủy bỏ cấp huyện và sáp nhập tỉnh với tỉnh, xã với xã. Tuy nhiên bảng mã cho các xã sau sát nhập vẫn chưa có chính thức sau nhiều tháng trời, chỉ tồn tại trong văn bản "Dự thảo". Cách đây mấy ngày, thì mình phát hiện dữ liệu đó đã được công bố chính thức trên website của Cục Thống kê nên đã cập nhật luôn thư viện vietnam-provincesAPI Tỉnh thành Việt Nam.

Đợt sát nhập tỉnh thành này có vẻ cũng bao gồm cả việc tổ chức lại bộ máy hành chính Trung ương. Lần trước, cơ quan cung cấp dữ liệu bảng mã tỉnh thành là Tổng cục Thống kê", hoạt động tại tên miền gso.gov.vn, nhưng nay cơ quan đó là "Cục Thống kê", hoạt động tại tên miền nso.gov.vn.


Define UI comprising ListView in Blueprint for modern GTK apps

In a previous post, "Define UI comprising Dropdown in Blueprint for modern GTK apps", I presented how to use DropDown in Blueprint. Now we go with a bit more complex example, with ListView widget.

This is the UI where ListView is used, in my CoBang app:

WiFi list

It shows a list of WiFi network config, for which user will pick to generate QR code. The list is accompanied with a search box, via which user will type part of Wi-Fi name to narrow down the list, to quickly find the needed Wi-Fi network.


Define UI comprising Dropdown in Blueprint for modern GTK apps

GTK is one of the GUI toolkits for building Linux desktop apps, notable for its modern visual look, and with some advanced developer experience features, like Inspector.

But one of the things that is still old-fashioned is its support for declarative UI. GTK allows developer to describe the UI separately from application code, but the language is XML which is too verbose, comparing to QT's QML or Slint. Fortunately, there is an new language, Blueprint, to describe UI for GTK app, which brings the same taste of QML, Slint to the table. But Blueprint is still young, not integrated to GTK yet (the files written in Blueprint must be compiled to Gtk.Builder XML) and the documentation is not rich enough.

This post shows you how to use Dropdown or other list widgets (like ListView, GridView) in Blueprint. The example use case and code is drawn from my application, CoBang.

List widgets follow Model-View-Controller pattern, to dislay a list of data with dynamic length. The widget is not used alone, but with other non-display components from GTK library:

...

Điểm mới của Python 3.14: Chế độ free-threading

Một điểm mới khác, khá quan trọng, của Python 3.14, nhưng không "đập vào mắt người dùng" là chế độ "free-threading". Đây là chế độ mà CPython tắt "Global Interpreter Lock" (GIL), một loại khóa trước đây dùng để ngăn chặn nhiều thread cùng truy cập, sửa đổi dữ liệu thuộc kiểu riêng của CPython. Nay với chế độ "free-threading" thì các thread được chạy song song thoải mái hơn (tốc độ xử lý của ứng dụng đa luồng cũng tăng lên).

Nếu bạn viết code Python, không cần phải quan tâm vì ở mức độ này không nhìn thấy GIL. Chỉ khi bạn viết extension cho Python bằng ngôn ngữ biên dịch (C, C++, Rust) thì mới phải động vào GIL. Khi CPython gỡ bỏ GIL, tương tự như ngã tư bỏ đi cảnh sát đứng phân luồng, thì tác giả các extension này phải tự đảm bảo code mình là thread-safe, tự áp dụng các phương tiện, chiêu thức khác để tránh code mình bị crash, deadlock trong môi trường đa luồng. Điều này lại là cơ hội tỏa sáng cho các extension viết bằng Rust. Một trong các điểm "ăn tiền" của Rust là "fearless concurrency". Rust có các luật kiểm tra ownership, lifetime chặt chẽ, có các phương tiện dành cho lập trình đa luồng giúp bạn tránh tối đa các lỗi hay gặp, khó mò trong lập trình đa luồng.

Free-threading

Mình có một extension, viết bằng Rust, để làm cho nó tương thích với "free-threading" thì cực kỳ dễ, chỉ cần khai báo gil_used = false, vì vốn từ đầu nó đã chạy mà không cần "xin" GIL rồi.

...