Hello QATrack+ community,
I'm currently attempting to set up QATrack+ on Windows Server 2022 with Python 3.9, following the official documentation at https://docs.qatrackplus.com/en/stable/install/win.html#new-installation . Despite carefully following the installation steps, I've encountered several persistent challenges that I'm hoping the community can help with.
Primary Issues:
1. Database migration failures when running `python manage.py migrate`
2. Dependency conflicts, particularly with numpy, matplotlib, and other scientific packages
3. The specific error I'm seeing is: "contourpy 1.2.1 requires numpy>=1.20, but you have numpy 1.19.5 which is incompatible"
I've tried multiple approaches, including:
- Using pip directly with the requirements files
- Setting up an Anaconda environment to better manage dependencies
- Downgrading specific packages to match the versions in the requirements
My ultimate goal is to implement Azure AD authentication using django-auth-adfs ( https://django-auth-adfs.readthedocs.io/en/latest/azure_ad_config_guide.html ) for our institution, but I need to get a stable QATrack+ installation working first.
Given the forum discussions about the project modernisation efforts and transition to newer Django/Python versions, I'm wondering:
1. Is anyone successfully running QATrack+ on Windows Server 2022 with newer Python versions?
2. Has anyone implemented Azure AD authentication with QATrack+?
3. Would it be better to wait for the modernisation efforts to complete before attempting this implementation?
4. Are there any specific workarounds for the dependency conflicts I'm experiencing?
I'd greatly appreciate any guidance, suggestions, or shared experiences from others who have navigated similar challenges.
Thank you,
Pshmey (Przemek)
OUH - Oxford University Hospital
Hi Cody and QATrack+ Community,
First off, a huge thank you to Cody for your response and for sharing the requirements file - it made my life easier! I reused it with only minor tweaks (Django version and LDAP wheel adjustments) and managed to get QATrack+ running stably with LDAP on Windows Server 2022. I’ll detail my findings below to address your questions and hopefully help others in similar environments.
My Setup and Progress
After wrestling with the initial install, I’ve got QATrack+ running on Windows Server 2022 with Python 3.9 and traditional AD (LDAP) integration via django-auth-ldap. My ultimate goal was Azure AD authentication with django-auth-adfs, but as of April 2025, QATrack+ doesn’t support Azure AD natively due to dependency conflicts and the decommissioning of our ADFS servers. LDAP became the only viable option, and I’ve documented the process below.
Referring to Cody’s Points:
Installation and Configuration Details
Initial Challenges
Solutions
pip install -r qatrack31_working_requirements.txt
from django_auth_ldap.backend import LDAPBackend, populate_user
from django.dispatch import receiver
import logging
logger = logging.getLogger('custom_ldap_backend')
logger.setLevel(logging.DEBUG)
handler = logging.StreamHandler()
handler.setFormatter(logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s'))
logger.addHandler(handler)
logger.propagate = False
class CustomLDAPBackend(LDAPBackend):
def authenticate(self, request, username=None, password=None, **kwargs):
logger.debug(f"Authenticating {username}")
user = super().authenticate(request, username=username, password=password, **kwargs)
if user: logger.debug(f"User {username} authenticated successfully via LDAP")
else: logger.debug(f"Authentication failed for {username}")
return user
@receiver(populate_user)
def assign_qatrack_groups(sender, user, ldap_user, **kwargs):
from qatrack.accounts.models import ActiveDirectoryGroupMap
logger.debug(f"Populating user {user.username}")
raw_groups = ldap_user.group_dns
ad_groups = [dn.split(',')[0].lower().replace('cn=', '') for dn in raw_groups]
group_map = {k.lower(): v for k, v in ActiveDirectoryGroupMap.group_map().items()}
for ad_group in ad_groups:
if ad_group in group_map:
logger.debug(f"Assigning groups for {ad_group}: {group_map[ad_group]}")
user.groups.add(*group_map[ad_group])
user.save()
import ldap
from django_auth_ldap.config import LDAPSearch, ActiveDirectoryGroupType
import logging
AUTHENTICATION_BACKENDS = (
'myapp.backends.CustomLDAPBackend',
'qatrack.accounts.backends.QATrackAccountBackend',
'django.contrib.auth.backends.ModelBackend',
)
AUTH_LDAP_SERVER_URI = "ldaps://oxnet.nhs.uk:636"
AUTH_LDAP_BIND_DN = "used our Ad service account......"
AUTH_LDAP_BIND_PASSWORD = "its_password"
AUTH_LDAP_BASE_DN = "DC=oxnet,DC=nhs,DC=uk"
AUTH_LDAP_USER_SEARCH = LDAPSearch( correctly specified nested path, for other organisations can be different:
"OU=OXNET Managed Resources,DC=oxnet,DC=nhs,DC=uk",
ldap.SCOPE_SUBTREE,
"(sAMAccountName=%(user)s)"
)
AUTH_LDAP_USER_ATTR_MAP = {"first_name": "givenName", "last_name": "sn", "email": "mail"}
AUTH_LDAP_GROUP_TYPE = ActiveDirectoryGroupType()
AUTH_LDAP_GROUP_SEARCH = LDAPSearch( same for groups:
"OU=OXNET Managed Resources,DC=oxnet,DC=nhs,DC=uk",
ldap.SCOPE_SUBTREE,
"(objectClass=group)"
)
AUTH_LDAP_FIND_GROUP_PERMS = True
AUTH_LDAP_GROUP_CACHE_TIMEOUT = 21600
AUTH_LDAP_MIRROR_GROUPS = False
AUTH_LDAP_START_TLS = False
AUTH_LDAP_GLOBAL_OPTIONS = {
ldap.OPT_X_TLS_REQUIRE_CERT: ldap.OPT_X_TLS_NEVER,
ldap.OPT_REFERRALS: 0,
}
AUTH_LDAP_ALWAYS_UPDATE_USER = True
Additional Findings
Cody, your advice to use your requirements file were key to getting this off the ground - as this was not working for me, vene when implementing ANACONDA VENV to resolve most of the issues - it was a matter "right version" - VS- "rights version" to most of the dependencies. The custom backends.py was necessary to map AD groups, as the default LDAP backend didn’t assign them without it—authentication worked, but group sync didn’t.
I hope this helps others in similar environments (Windows Server, traditional AD, Python 3.9).
I’ll keep notes on any further issues and share them for the KB. For now, LDAP works, emails send, and I’m setting up test lists. Looking forward to the Django 4.2 upgrade.
Thanks again,
Pshemy (Przemek)
OUH - Oxford University Hospital
Pshemy (Przemek)
OUH - Oxford University Hospital