diff --git a/NorahUniversity/__pycache__/settings.cpython-313.pyc b/NorahUniversity/__pycache__/settings.cpython-313.pyc index b611091..b6f4ada 100644 Binary files a/NorahUniversity/__pycache__/settings.cpython-313.pyc and b/NorahUniversity/__pycache__/settings.cpython-313.pyc differ diff --git a/NorahUniversity/__pycache__/urls.cpython-313.pyc b/NorahUniversity/__pycache__/urls.cpython-313.pyc index f3db1f1..56ff2be 100644 Binary files a/NorahUniversity/__pycache__/urls.cpython-313.pyc and b/NorahUniversity/__pycache__/urls.cpython-313.pyc differ diff --git a/NorahUniversity/settings.py b/NorahUniversity/settings.py index baaf0bb..18e7295 100644 --- a/NorahUniversity/settings.py +++ b/NorahUniversity/settings.py @@ -25,7 +25,7 @@ SECRET_KEY = 'django-insecure-_!ew&)1&r--3h17knd27^x8(xu(&-f4q3%x543lv5vx2!784s* # SECURITY WARNING: don't run with debug turned on in production! DEBUG = True -ALLOWED_HOSTS = [] +ALLOWED_HOSTS = ["*"] # Application definition diff --git a/NorahUniversity/urls.py b/NorahUniversity/urls.py index 84c78b0..e386c91 100644 --- a/NorahUniversity/urls.py +++ b/NorahUniversity/urls.py @@ -16,15 +16,23 @@ urlpatterns = [ path('admin/', admin.site.urls), path('api/', include(router.urls)), path('accounts/', include('allauth.urls')), - path('i18n/', include('django.conf.urls.i18n')), + path('i18n/', include('django.conf.urls.i18n')), path('summernote/', include('django_summernote.urls')), + # path('', include('recruitment.urls')), + path('/', views.form_wizard_view, name='form_wizard'), + path('/submit/', views.submit_form, name='submit_form'), + + path('api/templates/', views.list_form_templates, name='list_form_templates'), + path('api/templates/save/', views.save_form_template, name='save_form_template'), + path('api/templates//', views.load_form_template, name='load_form_template'), + path('api/templates//delete/', views.delete_form_template, name='delete_form_template'), ] -# 2. URLs that DO have a language prefix (user-facing views) -# This includes the root path (''), which is handled by 'recruitment.urls' urlpatterns += i18n_patterns( path('', include('recruitment.urls')), ) +# 2. URLs that DO have a language prefix (user-facing views) +# This includes the root path (''), which is handled by 'recruitment.urls' urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) \ No newline at end of file diff --git a/recruitment/__pycache__/urls.cpython-313.pyc b/recruitment/__pycache__/urls.cpython-313.pyc index f8eb656..cce2bd9 100644 Binary files a/recruitment/__pycache__/urls.cpython-313.pyc and b/recruitment/__pycache__/urls.cpython-313.pyc differ diff --git a/recruitment/__pycache__/views.cpython-313.pyc b/recruitment/__pycache__/views.cpython-313.pyc index 151d83e..e01a336 100644 Binary files a/recruitment/__pycache__/views.cpython-313.pyc and b/recruitment/__pycache__/views.cpython-313.pyc differ diff --git a/recruitment/urls.py b/recruitment/urls.py index b46f732..9ae1a4e 100644 --- a/recruitment/urls.py +++ b/recruitment/urls.py @@ -64,15 +64,11 @@ urlpatterns = [ path('forms/', views.form_templates_list, name='form_templates_list'), path('forms/create-template/', views.create_form_template, name='create_form_template'), - path('forms/form//', views.form_wizard_view, name='form_wizard'), - path('forms/form//submit/', views.submit_form, name='submit_form'), - path('forms//submissions//', views.form_submission_details, name='form_submission_details'), + # path('forms/form//submit/', views.submit_form, name='submit_form'), + # path('forms/form//', views.form_wizard_view, name='form_wizard'), + path('forms//submissions//', views.form_submission_details, name='form_submission_details'), path('forms/template//submissions/', views.form_template_submissions_list, name='form_template_submissions_list'), - path('api/templates/', views.list_form_templates, name='list_form_templates'), - path('api/templates/save/', views.save_form_template, name='save_form_template'), - path('api/templates//', views.load_form_template, name='load_form_template'), - path('api/templates//delete/', views.delete_form_template, name='delete_form_template'), # path('forms//', views.form_preview, name='form_preview'), # path('forms//submit/', views.form_submit, name='form_submit'), # path('forms//embed/', views.form_embed, name='form_embed'), diff --git a/recruitment/views.py b/recruitment/views.py index a62796b..fcf6e8d 100644 --- a/recruitment/views.py +++ b/recruitment/views.py @@ -33,6 +33,7 @@ from .utils import ( get_available_time_slots, ) from django.views.decorators.csrf import ensure_csrf_cookie +from django.views.decorators.http import require_POST from .models import ( FormTemplate, FormStage, @@ -844,10 +845,14 @@ def form_wizard_view(request, template_id): ) -@require_http_methods(["GET", "POST"]) +@require_POST def submit_form(request, template_id): """Handle form submission""" - print("request method", request.method) + print(f"Request method: {request}") + print(f"CSRF token in POST: {'csrfmiddlewaretoken' in request.POST}") + print(f"CSRF token value: {request.POST.get('csrfmiddlewaretoken', 'NOT FOUND')}") + print(f"POST data: {request.POST}") + print(f"FILES data: {request.FILES}") if request.method == "POST": try: template = get_object_or_404(FormTemplate, id=template_id) diff --git a/templates/forms/form_wizard.html b/templates/forms/form_wizard.html index 251a6ff..c2efea1 100644 --- a/templates/forms/form_wizard.html +++ b/templates/forms/form_wizard.html @@ -876,11 +876,10 @@ } const formData = new FormData(); + + // Add CSRF token as a form field (CRITICAL FIX) formData.append('csrfmiddlewaretoken', csrfToken); - // Add applicant info - //formData.append('applicant_name', state.formData.applicant_name || ''); - //formData.append('applicant_email', state.formData.applicant_email || ''); - console.log(state.formData) + // Add field responses state.stages.forEach(stage => { stage.fields.forEach(field => { @@ -898,22 +897,35 @@ }); try { - const response = await fetch(`/forms/form/${state.templateId}/submit/`, { + const response = await fetch(`/${state.templateId}/submit/`, { method: 'POST', body: formData + // IMPORTANT: Do NOT set Content-Type header when using FormData + // Do NOT set X-CSRFToken header when using csrfmiddlewaretoken in form data }); - const result = await response.json(); + // Check if response is OK + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + const result = await response.json(); if (result.success) { alert('Application submitted successfully! Thank you for your submission.'); - window.location.href = '/templates/'; // Redirect to templates list + window.location.href = '/applications/'; // Redirect to applications list } else { - alert('Error submitting form: ' + result.error); + alert('Error submitting form: ' + (result.error || 'Unknown error')); } } catch (error) { - console.error('Error:', error); - alert('Error submitting form. Please try again.'); + console.error('Submission error:', error); + // Try to get response text for debugging + try { + const errorText = await response.text(); + console.error('Response text:', errorText); + alert('Error submitting form. Server response: ' + errorText); + } catch (e) { + alert('Error submitting form: ' + error.message); + } } } @@ -953,7 +965,7 @@ elements.nextBtn.style.display = 'flex'; elements.nextBtn.textContent = state.currentStage === state.stages.length - 1 ? 'Preview' : - 'Next' + 'Next' } function createFieldElement(field) {