Major additions to roster system and login
I've added a lot of changes to the roster system (that will be finished tomorrow). I've implemented the template for a large part, and written the view behind it as well.
In the current state, it's going to be hard to make it all work well with just the Django template language, largely because of the way how I have to work reversed in HTML tables. So I've decided to prepare the rows up front, and then print them in the table directly. This makes the roster view pretty large, but that can be refactored in the future.
Other small changes include working on the login screen and URL handling, changing the settings to be more forgiving for debugging, and hiding the header for now, as it got annoyingly in the way
- Author
- Maarten 'Vngngdn' Vangeneugden
- Date
- Feb. 1, 2018, 7:28 p.m.
- Hash
- 09579b7d3616c73134d6fe268f106bb32513d21b
- Parent
- bf3254b908dee6e18e21bccce1b5d832e87d871e
- Modified files
- administration/templates/administration/index.djhtml
- administration/templates/administration/login.djhtml
- administration/templates/administration/nav.djhtml
- administration/templates/administration/roster.djhtml
- administration/urls.py
- administration/views.py
- joeni/settings.py
- static/css/header.css
administration/templates/administration/index.djhtml ¶
0 additions and 1 deletion.
View changes Hide changes
1 |
1 |
{% load i18n %} |
2 |
2 |
{% load humanize %} |
3 |
3 |
{% load crispy_forms_tags %} |
4 |
- | {% load joeni_org %} |
5 |
4 |
|
6 |
5 |
{% block title %} |
7 |
6 |
{% trans "Administration" %} | ◀ Joeni /▶ |
8 |
7 |
{% endblock %} |
9 |
8 |
|
10 |
9 |
{% block main %} |
11 |
10 |
{% include "administration/nav.djhtml" %} |
12 |
11 |
<h1>{% trans "Administration" %}</h1> |
13 |
12 |
<p> |
14 |
13 |
{% blocktrans %} |
15 |
14 |
Welcome to the administration website of Hasselt University. Here, |
16 |
15 |
you can find all links related to the university's services, |
17 |
16 |
events, messages, and so on. |
18 |
17 |
{% endblocktrans %} |
19 |
18 |
</p> |
20 |
19 |
|
21 |
20 |
<h2>{% trans "Education department bulletin board" %}</h2> |
22 |
21 |
{% for message in education_dept_messages %} |
23 |
22 |
<h3>{{message.title}}</h3> |
24 |
23 |
<time datetime="{{ message.date|date:'Y-m-d' }}"> |
25 |
24 |
{{ message.date|naturaltime }} |
26 |
25 |
</time> |
27 |
26 |
<p>{{message.text|org}}</p> |
28 |
27 |
{% empty %} |
29 |
28 |
<p>{% trans "There are no messages available." %}</p> |
30 |
29 |
{% endfor %} |
31 |
30 |
|
32 |
31 |
<h2>{% trans "Important telephone numbers and contact services" %}</h2> |
33 |
32 |
<dl> |
34 |
33 |
<dt>{% trans "Student secretary during working hours" %}</dt> |
35 |
34 |
<dd><a href="tel:+3211268100">(+32)11 26 81 00</a></dd> |
36 |
35 |
<dt>{% trans "Student police | District office" %}</dt> |
37 |
36 |
<dd><a href="tel:+3211268115">(+32)11 26 81 15</a></dd> |
38 |
37 |
<dt>{% trans "Student police | District service" %}</dt> |
39 |
38 |
<dd><a href="tel:+3211323300">(+32)11 32 33 00</a></dd> |
40 |
39 |
</dl> |
41 |
40 |
{% comment %} |
42 |
41 |
Psychosociale opvang binnen de kantooruren |
43 |
42 |
Studentenpsycholoog:studentenpsycholoog@uhasselt.be - tel.:011 26 90 48 |
44 |
43 |
Maatschappelijk assistent: Liesbeth Huber |
45 |
44 |
Logistieke vragen buiten de kantooruren |
46 |
45 |
Dienst MAT Diepenbeek: 0475 94 30 02 |
47 |
46 |
Dienst MAT Hasselt: 0493 59 38 33 |
48 |
47 |
Studentenpolitie |
49 |
48 |
Wijkkantoor: 011 26 81 15 |
50 |
49 |
Wijkdienst: 011 32 33 00 |
51 |
50 |
0499 59 57 28 |
52 |
51 |
Tele-Onthaal (24u/24u) |
53 |
52 |
106 |
54 |
53 |
#TODO |
55 |
54 |
{% endcomment %} |
56 |
55 |
|
57 |
56 |
{% endblock main %} |
58 |
57 |
administration/templates/administration/login.djhtml ¶
1 addition and 0 deletions.
View changes Hide changes
1 |
1 |
{% load i18n %} |
2 |
2 |
|
3 |
3 |
{% block title %} |
4 |
4 |
{% trans "Log in | ◀ Joeni /▶" %} |
5 |
5 |
{% endblock %} |
6 |
6 |
|
7 |
7 |
{% block main %} |
8 |
8 |
<h1>{% trans "Authenticate with Joeni" %}</h1> |
9 |
9 |
<p> |
10 |
10 |
{% blocktrans %} |
11 |
11 |
This page is only visible for students and personnel of Hasselt University. |
12 |
12 |
Please authenticate yourself with Joeni in order to continue. |
13 |
13 |
{% endblocktrans %} |
14 |
14 |
</p> |
15 |
15 |
|
16 |
16 |
<style> |
17 |
17 |
/* label color */ |
18 |
18 |
.input-field label { |
19 |
19 |
color: #9e9e9e; |
20 |
20 |
} |
21 |
21 |
/* label focus color */ |
22 |
22 |
.input-field input[type=password]:focus + label { |
23 |
23 |
color: #ffc107; |
24 |
24 |
} |
25 |
25 |
/* label underline focus color */ |
26 |
26 |
.input-field input[type=password]:focus { |
27 |
27 |
border-bottom: 1px solid #ffc107; |
28 |
28 |
box-shadow: 0 1px 0 0 #ffc107; |
29 |
29 |
} |
30 |
30 |
.input-field input[type=text]:focus + label { |
31 |
31 |
color: #ffc107; |
32 |
32 |
} |
33 |
33 |
/* label underline focus color */ |
34 |
34 |
.input-field input[type=text]:focus { |
35 |
35 |
border-bottom: 1px solid #ffc107; |
36 |
36 |
box-shadow: 0 1px 0 0 #ffc107; |
37 |
37 |
} |
38 |
38 |
/* icon prefix focus color */ |
39 |
39 |
.input-field .prefix.active { |
40 |
40 |
color: #ffc107; |
41 |
41 |
} |
42 |
42 |
</style> |
43 |
43 |
<form action="{% url 'administration-login' %}" method="post"> |
44 |
44 |
{% csrf_token %} {# This is necessary for forms, CSRF protection. #} |
45 |
45 |
<label for="name">{% trans "Name" %}</label> |
+ |
46 |
<label for="name">{% trans "Name" %}</label> |
46 |
47 |
<input id="name" name="name" type="text" class="validate" require /> |
47 |
48 |
<br /> |
48 |
49 |
<label for="pass">{% trans "Passphrase" %}</label> |
49 |
50 |
<input id="pass" name="pass" type="password" require /> |
50 |
51 |
<input type="submit" value="{% trans "Log in" %}" /> |
51 |
52 |
</form> |
52 |
53 |
{% endblock main %} |
53 |
54 |
administration/templates/administration/nav.djhtml ¶
1 addition and 1 deletion.
View changes Hide changes
1 |
1 |
{% load i18n %} |
2 |
2 |
<nav> |
3 |
3 |
<a href="{% url 'administration-settings' %}">{% trans "Personal settings" %}</a> |
4 |
4 |
<a href="{% url 'administration-curriculum' %}">{% trans "Curricula" %}</a> |
5 |
5 |
<a href="{% url 'administration-results' %}">{% trans "Course results" %}</a> |
6 |
- | <a href="{% url 'administration-forms' %}">{% trans "Forms" %}</a> |
+ |
6 |
<a href="{% url 'administration-forms' %}">{% trans "Forms" %}</a> |
7 |
7 |
<a href="{% url 'administration-rooms' %}">{% trans "Rooms" %}</a> |
8 |
8 |
<a href="{% url 'administration-roster' %}">{% trans "Personal Roster" %}</a> |
9 |
9 |
</nav> |
10 |
10 |
administration/templates/administration/roster.djhtml ¶
32 additions and 1 deletion.
View changes Hide changes
1 |
1 |
{% load i18n %} |
+ |
2 |
{# "silent" blocks the cycle operator from printing the cycler, and in subsequent calls #} |
+ |
3 |
{% load i18n %} |
2 |
4 |
|
3 |
5 |
{% block title %} |
4 |
6 |
{% trans "Roster | ◀ Joeni /▶" %} |
5 |
7 |
{% endblock %} |
6 |
8 |
|
7 |
9 |
{% block main %} |
8 |
10 |
{% include "administration/nav.djhtml" %} |
9 |
11 |
<h1>{% trans "" %}</h1> |
10 |
- | {% endblock main %} |
+ |
12 |
<p> |
+ |
13 |
{% trans "Personal roster from" %} {{ begin|date }} {% trans "to" %} {{ end|date }} |
+ |
14 |
</p> |
+ |
15 |
<table> |
+ |
16 |
<th> |
+ |
17 |
<td></td> {# Empty row for hours #} |
+ |
18 |
{% for day in days %} |
+ |
19 |
<td>{{ day|date:"l (d/m)" }}</td> |
+ |
20 |
{% endfor %} |
+ |
21 |
</th> |
+ |
22 |
{% for time, events in time_blocks %} |
+ |
23 |
<tr> |
+ |
24 |
{% if hour == "hour" %} |
+ |
25 |
<td>{{ time }}</td> |
+ |
26 |
{% else %} |
+ |
27 |
<td></td> |
+ |
28 |
{% endif %} |
+ |
29 |
{% cycle hour %} |
+ |
30 |
<td>{{ time }}</td> |
+ |
31 |
<!--<td rowspan="5">AI</td> |
+ |
32 |
<td>Dinsdag</td> |
+ |
33 |
<td>Dinsdag</td> |
+ |
34 |
<td>Woensdag</td> |
+ |
35 |
<td>Dondeddag</td> |
+ |
36 |
<td>Vdijdag</td> |
+ |
37 |
<td>Zaterdag</td>--> |
+ |
38 |
</tr> |
+ |
39 |
{% endfor %} |
+ |
40 |
</table> |
+ |
41 |
{% endblock main %} |
11 |
42 |
administration/urls.py ¶
6 additions and 4 deletions.
View changes Hide changes
1 |
- | from django.contrib.auth import views as auth_views |
+ |
1 |
from django.contrib.auth import views as auth_views |
2 |
2 |
from . import views |
3 |
3 |
from django.utils.translation import gettext_lazy as _ |
4 |
4 |
|
5 |
5 |
urlpatterns = ([ |
6 |
6 |
path('', views.index, name='administration-index'), |
7 |
7 |
path(_('pre-registration'), views.pre_registration, name='administration-pre-registration'), |
8 |
8 |
path(_('settings'), views.settings, name='administration-settings'), |
9 |
9 |
path(_('curriculum'), views.curriculum, name='administration-curriculum'), |
10 |
10 |
path(_('results'), views.results, name='administration-results'), |
11 |
- | path(_('results/<slug:course>'), views.result, name='administration-results'), |
12 |
- | path(_('results/<int:student_id>'), views.result, name='administration-results'), |
13 |
- | path(_('forms'), views.forms, name='administration-forms'), # In Dutch: "Attesten" |
+ |
11 |
#path(_('results'), views.results, name='administration-results'), |
+ |
12 |
#path(_('results/<slug:course>'), views.result, name='administration-results'), |
+ |
13 |
#path(_('results/<int:student_id>'), views.result, name='administration-results'), |
+ |
14 |
path(_('forms'), views.forms, name='administration-forms'), # In Dutch: "Attesten" |
14 |
15 |
path(_('forms/<str:form>'), views.forms, name='administration-forms'), |
15 |
16 |
path(_('rooms'), views.rooms, name='administration-rooms'), |
16 |
17 |
path(_('rooms/<str:room>'), views.rooms, name='administration-rooms'), |
17 |
18 |
path(_('rooms/reservate'), views.room_reservate, name='administration-room-reservate'), |
18 |
19 |
path(_('roster'), views.roster, name='administration-roster'), |
19 |
20 |
path(_('jobs'), views.jobs, name='administration-jobs'), |
+ |
21 |
path(_('jobs'), views.jobs, name='administration-jobs'), |
20 |
22 |
path(_('bulletin-board'), views.bulletin_board, name='administration-bulletin-board'), |
21 |
23 |
|
22 |
24 |
path('login', views.login, name='administration-login'), |
23 |
25 |
]) |
24 |
26 |
administration/views.py ¶
54 additions and 24 deletions.
View changes Hide changes
1 |
1 |
import datetime |
+ |
2 |
import datetime |
2 |
3 |
from django.urls import reverse # Why? |
3 |
4 |
from django.utils.translation import gettext as _ |
4 |
5 |
from .models import * |
5 |
6 |
from .forms import UserDataForm |
6 |
7 |
import administration |
7 |
8 |
from django.contrib.auth.decorators import login_required |
8 |
9 |
|
+ |
10 |
|
9 |
11 |
@login_required |
10 |
12 |
def roster(request, begin=None, end=None): |
11 |
13 |
"""Collects and renders the data that has to be displayed in the roster. |
12 |
14 |
|
13 |
15 |
The begin and end date can be specified. Only roster points in that range |
14 |
16 |
will be included in the response. If no begin and end are specified, it will |
15 |
17 |
take the current week as begin and end point. If it's |
16 |
18 |
weekend, it will take next week.""" |
17 |
19 |
|
18 |
20 |
template = "administration/roster.djhtml" |
+ |
21 |
context = dict() |
+ |
22 |
template = "administration/roster.djhtml" |
19 |
23 |
|
20 |
24 |
if begin is None or end is None: |
21 |
25 |
today = datetime.date.today() |
22 |
26 |
if today.isoweekday() in {6,7}: # Weekend |
23 |
27 |
begin = today + datetime.timedelta(days=8-today.isoweekday()) |
24 |
28 |
end = today + datetime.timedelta(days=13-today.isoweekday()) |
25 |
29 |
else: # Same week |
26 |
30 |
begin = today - datetime.timedelta(days=today.weekday()) |
27 |
31 |
end = today + datetime.timedelta(days=5-today.isoweekday()) |
28 |
32 |
|
+ |
33 |
context['end'] = end |
+ |
34 |
|
29 |
35 |
|
+ |
36 |
while (end-days[-1]).days != 0: |
+ |
37 |
# Human translation: Keep adding days until the last day in the array of |
+ |
38 |
# days is the same day as the last day the user wants to see the roster for. |
+ |
39 |
days.append(days[-1] + datetime.timedelta(days=1)) |
+ |
40 |
context['days'] = days |
+ |
41 |
|
30 |
42 |
course_events = CourseEvent.objects.filter(begin_time__gte=begin).filter(end_time__lte=end) |
+ |
43 |
course_events = CourseEvent.objects.filter(begin_time__gte=begin).filter(end_time__lte=end) |
31 |
44 |
university_events = UniversityEvent.objects.filter(begin_time__gte=begin).filter(end_time__lte=end) |
32 |
45 |
study_events = StudyEvent.objects.filter(begin_time__gte=begin).filter(end_time__lte=end) |
33 |
46 |
events = Event.objects.filter(begin_time__gte=begin).filter(end_time__lte=end) |
34 |
47 |
|
35 |
48 |
return render(request, template, context) |
+ |
49 |
time_blocks = [] |
+ |
50 |
for i in range(8, 20): |
+ |
51 |
time_block = str(i) |
+ |
52 |
for j in range(0, 60, 15): |
+ |
53 |
if j == 0: |
+ |
54 |
time_blocks.append([time_block + ":00",""]) |
+ |
55 |
continue |
+ |
56 |
time_blocks.append([time_block + ":" + str(j), ""]) |
+ |
57 |
context['time_blocks'] = time_blocks |
+ |
58 |
|
+ |
59 |
# Preparing events for the template |
+ |
60 |
c_es = [] |
+ |
61 |
for course_event in course_events: |
+ |
62 |
duration = course_event.end - course_event.begin |
+ |
63 |
quarters = duration.minutes // 15 |
+ |
64 |
course_item = str( |
+ |
65 |
"<td style='background-color:'"+course_event.course.course.color+";' rowspan='" |
+ |
66 |
+ str(quarters) + "'>" |
+ |
67 |
+ "<a href=" + reverse("courses-course-index", args="")+"> " # FIXME so that this links to the course's index page |
+ |
68 |
+ str(course_event.course) |
+ |
69 |
+ "<br />" |
+ |
70 |
+ str(course_event.docent) |
+ |
71 |
+ "<br />" |
+ |
72 |
+ str(course_event.room) + " (" + str(course_event.subject) + ")</a></td>") |
+ |
73 |
|
+ |
74 |
|
+ |
75 |
|
+ |
76 |
|
+ |
77 |
return render(request, template, context) |
36 |
78 |
# TODO Finish! |
37 |
79 |
|
38 |
80 |
def index(request): |
39 |
81 |
template = "administration/index.djhtml" |
40 |
82 |
context = {} |
41 |
83 |
return render(request, template, context) |
42 |
84 |
|
43 |
85 |
pass |
44 |
86 |
|
45 |
87 |
def pre_registration(request): |
46 |
88 |
user_data_form = UserDataForm() |
47 |
89 |
template = "administration/pre_registration.djhtml" |
48 |
90 |
context = dict() |
49 |
91 |
|
50 |
92 |
if request.method == 'POST': |
51 |
93 |
user_data_form = UserDataForm(request.POST) |
52 |
94 |
context['user_data_form'] = user_data_form |
53 |
95 |
if user_data_form.is_valid(): |
54 |
96 |
user_data_form.save() |
55 |
97 |
context['messsage'] = _("Your registration has been completed. You will receive an e-mail shortly.") |
56 |
98 |
else: |
57 |
99 |
context['messsage'] = _("The data you supplied had errors. Please review your submission.") |
58 |
100 |
else: |
59 |
101 |
context['user_data_form'] = UserDataForm(instance = user_data) |
60 |
102 |
|
61 |
103 |
return render(request, template, context) |
62 |
104 |
pass |
63 |
105 |
|
64 |
106 |
@login_required |
65 |
107 |
def settings(request): |
66 |
108 |
user_data = UserData.objects.get(user=request.user) |
67 |
109 |
user_data_form = UserDataForm(instance = user_data) |
68 |
110 |
template = "administration/settings.djhtml" |
69 |
111 |
context = dict() |
70 |
112 |
|
71 |
113 |
if request.method == 'POST': |
72 |
114 |
user_data_form = UserDataForm(request.POST, instance = user_data) |
73 |
115 |
context['user_data_form'] = user_data_form |
74 |
116 |
if user_data_form.is_valid(): |
75 |
117 |
user_data_form.save() |
76 |
118 |
context['messsage'] = _("Your settings were successfully updated.") |
77 |
119 |
else: |
78 |
120 |
context['messsage'] = _("The data you supplied had errors. Please review your submission.") |
79 |
121 |
else: |
80 |
122 |
context['user_data_form'] = UserDataForm(instance = user_data) |
81 |
123 |
|
82 |
124 |
return render(request, template, context) |
83 |
125 |
|
84 |
126 |
@login_required |
85 |
127 |
def bulletin_board(request): |
86 |
128 |
context = dict() |
87 |
129 |
context['exam_commission_decisions'] = ExamCommissionDecision.objects.filter(user=request.user) |
88 |
130 |
context['education_department_messages'] = ExamCommissionDecision.objects.filter(user=request.user) |
89 |
131 |
template = "administration/bulletin_board.djhtml" |
90 |
132 |
return render(request, template, context) |
91 |
133 |
|
92 |
134 |
def jobs(request): |
93 |
135 |
context = dict() |
94 |
136 |
template = "administration/jobs.djhtml" |
95 |
137 |
#@context['decisions'] = ExamCommissionDecision.objects.filter(user=request.user) |
96 |
138 |
return render(request, template, context) |
97 |
139 |
|
98 |
140 |
|
99 |
141 |
def curriculum(request): |
100 |
142 |
return render(request, template, context) |
101 |
143 |
|
102 |
144 |
def result(request): |
103 |
145 |
return render(request, template, context) |
104 |
146 |
|
105 |
147 |
@login_required |
106 |
148 |
def results(request): |
107 |
149 |
results = CourseResult.objects.filter(student=request.user) |
108 |
150 |
template = "administration/results.djhtml" |
109 |
151 |
# TODO |
110 |
152 |
return render(request, template, context) |
111 |
153 |
|
112 |
154 |
def forms(request): |
113 |
155 |
return render(request, template, context) |
114 |
156 |
|
115 |
157 |
def rooms(request): |
116 |
158 |
template = "administration/rooms.djhtml" |
117 |
159 |
return render(request, template, context) |
118 |
160 |
|
119 |
161 |
def room_reservate(request): |
120 |
162 |
return render(request, template, context) |
121 |
163 |
|
122 |
164 |
def login(request): |
123 |
165 |
if request.method == "POST": |
+ |
166 |
if request.method == "POST": |
124 |
167 |
name = request.POST['name'] |
125 |
168 |
passphrase = request.POST['password'] |
126 |
- | user = authenticate(username=name, password=passphrase) |
+ |
169 |
user = authenticate(username=name, password=passphrase) |
127 |
170 |
if user is not None: # The user was successfully authenticated. |
128 |
- | login(request, user) |
129 |
- | # Because of Leen, I now track when and where is logged in: |
130 |
- | loginRecord = Login() |
131 |
- | loginRecord.ip = request.META['REMOTE_ADDR'] |
132 |
- | loginRecord.name = name |
133 |
- | loginRecord.save() |
134 |
- | return HttpResponseRedirect(reverse('ITdays-index')) |
135 |
- | |
+ |
171 |
print("YA") |
+ |
172 |
return HttpResponseRedirect(request.POST['next']) |
+ |
173 |
else: # User credentials were wrong |
+ |
174 |
context['next'] = request.POST['next'] |
+ |
175 |
context['message'] = _("The given credentials were not correct.") |
+ |
176 |
else: |
+ |
177 |
context['next'] = request.GET.get('next', None) |
+ |
178 |
if context['next'] is None: |
+ |
179 |
context['next'] = reverse('administration-index') |
+ |
180 |
|
136 |
181 |
template = 'administration/login.djhtml' |
137 |
182 |
|
138 |
183 |
footer_links = [ |
139 |
- | ["Home", "/"], |
140 |
- | ["Contact", "mailto:maarten.vangeneugden@student.uhasselt.be"], |
141 |
- | ] |
142 |
- | |
143 |
- | context = { |
144 |
- | 'materialDesign_color': "deep-purple", |
145 |
- | 'materialDesign_accentColor': "amber", |
146 |
- | 'navbar_title': "Authentication", |
147 |
- | 'navbar_fixed': True, |
148 |
- | 'navbar_backArrow': True, |
149 |
- | 'footer_title': "Quotebook", |
150 |
- | 'footer_description': "Een lijst van citaten uit 2BACH Informatica @ UHasselt.", |
151 |
- | 'footer_links': footer_links, |
152 |
- | } |
153 |
- | return render(request, template, context) |
154 |
184 |
joeni/settings.py ¶
19 additions and 15 deletions.
View changes Hide changes
1 |
1 |
Django settings for Joeni project. |
2 |
2 |
|
3 |
3 |
Generated by 'django-admin startproject' using Django 2.0b1. |
4 |
4 |
|
5 |
5 |
For more information on this file, see |
6 |
6 |
https://docs.djangoproject.com/en/dev/topics/settings/ |
7 |
7 |
|
8 |
8 |
For the full list of settings and their values, see |
9 |
9 |
https://docs.djangoproject.com/en/dev/ref/settings/ |
10 |
10 |
""" |
11 |
11 |
|
12 |
12 |
import os |
13 |
13 |
|
14 |
14 |
# Build paths inside the project like this: os.path.join(BASE_DIR, ...) |
15 |
15 |
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) |
16 |
16 |
|
17 |
17 |
|
18 |
18 |
# Quick-start development settings - unsuitable for production |
19 |
19 |
# See https://docs.djangoproject.com/en/dev/howto/deployment/checklist/ |
20 |
20 |
|
21 |
21 |
# SECURITY WARNING: keep the secret key used in production secret! |
22 |
22 |
SECRET_KEY = '!2634qc=b*lp0=helzcmvb3+1_wcl!6z@mhzi%p(vg7odq&gfz' |
23 |
23 |
|
24 |
24 |
# SECURITY WARNING: don't run with debug turned on in production! |
25 |
25 |
DEBUG = True |
26 |
26 |
|
27 |
27 |
# Crispy settings |
28 |
28 |
CRISPY_FAIL_SILENTLY = not DEBUG # For debugging info for Crispy |
29 |
29 |
CRISPY_TEMPLATE_PACK = "hasselt-university" |
30 |
30 |
|
31 |
31 |
|
32 |
32 |
ALLOWED_HOSTS = [] |
33 |
33 |
|
34 |
34 |
|
35 |
35 |
# Application definition |
36 |
36 |
|
37 |
37 |
INSTALLED_APPS = [ |
38 |
38 |
'django.contrib.admin', |
39 |
39 |
'django.contrib.auth', |
40 |
40 |
'django.contrib.contenttypes', |
41 |
41 |
'django.contrib.humanize', |
42 |
42 |
'django.contrib.sessions', |
43 |
43 |
'django.contrib.messages', |
44 |
44 |
'django.contrib.staticfiles', |
45 |
45 |
'administration', |
46 |
46 |
'agora', |
47 |
47 |
'courses', |
48 |
48 |
'joeni', |
49 |
49 |
] |
50 |
50 |
|
51 |
51 |
MIDDLEWARE = [ |
52 |
52 |
'django.middleware.security.SecurityMiddleware', |
53 |
53 |
'django.middleware.locale.LocaleMiddleware', |
54 |
54 |
'django.middleware.common.CommonMiddleware', |
55 |
55 |
'django.middleware.csrf.CsrfViewMiddleware', |
56 |
56 |
'django.contrib.sessions.middleware.SessionMiddleware', |
57 |
57 |
'django.contrib.auth.middleware.AuthenticationMiddleware', |
58 |
58 |
'django.contrib.sessions.middleware.SessionMiddleware', |
59 |
59 |
'django.contrib.messages.middleware.MessageMiddleware', |
60 |
60 |
'django.middleware.clickjacking.XFrameOptionsMiddleware', |
61 |
61 |
'django.middleware.security.SecurityMiddleware', |
62 |
62 |
# Caching middleware |
63 |
63 |
'django.middleware.cache.UpdateCacheMiddleware', |
64 |
64 |
'django.middleware.common.CommonMiddleware', |
65 |
65 |
'django.middleware.cache.FetchFromCacheMiddleware', |
66 |
66 |
] |
67 |
67 |
|
68 |
68 |
# Caching settings |
69 |
69 |
CACHE_MIDDLEWARE_ALIAS = 'default' |
70 |
70 |
CACHE_MIDDLEWARE_SECONDS = 300 |
71 |
71 |
CACHE_MIDDLEWARE_KEY_PREFIX = '' |
72 |
72 |
|
73 |
73 |
ROOT_URLCONF = 'joeni.urls' |
74 |
74 |
|
75 |
75 |
TEMPLATES = [ |
76 |
76 |
{ |
77 |
77 |
'BACKEND': 'django.template.backends.django.DjangoTemplates', |
78 |
78 |
'DIRS': [], |
79 |
79 |
'APP_DIRS': True, |
80 |
80 |
'OPTIONS': { |
81 |
81 |
'context_processors': [ |
82 |
82 |
'django.template.context_processors.debug', |
83 |
83 |
'django.template.context_processors.request', |
84 |
84 |
'django.contrib.auth.context_processors.auth', |
85 |
85 |
'django.contrib.messages.context_processors.messages', |
86 |
86 |
], |
87 |
87 |
}, |
88 |
88 |
}, |
89 |
89 |
] |
90 |
90 |
|
91 |
91 |
#WSGI_APPLICATION = 'joeni.wsgi.application' |
92 |
92 |
|
93 |
93 |
|
94 |
94 |
# Database |
95 |
95 |
# https://docs.djangoproject.com/en/dev/ref/settings/#databases |
96 |
96 |
|
97 |
97 |
DATABASES = { |
98 |
98 |
'default': { |
99 |
99 |
'ENGINE': 'django.db.backends.sqlite3', |
100 |
100 |
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), |
101 |
101 |
} |
102 |
102 |
} |
103 |
103 |
|
104 |
104 |
# Page to display when a user needs / wants to log in |
105 |
105 |
LOGIN_URL = 'administration/login' |
106 |
- | |
+ |
106 |
|
107 |
107 |
# Custom User model |
108 |
108 |
AUTH_USER_MODEL = 'administration.User' |
109 |
109 |
|
110 |
110 |
# Password validation |
111 |
111 |
# https://docs.djangoproject.com/en/dev/ref/settings/#auth-password-validators |
112 |
112 |
|
113 |
113 |
AUTH_PASSWORD_VALIDATORS = [ |
114 |
- | { |
115 |
- | 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', |
116 |
- | }, |
117 |
- | { |
118 |
- | 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', |
119 |
- | }, |
120 |
- | { |
121 |
- | 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', |
122 |
- | }, |
123 |
- | { |
124 |
- | 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', |
125 |
- | }, |
126 |
- | ] |
127 |
- | |
+ |
114 |
if not DEBUG: |
+ |
115 |
# XXX: For testing and easily creating new accounts, I've disabled the |
+ |
116 |
# validators to make it easier to work with. |
+ |
117 |
AUTH_PASSWORD_VALIDATORS = [ |
+ |
118 |
{ |
+ |
119 |
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', |
+ |
120 |
}, |
+ |
121 |
{ |
+ |
122 |
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', |
+ |
123 |
}, |
+ |
124 |
{ |
+ |
125 |
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', |
+ |
126 |
}, |
+ |
127 |
{ |
+ |
128 |
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', |
+ |
129 |
}, |
+ |
130 |
] |
+ |
131 |
|
128 |
132 |
CACHES = { |
129 |
133 |
'default': { |
130 |
134 |
'BACKEND': 'django.core.cache.backends.dummy.DummyCache', |
131 |
135 |
} |
132 |
136 |
} |
133 |
137 |
|
134 |
138 |
# Internationalization |
135 |
139 |
# https://docs.djangoproject.com/en/dev/topics/i18n/ |
136 |
140 |
|
137 |
141 |
LANGUAGE_CODE = 'en-us' |
138 |
142 |
|
139 |
143 |
TIME_ZONE = 'UTC' |
140 |
144 |
|
141 |
145 |
USE_I18N = True |
142 |
146 |
|
143 |
147 |
USE_L10N = True |
144 |
148 |
|
145 |
149 |
USE_TZ = True |
146 |
150 |
|
147 |
151 |
|
148 |
152 |
# Static files (CSS, JavaScript, Images) |
149 |
153 |
# https://docs.djangoproject.com/en/dev/howto/static-files/ |
150 |
154 |
|
151 |
155 |
STATICFILES_DIRS = [ |
152 |
156 |
BASE_DIR + "/static", |
153 |
157 |
] |
154 |
158 |
#STATIC_ROOT = BASE_DIR + '/static/' |
155 |
159 |
STATIC_URL = '/static/' |
156 |
160 |
MEDIA_URL = '/media/' |
157 |
161 |
static/css/header.css ¶
1 addition and 0 deletions.