@@ -231,6 +231,12 @@ def add_project(
231231 "-w/-W" ,
232232 help = "Enable Wagtail CMS (default: False)" ,
233233 ),
234+ add_qe : bool = typer .Option (
235+ False ,
236+ "--qe/--no-qe" ,
237+ "-q/-Q" ,
238+ help = "Enable Queryable Encryption (default: False)" ,
239+ ),
234240 auto_install : bool = typer .Option (
235241 True ,
236242 "--install/--no-install" ,
@@ -246,20 +252,23 @@ def add_project(
246252 """
247253 Create a new Django project using bundled templates.
248254 Frontend is added by default. Use --no-frontend to skip frontend creation.
249- Use --wagtail to enable Wagtail CMS.
255+ Use --wagtail to enable Wagtail CMS. Use --qe to enable Queryable Encryption.
256+ Flags can be stacked: --qe --wagtail enables a Wagtail site with QE.
250257
251258 Projects are created in base_dir/projects/ by default.
252259 If no name is provided, a random name is generated.
253260
254261 Examples::
255262
256- dbx project add # Create with random name (includes frontend)
257- dbx project add myproject # Create with explicit name (includes frontend)
263+ dbx project add # Create with random name (includes frontend)
264+ dbx project add myproject # Create with explicit name (includes frontend)
258265 dbx project add myproject --no-frontend # Create without frontend
259266 dbx project add myproject --wagtail # Create with Wagtail CMS enabled
260- dbx project add -d ~/custom/path # Create with random name in custom directory
261- dbx project add myproject -d ~/custom/path # Create in custom directory
262- dbx project add myproject --base-dir ~/path/to/myproject # Create directly at ~/path/to/myproject
267+ dbx project add myproject --qe # Create with Queryable Encryption enabled
268+ dbx project add myproject --qe --wagtail # Create with QE + Wagtail
269+ dbx project add -d ~/custom/path # Create with random name in custom directory
270+ dbx project add myproject -d ~/custom/path # Create in custom directory
271+ dbx project add myproject --base-dir ~/path/to/myproject # Create directly at path
263272 """
264273 # Normalize parameters when called programmatically (not via CLI).
265274 # When called directly, typer.Option/Argument defaults are OptionInfo/ArgumentInfo objects.
@@ -273,6 +282,8 @@ def add_project(
273282 add_frontend = True
274283 if not isinstance (add_wagtail , bool ):
275284 add_wagtail = False
285+ if not isinstance (add_qe , bool ):
286+ add_qe = False
276287 if not isinstance (auto_install , bool ):
277288 auto_install = True
278289 if not isinstance (python_path_override , (str , type (None ))):
@@ -453,7 +464,9 @@ def add_project(
453464 raise typer .Exit (code = 1 )
454465
455466 # Add pyproject.toml after project creation
456- _create_pyproject_toml (project_path , name , settings_path , wagtail = add_wagtail )
467+ _create_pyproject_toml (
468+ project_path , name , settings_path , wagtail = add_wagtail , qe = add_qe
469+ )
457470
458471 # Enable Wagtail CMS if requested
459472 if add_wagtail :
@@ -466,6 +479,17 @@ def add_project(
466479 err = True ,
467480 )
468481
482+ # Enable Queryable Encryption if requested
483+ if add_qe :
484+ typer .echo (f"🔐 Enabling Queryable Encryption for project '{ name } '..." )
485+ try :
486+ _enable_qe (project_path , name , wagtail = add_wagtail )
487+ except Exception as e :
488+ typer .echo (
489+ f"⚠️ Project created successfully, but QE setup failed: { e } " ,
490+ err = True ,
491+ )
492+
469493 # Create frontend by default (unless --no-frontend is specified)
470494 if add_frontend :
471495 typer .echo (f"🎨 Adding frontend to project '{ name } '..." )
@@ -711,6 +735,7 @@ def _create_pyproject_toml(
711735 project_name : str ,
712736 settings_path : str = "settings.base" ,
713737 wagtail : bool = False ,
738+ qe : bool = False ,
714739):
715740 """Create a pyproject.toml file for the Django project."""
716741 base_deps = [
@@ -721,6 +746,8 @@ def _create_pyproject_toml(
721746 ]
722747 if wagtail :
723748 base_deps .append ('"wagtail"' )
749+ if qe :
750+ base_deps .append ('"pymongocrypt"' )
724751 deps_str = ",\n " .join (base_deps )
725752
726753 pyproject_content = f"""[build-system]
@@ -814,6 +841,30 @@ def _enable_wagtail(project_path: Path, project_name: str) -> None:
814841 f .write (wagtail_block )
815842
816843
844+ def _enable_qe (project_path : Path , project_name : str , wagtail : bool = False ) -> None :
845+ """Uncomment the QE block in settings and select the correct medical_records app."""
846+ settings_file = project_path / project_name / "settings" / f"{ project_name } .py"
847+ if settings_file .exists ():
848+ content = settings_file .read_text ()
849+ content = content .replace (
850+ "# from .qe import * # noqa\n "
851+ "# INSTALLED_APPS += QE_INSTALLED_APPS # noqa: F405" ,
852+ "from .qe import * # noqa\n "
853+ "INSTALLED_APPS += QE_INSTALLED_APPS # noqa: F405" ,
854+ )
855+ settings_file .write_text (content )
856+
857+ if wagtail :
858+ qe_settings_file = project_path / project_name / "settings" / "qe.py"
859+ if qe_settings_file .exists ():
860+ qe_content = qe_settings_file .read_text ()
861+ qe_content = qe_content .replace (
862+ '"medical_records.django"' ,
863+ '"medical_records.wagtail"' ,
864+ )
865+ qe_settings_file .write_text (qe_content )
866+
867+
817868def _setup_wagtail_initial_data (
818869 python_path : str ,
819870 proj ,
0 commit comments