We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Chant Search Manuscript view - change URL path to match OldCantus
I understand we're trying to keep URLs the same between OldCantus and NewCantus, but there's a difference in the Chant Search Manuscript view. OldCantus uses `/searchms/` (e.g. https://cantus.uwaterloo.ca/searchms/123610?t=est), whereas NewCantus uses `/chant-search-ms/` (e.g. http://206.12.93.196/chant-search-ms/123610?t=est).

This doesn't strike me as a particularly vital difference - I doubt many people will have bookmarked and or cited a Search Manuscript page. But this would be a fairly simple fix, so we may as well make NewCantus work the same as OldCantus in this case.

Bigger picture question: how important is it that all URL paths match between OldCantus and New? @annamorphism, do you have a sense of this?

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `django/cantusdb_project/main_app/urls.py`
Content:
```
1 from django.urls import include, path, reverse
2 from django.contrib.auth.views import (
3     PasswordResetView,
4     PasswordResetDoneView,
5     PasswordResetConfirmView,
6     PasswordResetCompleteView,
7 )
8 from main_app.views import views
9 import debug_toolbar
10 from main_app.views.century import (
11     CenturyDetailView,
12 )
13 from main_app.views.chant import (
14     ChantByCantusIDView,
15     ChantCreateView,
16     ChantDeleteView,
17     ChantDetailView,
18     ChantEditSyllabificationView,
19     ChantIndexView,
20     ChantListView,
21     ChantProofreadView,
22     ChantSearchView,
23     ChantSearchMSView,
24     CISearchView,
25     MelodySearchView,
26     SourceEditChantsView,
27 )
28 from main_app.views.feast import (
29     FeastDetailView,
30     FeastListView,
31 )
32 from main_app.views.genre import (
33     GenreDetailView,
34     GenreListView,
35 )
36 from main_app.views.notation import (
37     NotationDetailView,
38 )
39 from main_app.views.office import (
40     OfficeListView,
41     OfficeDetailView,
42 )
43 from main_app.views.provenance import (
44     ProvenanceDetailView,
45 )
46 from main_app.views.sequence import (
47     SequenceDetailView,
48     SequenceEditView,
49     SequenceListView,
50 )
51 from main_app.views.source import (
52     SourceCreateView,
53     SourceDetailView,
54     SourceEditView,
55     SourceListView,
56 )
57 from main_app.views.user import (
58     CustomLoginView,
59     CustomLogoutView,
60     IndexerListView,
61     UserDetailView,
62     UserListView,
63     UserSourceListView,
64 )
65 
66 urlpatterns = [
67     path("__debug__/", include(debug_toolbar.urls)),
68     path(
69         "contact/",
70         views.contact,
71         name="contact",
72     ),
73     # login/logout/user
74     path(
75         "login/",
76         CustomLoginView.as_view(redirect_authenticated_user=True),
77         name="login",
78     ),
79     path(
80         "logout/",
81         CustomLogoutView.as_view(),
82         name="logout",
83     ),
84     path(
85         "my-sources/",
86         UserSourceListView.as_view(),
87         name="my-sources",
88     ),
89     path(
90         "user/<int:pk>",
91         UserDetailView.as_view(),
92         name="user-detail",
93     ),
94     path(
95         "users/",
96         UserListView.as_view(),
97         name="user-list",
98     ),
99     path(
100         "change-password/",
101         views.change_password,
102         name="change-password",
103     ),
104     # password reset views
105     path(
106         # here, user can initiate a request to send a password reset email
107         "reset-password/",
108         PasswordResetView.as_view(
109             template_name="registration/reset_password.html",
110             email_template_name="registration/reset_password_email.html",
111             success_url="/reset-password-sent/",
112         ),
113         name="reset_password",
114     ),
115     path(
116         # we display this page once the password reset email has been sent
117         "reset-password-sent/",
118         PasswordResetDoneView.as_view(
119             template_name="registration/reset_password_sent.html",
120         ),
121         name="reset_password_done",
122     ),
123     path(
124         # here, the user can specify their new password
125         "reset/<uidb64>/<token>",
126         PasswordResetConfirmView.as_view(
127             template_name="registration/reset_password_confirm.html",
128             success_url="/reset-password-complete/",
129         ),
130         name="reset_password_confirm",
131     ),
132     path(
133         # we display this page once a user has completed a password reset
134         # depending on whether their attempt was successful, this page either shows
135         # a success message or a non-success message.
136         "reset-password-complete/",
137         PasswordResetCompleteView.as_view(
138             template_name="registration/reset_password_complete.html"
139         ),
140         name="reset_password_complete",
141     ),
142     # century
143     path("century/<int:pk>", CenturyDetailView.as_view(), name="century-detail"),
144     # chant
145     path(
146         "chants/",
147         ChantListView.as_view(),
148         name="chant-list",
149     ),  # /chants/?source={source id}
150     path(
151         "chant/<int:pk>",
152         ChantDetailView.as_view(),
153         name="chant-detail",
154     ),
155     path(
156         "chant-search/",
157         ChantSearchView.as_view(),
158         name="chant-search",
159     ),
160     path(
161         "chant-create/<int:source_pk>",
162         ChantCreateView.as_view(),
163         name="chant-create",
164     ),
165     path(
166         "id/<str:cantus_id>",
167         ChantByCantusIDView.as_view(),
168         name="chant-by-cantus-id",
169     ),
170     path(
171         "chant-delete/<int:pk>",
172         ChantDeleteView.as_view(),
173         name="chant-delete",
174     ),
175     path(
176         "edit-chants/<int:source_id>",
177         SourceEditChantsView.as_view(),
178         name="source-edit-chants",
179     ),
180     path(
181         "proofread-chant/<int:source_id>",
182         ChantProofreadView.as_view(),
183         name="chant-proofread",
184     ),
185     path(
186         "edit-syllabification/<int:chant_id>",
187         ChantEditSyllabificationView.as_view(),
188         name="source-edit-syllabification",
189     ),
190     path(
191         "index/",
192         ChantIndexView.as_view(),
193         name="chant-index",
194     ),  # /index/?source={source id}
195     # feast
196     path(
197         "feasts/",
198         FeastListView.as_view(),
199         name="feast-list",
200     ),
201     path(
202         "feast/<int:pk>",
203         FeastDetailView.as_view(),
204         name="feast-detail",
205     ),
206     # genre
207     path(
208         "genres/",
209         GenreListView.as_view(),
210         name="genre-list",
211     ),
212     path(
213         "genre/<int:pk>",
214         GenreDetailView.as_view(),
215         name="genre-detail",
216     ),
217     # indexer
218     path(
219         "indexers/",
220         IndexerListView.as_view(),
221         name="indexer-list",
222     ),
223     # notation
224     path(
225         "notation/<int:pk>",
226         NotationDetailView.as_view(),
227         name="notation-detail",
228     ),
229     # office
230     path(
231         "offices/",
232         OfficeListView.as_view(),
233         name="office-list",
234     ),
235     path(
236         "office/<int:pk>",
237         OfficeDetailView.as_view(),
238         name="office-detail",
239     ),
240     # provenance
241     path(
242         "provenance/<int:pk>",
243         ProvenanceDetailView.as_view(),
244         name="provenance-detail",
245     ),
246     # sequence
247     path(
248         "sequences/",
249         SequenceListView.as_view(),
250         name="sequence-list",
251     ),
252     path(
253         "sequence/<int:pk>",
254         SequenceDetailView.as_view(),
255         name="sequence-detail",
256     ),
257     path(
258         "edit-sequence/<int:sequence_id>",
259         SequenceEditView.as_view(),
260         name="sequence-edit",
261     ),
262     # source
263     path(
264         "sources/",
265         SourceListView.as_view(),
266         name="source-list",
267     ),
268     path(
269         "source/<int:pk>",
270         SourceDetailView.as_view(),
271         name="source-detail",
272     ),
273     path(
274         "source-create/",
275         SourceCreateView.as_view(),
276         name="source-create",
277     ),
278     path(
279         "edit-source/<int:source_id>",
280         SourceEditView.as_view(),
281         name="source-edit",
282     ),
283     # melody
284     path(
285         "melody/",
286         MelodySearchView.as_view(),
287         name="melody-search",
288     ),
289     path(
290         "ajax/melody/<str:cantus_id>",
291         views.ajax_melody_list,
292         name="ajax-melody",
293     ),
294     path(
295         "ajax/melody-search/",
296         views.ajax_melody_search,
297         name="ajax-melody-search",
298     ),
299     # json api
300     path(
301         "json-sources/",
302         views.json_sources_export,
303         name="json-sources-export",
304     ),
305     path(
306         "json-node/<str:id>",
307         views.json_node_export,
308         name="json-node-export",
309     ),
310     path(
311         "json-nextchants/<str:cantus_id>",
312         views.json_nextchants,
313         name="json-nextchants",
314     ),
315     path(
316         "json-melody/<str:cantus_id>",
317         views.json_melody_export,
318         name="json-melody-export",
319     ),
320     # misc search
321     path(
322         "chant-search-ms/<int:source_pk>",
323         ChantSearchMSView.as_view(),
324         name="chant-search-ms",
325     ),
326     path(
327         "ci-search/<str:search_term>",
328         CISearchView.as_view(),
329         name="ci-search",
330     ),
331     path(
332         "ajax/search-bar/<str:search_term>",
333         views.ajax_search_bar,
334         name="ajax-search-bar",
335     ),
336     # misc
337     path(
338         "content-statistics",
339         views.items_count,
340         name="items-count",
341     ),
342     path(
343         "source/<str:source_id>/csv/",
344         views.csv_export,
345         name="csv-export",
346     ),
347     path(
348         "sites/default/files/csv/<str:source_id>.csv",
349         views.csv_export_redirect_from_old_path,
350         name="csv-export-old-path",
351     ),
352     path(
353         "ajax/concordance/<str:cantus_id>",
354         views.ajax_concordance_list,
355         name="ajax-concordance",
356     ),
357     # content overview (for project managers)
358     path(
359         "content-overview/",
360         views.content_overview,
361         name="content-overview",
362     ),
363     # /node/ url redirects
364     path(
365         "node/<int:pk>",
366         views.redirect_node_url,
367         name="redirect-node-url",
368     ),
369     # /indexer/ url redirects
370     path(
371         "indexer/<int:pk>",
372         views.redirect_indexer,
373         name="redirect-indexer",
374     ),
375 ]
376 
377 handler404 = "main_app.views.views.handle404"
378
```
--- 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/django/cantusdb_project/main_app/urls.py b/django/cantusdb_project/main_app/urls.py
--- a/django/cantusdb_project/main_app/urls.py
+++ b/django/cantusdb_project/main_app/urls.py
@@ -319,7 +319,7 @@
     ),
     # misc search
     path(
-        "chant-search-ms/<int:source_pk>",
+        "searchms/<int:source_pk>",
         ChantSearchMSView.as_view(),
         name="chant-search-ms",
     ),

