Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
hackinscience
hkis-website
Commits
6df8f721
Commit
6df8f721
authored
Jan 29, 2019
by
Julien Palard
Browse files
Merge branch 'features/courses' into 'master'
added courses part1 See merge request
!5
parents
28f1200a
92f36e7c
Changes
8
Hide whitespace changes
Inline
Side-by-side
README.md
View file @
6df8f721
# How to contribute
## Requirements
This project requires Python 3.6 at least.
## Install
```
pip install -r requirements.txt
./manage.py migrate
...
...
hkis/urls.py
View file @
6df8f721
...
...
@@ -19,15 +19,17 @@ from django.conf import settings
from
django.urls
import
path
,
include
from
website.api
import
router
from
website.views
import
(
chat
,
dashboard_view
,
ProfileView
,
index
,
ExerciseListView
,
ExerciseView
,
about
,
LessonListView
,
LessonView
,
ProfileView
,
StatsDetailView
,
StatsListView
,
about
,
chat
,
dashboard_view
,
index
,
)
...
...
@@ -42,12 +44,14 @@ urlpatterns = [
path
(
"accounts/"
,
include
(
"registration.backends.default.urls"
)),
path
(
"dashboard/"
,
dashboard_view
,
name
=
"dashboard"
),
path
(
"exercises/"
,
ExerciseListView
.
as_view
(),
name
=
"exercises"
),
path
(
"favicon.ico"
,
favicon_view
),
path
(
"exercises/<slug:slug>"
,
ExerciseView
.
as_view
(),
name
=
"exercise"
),
path
(
"favicon.ico"
,
favicon_view
),
path
(
"profile/<int:pk>"
,
ProfileView
.
as_view
(),
name
=
"profile"
),
path
(
"stats/"
,
StatsListView
.
as_view
(),
name
=
"stats"
),
path
(
"stats/<int:pk>"
,
StatsDetailView
.
as_view
(),
name
=
"stats"
),
path
(
"chat/"
,
chat
,
name
=
"chat"
),
path
(
"lessons/"
,
LessonListView
.
as_view
(),
name
=
"lesson"
),
path
(
"lessons/<slug:slug>"
,
LessonView
.
as_view
(),
name
=
"lesson"
),
]
if
settings
.
DEBUG
:
...
...
website/admin.py
View file @
6df8f721
from
django
import
forms
from
django.contrib
import
admin
from
django_ace
import
AceWidget
from
website.models
import
Answer
,
Exercise
,
Snippet
from
website.models
import
Answer
,
Exercise
,
Snippet
,
Lesson
from
website.forms
import
AnswerForm
from
registration.admin
import
RegistrationAdmin
from
registration.models
import
RegistrationProfile
...
...
@@ -38,12 +38,29 @@ class AdminExerciseForm(forms.ModelForm):
}
class
AdminLessonForm
(
forms
.
ModelForm
):
class
Meta
:
model
=
Lesson
fields
=
(
"title"
,
"slug"
,
"is_published"
,
"position"
,
"content"
)
widgets
=
{
"content"
:
AceWidget
(
mode
=
"markdown"
,
theme
=
"twilight"
,
width
=
"100%"
,
height
=
"800px"
)
}
class
ExerciseAdmin
(
admin
.
ModelAdmin
):
readonly_fields
=
(
"id"
,)
list_display
=
(
"title"
,
"slug"
,
"is_published"
,
"position"
)
form
=
AdminExerciseForm
class
LessonAdmin
(
admin
.
ModelAdmin
):
readonly_fields
=
(
"id"
,)
list_display
=
(
"title"
,
"slug"
,
"is_published"
,
"position"
)
form
=
AdminLessonForm
class
AnswerAdmin
(
admin
.
ModelAdmin
):
readonly_fields
=
(
"user"
,
"created_at"
,
"corrected_at"
)
list_display
=
(
"user"
,
"exercise"
,
"is_valid"
,
"created_at"
,
"is_corrected"
)
...
...
@@ -67,6 +84,7 @@ class MyUserAdmin(UserAdmin):
admin
.
site
.
register
(
Answer
,
AnswerAdmin
)
admin
.
site
.
register
(
Exercise
,
ExerciseAdmin
)
admin
.
site
.
register
(
Lesson
,
LessonAdmin
)
admin
.
site
.
register
(
Snippet
,
SnippetAdmin
)
admin
.
site
.
unregister
(
RegistrationProfile
)
...
...
website/migrations/0009_lesson.py
0 → 100644
View file @
6df8f721
# Generated by Django 2.1 on 2019-01-25 18:46
from
django.db
import
migrations
,
models
import
django_extensions.db.fields
class
Migration
(
migrations
.
Migration
):
dependencies
=
[
(
'website'
,
'0008_auto_20190118_2151'
),
]
operations
=
[
migrations
.
CreateModel
(
name
=
'Lesson'
,
fields
=
[
(
'id'
,
models
.
AutoField
(
auto_created
=
True
,
primary_key
=
True
,
serialize
=
False
,
verbose_name
=
'ID'
)),
(
'title'
,
models
.
CharField
(
max_length
=
255
)),
(
'slug'
,
django_extensions
.
db
.
fields
.
AutoSlugField
(
blank
=
True
,
editable
=
False
,
populate_from
=
[
'title'
])),
(
'content'
,
models
.
TextField
()),
(
'is_published'
,
models
.
BooleanField
(
default
=
False
)),
(
'position'
,
models
.
FloatField
(
default
=
0
)),
],
options
=
{
'ordering'
:
[
'position'
],
},
),
]
website/models.py
View file @
6df8f721
...
...
@@ -58,6 +58,21 @@ class Answer(models.Model):
def
get_absolute_url
(
self
):
return
reverse
(
"exercise"
,
args
=
[
self
.
exercise
.
slug
])
class
Lesson
(
models
.
Model
):
title
=
models
.
CharField
(
max_length
=
255
)
slug
=
AutoSlugField
(
populate_from
=
[
"title"
],
editable
=
True
)
content
=
models
.
TextField
()
is_published
=
models
.
BooleanField
(
default
=
False
)
position
=
models
.
FloatField
(
default
=
0
)
class
Meta
:
ordering
=
[
"position"
]
def
get_absolute_url
(
self
):
return
reverse
(
"lesson"
,
args
=
[
self
.
slug
])
def
__str__
(
self
):
return
self
.
title
def
cb_new_answer
(
sender
,
instance
,
created
,
**
kwargs
):
group
=
"answers.{}.{}"
.
format
(
instance
.
user
.
id
,
instance
.
exercise
.
id
)
...
...
website/templates/hkis/lesson.html
0 → 100644
View file @
6df8f721
{% extends "hkis/layout.html" %}
{% load hkis_extra %}
{% load i18n static bootstrap4 %}
{% block title %}{{ object.title }}{% endblock %}
{% block stylesheets %}
<link
href=
"{% static "
css
/
codehilite.css
"
%}"
rel=
"stylesheet"
type=
"text/css"
/>
{% endblock %}
{% block container %}
{% if next %}
<div
class=
"float-right"
>
<a
class=
"btn btn-primary"
href=
"{% url "
lesson
"
next
%}"
>
Next →
</a>
</div>
{% endif %}
{{ object.content|markdown|md_to_bootstrap }}
{% endblock %}
website/templates/hkis/lessons.html
0 → 100644
View file @
6df8f721
{% extends "hkis/layout.html" %}
{% load i18n %}
{% load static %}
{% load bootstrap4 %}
{% block title %}Python course{% endblock %}
{% block container %}
<h1>
Python lessons
</h1>
<table
class=
"table table-sm table-hover records_list"
>
<tbody>
{% for lesson in lessons %}
<tr
onclick=
"if (!event.ctrlKey){location.href='{% url "
lesson
"
lesson.slug
%}';}"
>
<td>
<a
href=
"{% url "
lesson
"
lesson.slug
%}"
>
<h5>
{{ lesson.number }}. {{ lesson.title }}
</h5>
</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}
website/views.py
View file @
6df8f721
...
...
@@ -14,7 +14,7 @@ from django.contrib.auth.models import User
from
django.views.generic.detail
import
DetailView
from
django.views.generic.edit
import
CreateView
,
UpdateView
from
django.views.generic.list
import
ListView
from
website.models
import
Exercise
,
Answer
from
website.models
import
Exercise
,
Answer
,
Lesson
from
website.forms
import
AnswerForm
...
...
@@ -46,7 +46,6 @@ class ProfileView(LoginRequiredMixin, UpdateView):
messages
.
info
(
self
.
request
,
"Profile updated"
)
return
reverse
(
"profile"
,
kwargs
=
{
"pk"
:
self
.
request
.
user
.
id
})
class
ExerciseListView
(
LoginRequiredMixin
,
ListView
):
model
=
Exercise
template_name
=
"hkis/exercises.html"
...
...
@@ -112,6 +111,43 @@ class ExerciseView(LoginRequiredMixin, DetailView):
context
[
"next"
]
=
None
return
context
class
LessonListView
(
LoginRequiredMixin
,
ListView
):
model
=
Lesson
template_name
=
"hkis/lessons.html"
def
get_queryset
(
self
):
self
.
queryset
=
Lesson
.
objects
.
filter
(
is_published
=
True
)
return
super
().
get_queryset
()
def
get_context_data
(
self
,
**
kwargs
):
context
=
super
().
get_context_data
(
**
kwargs
)
context
[
"lessons"
]
=
[
{
**
vars
(
lesson
),
"number"
:
i
+
1
,
}
for
i
,
lesson
in
enumerate
(
self
.
object_list
)
]
return
context
class
LessonView
(
LoginRequiredMixin
,
DetailView
):
model
=
Lesson
template_name
=
"hkis/lesson.html"
def
get_context_data
(
self
,
**
kwargs
):
context
=
super
().
get_context_data
(
**
kwargs
)
try
:
context
[
"next"
]
=
(
Lesson
.
objects
.
filter
(
position__gt
=
self
.
object
.
position
)
.
order_by
(
"position"
)[
0
]
.
slug
)
except
IndexError
:
context
[
"next"
]
=
None
return
context
class
StatsListView
(
UserPassesTestMixin
,
ListView
):
template_name
=
"hkis/stats_list.html"
...
...
@@ -143,7 +179,7 @@ class StatsDetailView(UserPassesTestMixin, DetailView):
"is_valid"
:
exercice
.
nb_valid_anwser
>
0
,
"slug"
:
exercice
.
slug
,
}
for
exercice
in
Exercise
.
objects
.
annotate
(
for
exercice
in
Lesson
.
objects
.
annotate
(
nb_anwser
=
Count
(
"answers"
,
filter
=
Q
(
answers__user_id
=
user
.
id
)
),
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment