We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Links to non-existing person profiles are being generated
### What happened?

For example, on http://127.0.0.1:8000/ipr/2670/history/, a link to http://127.0.0.1:8000/person/laura.hill@parc.com is being generated, which 404s.

### What browser(s) are you seeing the problem on?

_No response_

### Code of Conduct

- [X] I agree to follow the IETF's Code of Conduct

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `ietf/person/views.py`
Content:
```
1 # Copyright The IETF Trust 2012-2020, All Rights Reserved
2 # -*- coding: utf-8 -*-
3 
4 
5 from io import StringIO, BytesIO
6 from PIL import Image
7 
8 from django.contrib import messages
9 from django.db.models import Q
10 from django.http import HttpResponse, Http404
11 from django.shortcuts import render, get_object_or_404, redirect
12 from django.utils import timezone
13 
14 import debug                            # pyflakes:ignore
15 
16 from ietf.ietfauth.utils import role_required
17 from ietf.person.models import Email, Person, Alias
18 from ietf.person.fields import select2_id_name_json
19 from ietf.person.forms import MergeForm
20 from ietf.person.utils import handle_users, merge_persons
21 
22 
23 def ajax_select2_search(request, model_name):
24     if model_name == "email":
25         model = Email
26     else:
27         model = Person
28 
29     q = [w.strip() for w in request.GET.get('q', '').split() if w.strip()]
30 
31     if not q:
32         objs = model.objects.none()
33     else:
34         query = Q()  # all objects returned if no other terms in the queryset
35         for t in q:
36             if model == Email:
37                 query &= Q(person__alias__name__icontains=t) | Q(address__icontains=t)
38             elif model == Person:
39                 if "@" in t: # allow searching email address if there's a @ in the search term
40                     query &= Q(alias__name__icontains=t) | Q(email__address__icontains=t)
41                 else:
42                     query &= Q(alias__name__icontains=t)
43 
44         objs = model.objects.filter(query)
45 
46     # require an account at the Datatracker
47     only_users = request.GET.get("user") == "1"
48     all_emails = request.GET.get("a", "0") == "1"
49 
50     if model == Email:
51         objs = objs.exclude(person=None).order_by('person__name')
52         if not all_emails:
53             objs = objs.filter(active=True)
54         if only_users:
55             objs = objs.exclude(person__user=None)
56     elif model == Person:
57         objs = objs.order_by("name")
58         if only_users:
59             objs = objs.exclude(user=None)
60 
61     try:
62         page = int(request.GET.get("p", 1)) - 1
63     except ValueError:
64         page = 0
65 
66     objs = objs.distinct()[page:page + 10]
67 
68     return HttpResponse(select2_id_name_json(objs), content_type='application/json')
69 
70 def profile(request, email_or_name):
71     if '@' in email_or_name:
72         persons = [ get_object_or_404(Email, address=email_or_name).person, ]
73     else:
74         aliases = Alias.objects.filter(name=email_or_name)
75         persons = list(set([ a.person for a in aliases ]))
76     persons = [ p for p in persons if p and p.id ]
77     if not persons:
78         raise Http404
79     return render(request, 'person/profile.html', {'persons': persons, 'today': timezone.now()})
80 
81 
82 def photo(request, email_or_name):
83     if '@' in email_or_name:
84         persons = [ get_object_or_404(Email, address=email_or_name).person, ]
85     else:
86         aliases = Alias.objects.filter(name=email_or_name)
87         persons = list(set([ a.person for a in aliases ]))
88         if not persons:
89             raise Http404("No such person")
90     if len(persons) > 1:
91         return HttpResponse(r"\r\n".join([p.email() for p in persons]), status=300)
92     person = persons[0]
93     if not person.photo:
94         raise Http404("No photo found")
95     size = request.GET.get('s') or request.GET.get('size', '80')
96     if not size.isdigit():
97         return HttpResponse("Size must be integer", status=400)
98     size = int(size)
99     img = Image.open(person.photo)
100     img = img.resize((size, img.height*size//img.width))
101     bytes = BytesIO()
102     try:
103         img.save(bytes, format='JPEG')
104         return HttpResponse(bytes.getvalue(), content_type='image/jpg')
105     except OSError:
106         raise Http404
107 
108 
109 @role_required("Secretariat")
110 def merge(request):
111     form = MergeForm()
112     method = 'get'
113     change_details = ''
114     warn_messages = []
115     source = None
116     target = None
117 
118     if request.method == "GET":
119         form = MergeForm()
120         if request.GET:
121             form = MergeForm(request.GET)
122             if form.is_valid():
123                 source = form.cleaned_data.get('source')
124                 target = form.cleaned_data.get('target')
125                 if source.user and target.user:
126                     warn_messages.append('WARNING: Both Person records have logins.  Be sure to specify the record to keep in the Target field.')
127                     if source.user.last_login and target.user.last_login and source.user.last_login > target.user.last_login:
128                         warn_messages.append('WARNING: The most recently used login is being deleted!')
129                 change_details = handle_users(source, target, check_only=True)
130                 method = 'post'
131             else:
132                 method = 'get'
133 
134     if request.method == "POST":
135         form = MergeForm(request.POST)
136         if form.is_valid():
137             source = form.cleaned_data.get('source')
138             source_id = source.id
139             target = form.cleaned_data.get('target')
140             # Do merge with force
141             output = StringIO()
142             success, changes = merge_persons(request, source, target, file=output)
143             if success:
144                 messages.success(request, 'Merged {} ({}) to {} ({}). {})'.format(
145                     source.name, source_id, target.name, target.id, changes))
146             else:
147                 messages.error(request, output)
148             return redirect('ietf.secr.rolodex.views.view', id=target.pk)
149 
150     return render(request, 'person/merge.html', {
151         'form': form,
152         'method': method,
153         'change_details': change_details,
154         'source': source,
155         'target': target,
156         'warn_messages': warn_messages,
157     })
158
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/ietf/person/views.py b/ietf/person/views.py
--- a/ietf/person/views.py
+++ b/ietf/person/views.py
@@ -68,11 +68,13 @@
     return HttpResponse(select2_id_name_json(objs), content_type='application/json')
 
 def profile(request, email_or_name):
+    aliases = Alias.objects.filter(name=email_or_name)
+    persons = list(set([ a.person for a in aliases ]))
+
     if '@' in email_or_name:
-        persons = [ get_object_or_404(Email, address=email_or_name).person, ]
-    else:
-        aliases = Alias.objects.filter(name=email_or_name)
-        persons = list(set([ a.person for a in aliases ]))
+        emails = Email.objects.filter(address=email_or_name)
+        persons += list(set([ e.person for e in emails ]))
+
     persons = [ p for p in persons if p and p.id ]
     if not persons:
         raise Http404

{"golden_diff": "diff --git a/ietf/person/views.py b/ietf/person/views.py\n--- a/ietf/person/views.py\n+++ b/ietf/person/views.py\n@@ -68,11 +68,13 @@\n     return HttpResponse(select2_id_name_json(objs), content_type='application/json')\n \n def profile(request, email_or_name):\n+    aliases = Alias.objects.filter(name=email_or_name)\n+    persons = list(set([ a.person for a in aliases ]))\n+\n     if '@' in email_or_name:\n-        persons = [ get_object_or_404(Email, address=email_or_name).person, ]\n-    else:\n-        aliases = Alias.objects.filter(name=email_or_name)\n-        persons = list(set([ a.person for a in aliases ]))\n+        emails = Email.objects.filter(address=email_or_name)\n+        persons += list(set([ e.person for e in emails ]))\n+\n     persons = [ p for p in persons if p and p.id ]\n     if not persons:\n         raise Http404\n", "issue": "Links to non-existing person profiles are being generated\n### What happened?\n\nFor example, on http://127.0.0.1:8000/ipr/2670/history/, a link to http://127.0.0.1:8000/person/laura.hill@parc.com is being generated, which 404s.\n\n### What browser(s) are you seeing the problem on?\n\n_No response_\n\n### Code of Conduct\n\n- [X] I agree to follow the IETF's Code of Conduct\n", "before_files": [{"content": "# Copyright The IETF Trust 2012-2020, All Rights Reserved\n# -*- coding: utf-8 -*-\n\n\nfrom io import StringIO, BytesIO\nfrom PIL import Image\n\nfrom django.contrib import messages\nfrom django.db.models import Q\nfrom django.http import HttpResponse, Http404\nfrom django.shortcuts import render, get_object_or_404, redirect\nfrom django.utils import timezone\n\nimport debug                            # pyflakes:ignore\n\nfrom ietf.ietfauth.utils import role_required\nfrom ietf.person.models import Email, Person, Alias\nfrom ietf.person.fields import select2_id_name_json\nfrom ietf.person.forms import MergeForm\nfrom ietf.person.utils import handle_users, merge_persons\n\n\ndef ajax_select2_search(request, model_name):\n    if model_name == \"email\":\n        model = Email\n    else:\n        model = Person\n\n    q = [w.strip() for w in request.GET.get('q', '').split() if w.strip()]\n\n    if not q:\n        objs = model.objects.none()\n    else:\n        query = Q()  # all objects returned if no other terms in the queryset\n        for t in q:\n            if model == Email:\n                query &= Q(person__alias__name__icontains=t) | Q(address__icontains=t)\n            elif model == Person:\n                if \"@\" in t: # allow searching email address if there's a @ in the search term\n                    query &= Q(alias__name__icontains=t) | Q(email__address__icontains=t)\n                else:\n                    query &= Q(alias__name__icontains=t)\n\n        objs = model.objects.filter(query)\n\n    # require an account at the Datatracker\n    only_users = request.GET.get(\"user\") == \"1\"\n    all_emails = request.GET.get(\"a\", \"0\") == \"1\"\n\n    if model == Email:\n        objs = objs.exclude(person=None).order_by('person__name')\n        if not all_emails:\n            objs = objs.filter(active=True)\n        if only_users:\n            objs = objs.exclude(person__user=None)\n    elif model == Person:\n        objs = objs.order_by(\"name\")\n        if only_users:\n            objs = objs.exclude(user=None)\n\n    try:\n        page = int(request.GET.get(\"p\", 1)) - 1\n    except ValueError:\n        page = 0\n\n    objs = objs.distinct()[page:page + 10]\n\n    return HttpResponse(select2_id_name_json(objs), content_type='application/json')\n\ndef profile(request, email_or_name):\n    if '@' in email_or_name:\n        persons = [ get_object_or_404(Email, address=email_or_name).person, ]\n    else:\n        aliases = Alias.objects.filter(name=email_or_name)\n        persons = list(set([ a.person for a in aliases ]))\n    persons = [ p for p in persons if p and p.id ]\n    if not persons:\n        raise Http404\n    return render(request, 'person/profile.html', {'persons': persons, 'today': timezone.now()})\n\n\ndef photo(request, email_or_name):\n    if '@' in email_or_name:\n        persons = [ get_object_or_404(Email, address=email_or_name).person, ]\n    else:\n        aliases = Alias.objects.filter(name=email_or_name)\n        persons = list(set([ a.person for a in aliases ]))\n        if not persons:\n            raise Http404(\"No such person\")\n    if len(persons) > 1:\n        return HttpResponse(r\"\\r\\n\".join([p.email() for p in persons]), status=300)\n    person = persons[0]\n    if not person.photo:\n        raise Http404(\"No photo found\")\n    size = request.GET.get('s') or request.GET.get('size', '80')\n    if not size.isdigit():\n        return HttpResponse(\"Size must be integer\", status=400)\n    size = int(size)\n    img = Image.open(person.photo)\n    img = img.resize((size, img.height*size//img.width))\n    bytes = BytesIO()\n    try:\n        img.save(bytes, format='JPEG')\n        return HttpResponse(bytes.getvalue(), content_type='image/jpg')\n    except OSError:\n        raise Http404\n\n\n@role_required(\"Secretariat\")\ndef merge(request):\n    form = MergeForm()\n    method = 'get'\n    change_details = ''\n    warn_messages = []\n    source = None\n    target = None\n\n    if request.method == \"GET\":\n        form = MergeForm()\n        if request.GET:\n            form = MergeForm(request.GET)\n            if form.is_valid():\n                source = form.cleaned_data.get('source')\n                target = form.cleaned_data.get('target')\n                if source.user and target.user:\n                    warn_messages.append('WARNING: Both Person records have logins.  Be sure to specify the record to keep in the Target field.')\n                    if source.user.last_login and target.user.last_login and source.user.last_login > target.user.last_login:\n                        warn_messages.append('WARNING: The most recently used login is being deleted!')\n                change_details = handle_users(source, target, check_only=True)\n                method = 'post'\n            else:\n                method = 'get'\n\n    if request.method == \"POST\":\n        form = MergeForm(request.POST)\n        if form.is_valid():\n            source = form.cleaned_data.get('source')\n            source_id = source.id\n            target = form.cleaned_data.get('target')\n            # Do merge with force\n            output = StringIO()\n            success, changes = merge_persons(request, source, target, file=output)\n            if success:\n                messages.success(request, 'Merged {} ({}) to {} ({}). {})'.format(\n                    source.name, source_id, target.name, target.id, changes))\n            else:\n                messages.error(request, output)\n            return redirect('ietf.secr.rolodex.views.view', id=target.pk)\n\n    return render(request, 'person/merge.html', {\n        'form': form,\n        'method': method,\n        'change_details': change_details,\n        'source': source,\n        'target': target,\n        'warn_messages': warn_messages,\n    })\n", "path": "ietf/person/views.py"}], "after_files": [{"content": "# Copyright The IETF Trust 2012-2020, All Rights Reserved\n# -*- coding: utf-8 -*-\n\n\nfrom io import StringIO, BytesIO\nfrom PIL import Image\n\nfrom django.contrib import messages\nfrom django.db.models import Q\nfrom django.http import HttpResponse, Http404\nfrom django.shortcuts import render, get_object_or_404, redirect\nfrom django.utils import timezone\n\nimport debug                            # pyflakes:ignore\n\nfrom ietf.ietfauth.utils import role_required\nfrom ietf.person.models import Email, Person, Alias\nfrom ietf.person.fields import select2_id_name_json\nfrom ietf.person.forms import MergeForm\nfrom ietf.person.utils import handle_users, merge_persons\n\n\ndef ajax_select2_search(request, model_name):\n    if model_name == \"email\":\n        model = Email\n    else:\n        model = Person\n\n    q = [w.strip() for w in request.GET.get('q', '').split() if w.strip()]\n\n    if not q:\n        objs = model.objects.none()\n    else:\n        query = Q()  # all objects returned if no other terms in the queryset\n        for t in q:\n            if model == Email:\n                query &= Q(person__alias__name__icontains=t) | Q(address__icontains=t)\n            elif model == Person:\n                if \"@\" in t: # allow searching email address if there's a @ in the search term\n                    query &= Q(alias__name__icontains=t) | Q(email__address__icontains=t)\n                else:\n                    query &= Q(alias__name__icontains=t)\n\n        objs = model.objects.filter(query)\n\n    # require an account at the Datatracker\n    only_users = request.GET.get(\"user\") == \"1\"\n    all_emails = request.GET.get(\"a\", \"0\") == \"1\"\n\n    if model == Email:\n        objs = objs.exclude(person=None).order_by('person__name')\n        if not all_emails:\n            objs = objs.filter(active=True)\n        if only_users:\n            objs = objs.exclude(person__user=None)\n    elif model == Person:\n        objs = objs.order_by(\"name\")\n        if only_users:\n            objs = objs.exclude(user=None)\n\n    try:\n        page = int(request.GET.get(\"p\", 1)) - 1\n    except ValueError:\n        page = 0\n\n    objs = objs.distinct()[page:page + 10]\n\n    return HttpResponse(select2_id_name_json(objs), content_type='application/json')\n\ndef profile(request, email_or_name):\n    aliases = Alias.objects.filter(name=email_or_name)\n    persons = list(set([ a.person for a in aliases ]))\n\n    if '@' in email_or_name:\n        emails = Email.objects.filter(address=email_or_name)\n        persons += list(set([ e.person for e in emails ]))\n\n    persons = [ p for p in persons if p and p.id ]\n    if not persons:\n        raise Http404\n    return render(request, 'person/profile.html', {'persons': persons, 'today': timezone.now()})\n\n\ndef photo(request, email_or_name):\n    if '@' in email_or_name:\n        persons = [ get_object_or_404(Email, address=email_or_name).person, ]\n    else:\n        aliases = Alias.objects.filter(name=email_or_name)\n        persons = list(set([ a.person for a in aliases ]))\n        if not persons:\n            raise Http404(\"No such person\")\n    if len(persons) > 1:\n        return HttpResponse(r\"\\r\\n\".join([p.email() for p in persons]), status=300)\n    person = persons[0]\n    if not person.photo:\n        raise Http404(\"No photo found\")\n    size = request.GET.get('s') or request.GET.get('size', '80')\n    if not size.isdigit():\n        return HttpResponse(\"Size must be integer\", status=400)\n    size = int(size)\n    img = Image.open(person.photo)\n    img = img.resize((size, img.height*size//img.width))\n    bytes = BytesIO()\n    try:\n        img.save(bytes, format='JPEG')\n        return HttpResponse(bytes.getvalue(), content_type='image/jpg')\n    except OSError:\n        raise Http404\n\n\n@role_required(\"Secretariat\")\ndef merge(request):\n    form = MergeForm()\n    method = 'get'\n    change_details = ''\n    warn_messages = []\n    source = None\n    target = None\n\n    if request.method == \"GET\":\n        form = MergeForm()\n        if request.GET:\n            form = MergeForm(request.GET)\n            if form.is_valid():\n                source = form.cleaned_data.get('source')\n                target = form.cleaned_data.get('target')\n                if source.user and target.user:\n                    warn_messages.append('WARNING: Both Person records have logins.  Be sure to specify the record to keep in the Target field.')\n                    if source.user.last_login and target.user.last_login and source.user.last_login > target.user.last_login:\n                        warn_messages.append('WARNING: The most recently used login is being deleted!')\n                change_details = handle_users(source, target, check_only=True)\n                method = 'post'\n            else:\n                method = 'get'\n\n    if request.method == \"POST\":\n        form = MergeForm(request.POST)\n        if form.is_valid():\n            source = form.cleaned_data.get('source')\n            source_id = source.id\n            target = form.cleaned_data.get('target')\n            # Do merge with force\n            output = StringIO()\n            success, changes = merge_persons(request, source, target, file=output)\n            if success:\n                messages.success(request, 'Merged {} ({}) to {} ({}). {})'.format(\n                    source.name, source_id, target.name, target.id, changes))\n            else:\n                messages.error(request, output)\n            return redirect('ietf.secr.rolodex.views.view', id=target.pk)\n\n    return render(request, 'person/merge.html', {\n        'form': form,\n        'method': method,\n        'change_details': change_details,\n        'source': source,\n        'target': target,\n        'warn_messages': warn_messages,\n    })\n", "path": "ietf/person/views.py"}]}