Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions makeabilitylab/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@
ALLOWED_HOSTS = ['*']

# Makeability Lab Global Variables, including Makeability Lab version
ML_WEBSITE_VERSION = "1.9.9.9" # Keep this updated with each release and also change the short description below
ML_WEBSITE_VERSION_DESCRIPTION = "Fixes poster upload bugs"
ML_WEBSITE_VERSION = "2.0" # Keep this updated with each release and also change the short description below
ML_WEBSITE_VERSION_DESCRIPTION = "Generates unique url_names for duplicate member names to avoid conflicts"
DATE_MAKEABILITYLAB_FORMED = datetime.date(2012, 1, 1) # Date Makeability Lab was formed
MAX_BANNERS = 7 # Maximum number of banners on a page

Expand Down
14 changes: 13 additions & 1 deletion website/models/person.py
Original file line number Diff line number Diff line change
Expand Up @@ -623,8 +623,20 @@ def save(self, *args, **kwargs):
if bool(re.search('[^a-zA-Z]', c)) and c in special_chars:
url_name_cleaned = url_name_cleaned.replace(c, special_chars.get(c))

# Finally, clean remaining characters (EX: dashes, periods).
# Clean remaining characters (EX: dashes, periods).
url_name_cleaned = re.sub('[^a-zA-Z]', '', url_name_cleaned)

# Check for collisions and append numeric suffix if needed
# We exclude the current person (by pk) when checking for duplicates to allow updates
base_url_name = url_name_cleaned
counter = 2

# Keep incrementing counter until we find a unique url_name
while Person.objects.filter(url_name=url_name_cleaned).exclude(pk=self.pk).exists():
url_name_cleaned = f"{base_url_name}{counter}"
counter += 1
_logger.debug(f"URL name collision detected for {self.get_full_name()}. Trying {url_name_cleaned}")

self.url_name = url_name_cleaned

# Next, automatically set the bio_date_modified field
Expand Down
8 changes: 8 additions & 0 deletions website/views/member.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import website.utils.ml_utils as ml_utils
from django.shortcuts import render, get_object_or_404, redirect
from django.db.models import Q
from django.core.exceptions import MultipleObjectsReturned

# For logging
import time
Expand Down Expand Up @@ -36,6 +37,13 @@ def member(request, member_name=None, member_id=None):
try:
# Try a case-insensitive exact match
person = get_object_or_404(Person, url_name__iexact=member_name)
except MultipleObjectsReturned:
# This should not happen if url_name uniqueness is working correctly
# Log error and return the most recently modified person as fallback
_logger.error(f"Multiple people found with url_name={member_name}! This indicates url_name uniqueness is broken. Returning most recent.")
person = Person.objects.filter(url_name__iexact=member_name).order_by('-modified_date').first()
if person is None:
raise Http404("No person matches the given query.")
except Http404:
_logger.debug(f"{member_name} not found for url_name, looking for closest match in database")
closest_urlname = get_closest_urlname_in_database(member_name)
Expand Down