{"golden_diff": "diff --git a/django/cantusdb_project/main_app/urls.py b/django/cantusdb_project/main_app/urls.py\n--- a/django/cantusdb_project/main_app/urls.py\n+++ b/django/cantusdb_project/main_app/urls.py\n@@ -319,7 +319,7 @@\n     ),\n     # misc search\n     path(\n-        \"chant-search-ms/<int:source_pk>\",\n+        \"searchms/<int:source_pk>\",\n         ChantSearchMSView.as_view(),\n         name=\"chant-search-ms\",\n     ),\n", "issue": "Chant Search Manuscript view - change URL path to match OldCantus\nI understand we're trying to keep URLs the same between OldCantus and NewCantus, but there's a difference in the Chant Search Manuscript view. OldCantus uses `/searchms/` (e.g. https://cantus.uwaterloo.ca/searchms/123610?t=est), whereas NewCantus uses `/chant-search-ms/` (e.g. http://206.12.93.196/chant-search-ms/123610?t=est).\r\n\r\nThis doesn't strike me as a particularly vital difference - I doubt many people will have bookmarked and or cited a Search Manuscript page. But this would be a fairly simple fix, so we may as well make NewCantus work the same as OldCantus in this case.\r\n\r\nBigger picture question: how important is it that all URL paths match between OldCantus and New? @annamorphism, do you have a sense of this?\n", "before_files": [{"content": "from django.urls import include, path, reverse\nfrom django.contrib.auth.views import (\n    PasswordResetView,\n    PasswordResetDoneView,\n    PasswordResetConfirmView,\n    PasswordResetCompleteView,\n)\nfrom main_app.views import views\nimport debug_toolbar\nfrom main_app.views.century import (\n    CenturyDetailView,\n)\nfrom main_app.views.chant import (\n    ChantByCantusIDView,\n    ChantCreateView,\n    ChantDeleteView,\n    ChantDetailView,\n    ChantEditSyllabificationView,\n    ChantIndexView,\n    ChantListView,\n    ChantProofreadView,\n    ChantSearchView,\n    ChantSearchMSView,\n    CISearchView,\n    MelodySearchView,\n    SourceEditChantsView,\n)\nfrom main_app.views.feast import (\n    FeastDetailView,\n    FeastListView,\n)\nfrom main_app.views.genre import (\n    GenreDetailView,\n    GenreListView,\n)\nfrom main_app.views.notation import (\n    NotationDetailView,\n)\nfrom main_app.views.office import (\n    OfficeListView,\n    OfficeDetailView,\n)\nfrom main_app.views.provenance import (\n    ProvenanceDetailView,\n)\nfrom main_app.views.sequence import (\n    SequenceDetailView,\n    SequenceEditView,\n    SequenceListView,\n)\nfrom main_app.views.source import (\n    SourceCreateView,\n    SourceDetailView,\n    SourceEditView,\n    SourceListView,\n)\nfrom main_app.views.user import (\n    CustomLoginView,\n    CustomLogoutView,\n    IndexerListView,\n    UserDetailView,\n    UserListView,\n    UserSourceListView,\n)\n\nurlpatterns = [\n    path(\"__debug__/\", include(debug_toolbar.urls)),\n    path(\n        \"contact/\",\n        views.contact,\n        name=\"contact\",\n    ),\n    # login/logout/user\n    path(\n        \"login/\",\n        CustomLoginView.as_view(redirect_authenticated_user=True),\n        name=\"login\",\n    ),\n    path(\n        \"logout/\",\n        CustomLogoutView.as_view(),\n        name=\"logout\",\n    ),\n    path(\n        \"my-sources/\",\n        UserSourceListView.as_view(),\n        name=\"my-sources\",\n    ),\n    path(\n        \"user/<int:pk>\",\n        UserDetailView.as_view(),\n        name=\"user-detail\",\n    ),\n    path(\n        \"users/\",\n        UserListView.as_view(),\n        name=\"user-list\",\n    ),\n    path(\n        \"change-password/\",\n        views.change_password,\n        name=\"change-password\",\n    ),\n    # password reset views\n    path(\n        # here, user can initiate a request to send a password reset email\n        \"reset-password/\",\n        PasswordResetView.as_view(\n            template_name=\"registration/reset_password.html\",\n            email_template_name=\"registration/reset_password_email.html\",\n            success_url=\"/reset-password-sent/\",\n        ),\n        name=\"reset_password\",\n    ),\n    path(\n        # we display this page once the password reset email has been sent\n        \"reset-password-sent/\",\n        PasswordResetDoneView.as_view(\n            template_name=\"registration/reset_password_sent.html\",\n        ),\n        name=\"reset_password_done\",\n    ),\n    path(\n        # here, the user can specify their new password\n        \"reset/<uidb64>/<token>\",\n        PasswordResetConfirmView.as_view(\n            template_name=\"registration/reset_password_confirm.html\",\n            success_url=\"/reset-password-complete/\",\n        ),\n        name=\"reset_password_confirm\",\n    ),\n    path(\n        # we display this page once a user has completed a password reset\n        # depending on whether their attempt was successful, this page either shows\n        # a success message or a non-success message.\n        \"reset-password-complete/\",\n        PasswordResetCompleteView.as_view(\n            template_name=\"registration/reset_password_complete.html\"\n        ),\n        name=\"reset_password_complete\",\n    ),\n    # century\n    path(\"century/<int:pk>\", CenturyDetailView.as_view(), name=\"century-detail\"),\n    # chant\n    path(\n        \"chants/\",\n        ChantListView.as_view(),\n        name=\"chant-list\",\n    ),  # /chants/?source={source id}\n    path(\n        \"chant/<int:pk>\",\n        ChantDetailView.as_view(),\n        name=\"chant-detail\",\n    ),\n    path(\n        \"chant-search/\",\n        ChantSearchView.as_view(),\n        name=\"chant-search\",\n    ),\n    path(\n        \"chant-create/<int:source_pk>\",\n        ChantCreateView.as_view(),\n        name=\"chant-create\",\n    ),\n    path(\n        \"id/<str:cantus_id>\",\n        ChantByCantusIDView.as_view(),\n        name=\"chant-by-cantus-id\",\n    ),\n    path(\n        \"chant-delete/<int:pk>\",\n        ChantDeleteView.as_view(),\n        name=\"chant-delete\",\n    ),\n    path(\n        \"edit-chants/<int:source_id>\",\n        SourceEditChantsView.as_view(),\n        name=\"source-edit-chants\",\n    ),\n    path(\n        \"proofread-chant/<int:source_id>\",\n        ChantProofreadView.as_view(),\n        name=\"chant-proofread\",\n    ),\n    path(\n        \"edit-syllabification/<int:chant_id>\",\n        ChantEditSyllabificationView.as_view(),\n        name=\"source-edit-syllabification\",\n    ),\n    path(\n        \"index/\",\n        ChantIndexView.as_view(),\n        name=\"chant-index\",\n    ),  # /index/?source={source id}\n    # feast\n    path(\n        \"feasts/\",\n        FeastListView.as_view(),\n        name=\"feast-list\",\n    ),\n    path(\n        \"feast/<int:pk>\",\n        FeastDetailView.as_view(),\n        name=\"feast-detail\",\n    ),\n    # genre\n    path(\n        \"genres/\",\n        GenreListView.as_view(),\n        name=\"genre-list\",\n    ),\n    path(\n        \"genre/<int:pk>\",\n        GenreDetailView.as_view(),\n        name=\"genre-detail\",\n    ),\n    # indexer\n    path(\n        \"indexers/\",\n        IndexerListView.as_view(),\n        name=\"indexer-list\",\n    ),\n    # notation\n    path(\n        \"notation/<int:pk>\",\n        NotationDetailView.as_view(),\n        name=\"notation-detail\",\n    ),\n    # office\n    path(\n        \"offices/\",\n        OfficeListView.as_view(),\n        name=\"office-list\",\n    ),\n    path(\n        \"office/<int:pk>\",\n        OfficeDetailView.as_view(),\n        name=\"office-detail\",\n    ),\n    # provenance\n    path(\n        \"provenance/<int:pk>\",\n        ProvenanceDetailView.as_view(),\n        name=\"provenance-detail\",\n    ),\n    # sequence\n    path(\n        \"sequences/\",\n        SequenceListView.as_view(),\n        name=\"sequence-list\",\n    ),\n    path(\n        \"sequence/<int:pk>\",\n        SequenceDetailView.as_view(),\n        name=\"sequence-detail\",\n    ),\n    path(\n        \"edit-sequence/<int:sequence_id>\",\n        SequenceEditView.as_view(),\n        name=\"sequence-edit\",\n    ),\n    # source\n    path(\n        \"sources/\",\n        SourceListView.as_view(),\n        name=\"source-list\",\n    ),\n    path(\n        \"source/<int:pk>\",\n        SourceDetailView.as_view(),\n        name=\"source-detail\",\n    ),\n    path(\n        \"source-create/\",\n        SourceCreateView.as_view(),\n        name=\"source-create\",\n    ),\n    path(\n        \"edit-source/<int:source_id>\",\n        SourceEditView.as_view(),\n        name=\"source-edit\",\n    ),\n    # melody\n    path(\n        \"melody/\",\n        MelodySearchView.as_view(),\n        name=\"melody-search\",\n    ),\n    path(\n        \"ajax/melody/<str:cantus_id>\",\n        views.ajax_melody_list,\n        name=\"ajax-melody\",\n    ),\n    path(\n        \"ajax/melody-search/\",\n        views.ajax_melody_search,\n        name=\"ajax-melody-search\",\n    ),\n    # json api\n    path(\n        \"json-sources/\",\n        views.json_sources_export,\n        name=\"json-sources-export\",\n    ),\n    path(\n        \"json-node/<str:id>\",\n        views.json_node_export,\n        name=\"json-node-export\",\n    ),\n    path(\n        \"json-nextchants/<str:cantus_id>\",\n        views.json_nextchants,\n        name=\"json-nextchants\",\n    ),\n    path(\n        \"json-melody/<str:cantus_id>\",\n        views.json_melody_export,\n        name=\"json-melody-export\",\n    ),\n    # misc search\n    path(\n        \"chant-search-ms/<int:source_pk>\",\n        ChantSearchMSView.as_view(),\n        name=\"chant-search-ms\",\n    ),\n    path(\n        \"ci-search/<str:search_term>\",\n        CISearchView.as_view(),\n        name=\"ci-search\",\n    ),\n    path(\n        \"ajax/search-bar/<str:search_term>\",\n        views.ajax_search_bar,\n        name=\"ajax-search-bar\",\n    ),\n    # misc\n    path(\n        \"content-statistics\",\n        views.items_count,\n        name=\"items-count\",\n    ),\n    path(\n        \"source/<str:source_id>/csv/\",\n        views.csv_export,\n        name=\"csv-export\",\n    ),\n    path(\n        \"sites/default/files/csv/<str:source_id>.csv\",\n        views.csv_export_redirect_from_old_path,\n        name=\"csv-export-old-path\",\n    ),\n    path(\n        \"ajax/concordance/<str:cantus_id>\",\n        views.ajax_concordance_list,\n        name=\"ajax-concordance\",\n    ),\n    # content overview (for project managers)\n    path(\n        \"content-overview/\",\n        views.content_overview,\n        name=\"content-overview\",\n    ),\n    # /node/ url redirects\n    path(\n        \"node/<int:pk>\",\n        views.redirect_node_url,\n        name=\"redirect-node-url\",\n    ),\n    # /indexer/ url redirects\n    path(\n        \"indexer/<int:pk>\",\n        views.redirect_indexer,\n        name=\"redirect-indexer\",\n    ),\n]\n\nhandler404 = \"main_app.views.views.handle404\"\n", "path": "django/cantusdb_project/main_app/urls.py"}], "after_files": [{"content": "from django.urls import include, path, reverse\nfrom django.contrib.auth.views import (\n    PasswordResetView,\n    PasswordResetDoneView,\n    PasswordResetConfirmView,\n    PasswordResetCompleteView,\n)\nfrom main_app.views import views\nimport debug_toolbar\nfrom main_app.views.century import (\n    CenturyDetailView,\n)\nfrom main_app.views.chant import (\n    ChantByCantusIDView,\n    ChantCreateView,\n    ChantDeleteView,\n    ChantDetailView,\n    ChantEditSyllabificationView,\n    ChantIndexView,\n    ChantListView,\n    ChantProofreadView,\n    ChantSearchView,\n    ChantSearchMSView,\n    CISearchView,\n    MelodySearchView,\n    SourceEditChantsView,\n)\nfrom main_app.views.feast import (\n    FeastDetailView,\n    FeastListView,\n)\nfrom main_app.views.genre import (\n    GenreDetailView,\n    GenreListView,\n)\nfrom main_app.views.notation import (\n    NotationDetailView,\n)\nfrom main_app.views.office import (\n    OfficeListView,\n    OfficeDetailView,\n)\nfrom main_app.views.provenance import (\n    ProvenanceDetailView,\n)\nfrom main_app.views.sequence import (\n    SequenceDetailView,\n    SequenceEditView,\n    SequenceListView,\n)\nfrom main_app.views.source import (\n    SourceCreateView,\n    SourceDetailView,\n    SourceEditView,\n    SourceListView,\n)\nfrom main_app.views.user import (\n    CustomLoginView,\n    CustomLogoutView,\n    IndexerListView,\n    UserDetailView,\n    UserListView,\n    UserSourceListView,\n)\n\nurlpatterns = [\n    path(\"__debug__/\", include(debug_toolbar.urls)),\n    path(\n        \"contact/\",\n        views.contact,\n        name=\"contact\",\n    ),\n    # login/logout/user\n    path(\n        \"login/\",\n        CustomLoginView.as_view(redirect_authenticated_user=True),\n        name=\"login\",\n    ),\n    path(\n        \"logout/\",\n        CustomLogoutView.as_view(),\n        name=\"logout\",\n    ),\n    path(\n        \"my-sources/\",\n        UserSourceListView.as_view(),\n        name=\"my-sources\",\n    ),\n    path(\n        \"user/<int:pk>\",\n        UserDetailView.as_view(),\n        name=\"user-detail\",\n    ),\n    path(\n        \"users/\",\n        UserListView.as_view(),\n        name=\"user-list\",\n    ),\n    path(\n        \"change-password/\",\n        views.change_password,\n        name=\"change-password\",\n    ),\n    # password reset views\n    path(\n        # here, user can initiate a request to send a password reset email\n        \"reset-password/\",\n        PasswordResetView.as_view(\n            template_name=\"registration/reset_password.html\",\n            email_template_name=\"registration/reset_password_email.html\",\n            success_url=\"/reset-password-sent/\",\n        ),\n        name=\"reset_password\",\n    ),\n    path(\n        # we display this page once the password reset email has been sent\n        \"reset-password-sent/\",\n        PasswordResetDoneView.as_view(\n            template_name=\"registration/reset_password_sent.html\",\n        ),\n        name=\"reset_password_done\",\n    ),\n    path(\n        # here, the user can specify their new password\n        \"reset/<uidb64>/<token>\",\n        PasswordResetConfirmView.as_view(\n            template_name=\"registration/reset_password_confirm.html\",\n            success_url=\"/reset-password-complete/\",\n        ),\n        name=\"reset_password_confirm\",\n    ),\n    path(\n        # we display this page once a user has completed a password reset\n        # depending on whether their attempt was successful, this page either shows\n        # a success message or a non-success message.\n        \"reset-password-complete/\",\n        PasswordResetCompleteView.as_view(\n            template_name=\"registration/reset_password_complete.html\"\n        ),\n        name=\"reset_password_complete\",\n    ),\n    # century\n    path(\"century/<int:pk>\", CenturyDetailView.as_view(), name=\"century-detail\"),\n    # chant\n    path(\n        \"chants/\",\n        ChantListView.as_view(),\n        name=\"chant-list\",\n    ),  # /chants/?source={source id}\n    path(\n        \"chant/<int:pk>\",\n        ChantDetailView.as_view(),\n        name=\"chant-detail\",\n    ),\n    path(\n        \"chant-search/\",\n        ChantSearchView.as_view(),\n        name=\"chant-search\",\n    ),\n    path(\n        \"chant-create/<int:source_pk>\",\n        ChantCreateView.as_view(),\n        name=\"chant-create\",\n    ),\n    path(\n        \"id/<str:cantus_id>\",\n        ChantByCantusIDView.as_view(),\n        name=\"chant-by-cantus-id\",\n    ),\n    path(\n        \"chant-delete/<int:pk>\",\n        ChantDeleteView.as_view(),\n        name=\"chant-delete\",\n    ),\n    path(\n        \"edit-chants/<int:source_id>\",\n        SourceEditChantsView.as_view(),\n        name=\"source-edit-chants\",\n    ),\n    path(\n        \"proofread-chant/<int:source_id>\",\n        ChantProofreadView.as_view(),\n        name=\"chant-proofread\",\n    ),\n    path(\n        \"edit-syllabification/<int:chant_id>\",\n        ChantEditSyllabificationView.as_view(),\n        name=\"source-edit-syllabification\",\n    ),\n    path(\n        \"index/\",\n        ChantIndexView.as_view(),\n        name=\"chant-index\",\n    ),  # /index/?source={source id}\n    # feast\n    path(\n        \"feasts/\",\n        FeastListView.as_view(),\n        name=\"feast-list\",\n    ),\n    path(\n        \"feast/<int:pk>\",\n        FeastDetailView.as_view(),\n        name=\"feast-detail\",\n    ),\n    # genre\n    path(\n        \"genres/\",\n        GenreListView.as_view(),\n        name=\"genre-list\",\n    ),\n    path(\n        \"genre/<int:pk>\",\n        GenreDetailView.as_view(),\n        name=\"genre-detail\",\n    ),\n    # indexer\n    path(\n        \"indexers/\",\n        IndexerListView.as_view(),\n        name=\"indexer-list\",\n    ),\n    # notation\n    path(\n        \"notation/<int:pk>\",\n        NotationDetailView.as_view(),\n        name=\"notation-detail\",\n    ),\n    # office\n    path(\n        \"offices/\",\n        OfficeListView.as_view(),\n        name=\"office-list\",\n    ),\n    path(\n        \"office/<int:pk>\",\n        OfficeDetailView.as_view(),\n        name=\"office-detail\",\n    ),\n    # provenance\n    path(\n        \"provenance/<int:pk>\",\n        ProvenanceDetailView.as_view(),\n        name=\"provenance-detail\",\n    ),\n    # sequence\n    path(\n        \"sequences/\",\n        SequenceListView.as_view(),\n        name=\"sequence-list\",\n    ),\n    path(\n        \"sequence/<int:pk>\",\n        SequenceDetailView.as_view(),\n        name=\"sequence-detail\",\n    ),\n    path(\n        \"edit-sequence/<int:sequence_id>\",\n        SequenceEditView.as_view(),\n        name=\"sequence-edit\",\n    ),\n    # source\n    path(\n        \"sources/\",\n        SourceListView.as_view(),\n        name=\"source-list\",\n    ),\n    path(\n        \"source/<int:pk>\",\n        SourceDetailView.as_view(),\n        name=\"source-detail\",\n    ),\n    path(\n        \"source-create/\",\n        SourceCreateView.as_view(),\n        name=\"source-create\",\n    ),\n    path(\n        \"edit-source/<int:source_id>\",\n        SourceEditView.as_view(),\n        name=\"source-edit\",\n    ),\n    # melody\n    path(\n        \"melody/\",\n        MelodySearchView.as_view(),\n        name=\"melody-search\",\n    ),\n    path(\n        \"ajax/melody/<str:cantus_id>\",\n        views.ajax_melody_list,\n        name=\"ajax-melody\",\n    ),\n    path(\n        \"ajax/melody-search/\",\n        views.ajax_melody_search,\n        name=\"ajax-melody-search\",\n    ),\n    # json api\n    path(\n        \"json-sources/\",\n        views.json_sources_export,\n        name=\"json-sources-export\",\n    ),\n    path(\n        \"json-node/<str:id>\",\n        views.json_node_export,\n        name=\"json-node-export\",\n    ),\n    path(\n        \"json-nextchants/<str:cantus_id>\",\n        views.json_nextchants,\n        name=\"json-nextchants\",\n    ),\n    path(\n        \"json-melody/<str:cantus_id>\",\n        views.json_melody_export,\n        name=\"json-melody-export\",\n    ),\n    # misc search\n    path(\n        \"searchms/<int:source_pk>\",\n        ChantSearchMSView.as_view(),\n        name=\"chant-search-ms\",\n    ),\n    path(\n        \"ci-search/<str:search_term>\",\n        CISearchView.as_view(),\n        name=\"ci-search\",\n    ),\n    path(\n        \"ajax/search-bar/<str:search_term>\",\n        views.ajax_search_bar,\n        name=\"ajax-search-bar\",\n    ),\n    # misc\n    path(\n        \"content-statistics\",\n        views.items_count,\n        name=\"items-count\",\n    ),\n    path(\n        \"source/<str:source_id>/csv/\",\n        views.csv_export,\n        name=\"csv-export\",\n    ),\n    path(\n        \"sites/default/files/csv/<str:source_id>.csv\",\n        views.csv_export_redirect_from_old_path,\n        name=\"csv-export-old-path\",\n    ),\n    path(\n        \"ajax/concordance/<str:cantus_id>\",\n        views.ajax_concordance_list,\n        name=\"ajax-concordance\",\n    ),\n    # content overview (for project managers)\n    path(\n        \"content-overview/\",\n        views.content_overview,\n        name=\"content-overview\",\n    ),\n    # /node/ url redirects\n    path(\n        \"node/<int:pk>\",\n        views.redirect_node_url,\n        name=\"redirect-node-url\",\n    ),\n    # /indexer/ url redirects\n    path(\n        \"indexer/<int:pk>\",\n        views.redirect_indexer,\n        name=\"redirect-indexer\",\n    ),\n]\n\nhandler404 = \"main_app.views.views.handle404\"\n", "path": "django/cantusdb_project/main_app/urls.py"}]}