Skip to content
Snippets Groups Projects
Commit 5df81d16 authored by Tomáš Valenta's avatar Tomáš Valenta
Browse files

finish data structure, make views

parent cafece12
No related branches found
No related tags found
No related merge requests found
Showing
with 552 additions and 60 deletions
...@@ -3,3 +3,4 @@ __pycache__/ ...@@ -3,3 +3,4 @@ __pycache__/
webpack-stats.json webpack-stats.json
staticfiles staticfiles
node_modules node_modules
shared/static/shared/*.{js,css,txt}
from django.contrib import admin from django.contrib import admin
# Register your models here. from shared.admin import MarkdownxGuardedModelAdmin
from .models import Group
class GroupAdmin(MarkdownxGuardedModelAdmin):
autocomplete_fields = ("lectures",)
admin.site.register(Group, GroupAdmin)
...@@ -2,5 +2,6 @@ from django.apps import AppConfig ...@@ -2,5 +2,6 @@ from django.apps import AppConfig
class GroupsConfig(AppConfig): class GroupsConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField' default_auto_field = "django.db.models.BigAutoField"
name = 'groups' name = "groups"
verbose_name = "Skupiny"
...@@ -12,8 +12,7 @@ class Group(models.Model): ...@@ -12,8 +12,7 @@ class Group(models.Model):
lectures = models.ManyToManyField( lectures = models.ManyToManyField(
"lectures.Lecture", "lectures.Lecture",
blank=True, blank=True,
null=True, verbose_name="Lekce",
verbose_name="Události",
) )
class Meta: class Meta:
......
from django.contrib import admin from django.contrib import admin
from shared.admin import MarkdownxGuardedModelAdmin
from .models import (
Lecture,
LectureGroup,
LectureLector,
LectureMaterial,
LectureRecording,
)
# Register your models here. # Register your models here.
class IndexHiddenModelAdmin(MarkdownxGuardedModelAdmin):
def has_module_permission(self, request):
return False
class LectureGroupAdmin(MarkdownxGuardedModelAdmin):
autocomplete_fields = ("user_groups",)
search_fields = ("name",)
class LectureLectorInline(admin.TabularInline):
model = LectureLector
extra = 1
class LectureRecordingInline(admin.TabularInline):
model = LectureRecording
extra = 1
class LectureMaterialInline(admin.StackedInline):
model = LectureMaterial
extra = 1
class LectureAdmin(MarkdownxGuardedModelAdmin):
inlines = (
LectureLectorInline,
LectureRecordingInline,
LectureMaterialInline,
)
autocomplete_fields = ("groups",)
search_fields = ("name", "description")
list_display = (
"name",
"timestamp",
)
for model in (
LectureLector,
LectureMaterial,
LectureRecording,
):
admin.site.register(model, IndexHiddenModelAdmin)
admin.site.register(Lecture, LectureAdmin)
admin.site.register(LectureGroup, LectureGroupAdmin)
...@@ -2,5 +2,6 @@ from django.apps import AppConfig ...@@ -2,5 +2,6 @@ from django.apps import AppConfig
class LecturesConfig(AppConfig): class LecturesConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField' default_auto_field = "django.db.models.BigAutoField"
name = 'lectures' name = "lectures"
verbose_name = "Lekce"
# Generated by Django 4.1.4 on 2023-04-17 10:56 # Generated by Django 4.1.4 on 2023-04-17 10:56
from django.db import migrations, models
import django.db.models.deletion import django.db.models.deletion
import markdownx.models import markdownx.models
from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):
initial = True initial = True
dependencies = [ dependencies = []
]
operations = [ operations = [
migrations.CreateModel( migrations.CreateModel(
name='Lecture', name="Lecture",
fields=[ fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), (
('timestamp', models.DateTimeField(blank=True, null=True, verbose_name='Datum a čas konání')), "id",
('type', models.CharField(choices=[('recommended', 'Doporučené'), ('optional', 'Volitelné')], max_length=11, verbose_name='Typ')), models.BigAutoField(
('name', models.CharField(max_length=128, verbose_name='Název')), auto_created=True,
('description', markdownx.models.MarkdownxField(blank=True, help_text='Můžeš použít markdown.', null=True, verbose_name='Popis')), primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"timestamp",
models.DateTimeField(
blank=True, null=True, verbose_name="Datum a čas konání"
),
),
(
"type",
models.CharField(
choices=[
("recommended", "Doporučené"),
("optional", "Volitelné"),
],
max_length=11,
verbose_name="Typ",
),
),
("name", models.CharField(max_length=128, verbose_name="Název")),
(
"description",
markdownx.models.MarkdownxField(
blank=True,
help_text="Můžeš použít markdown.",
null=True,
verbose_name="Popis",
),
),
], ],
options={ options={
'verbose_name': 'Lekce', "verbose_name": "Lekce",
'verbose_name_plural': 'Lekce', "verbose_name_plural": "Lekce",
}, },
), ),
migrations.CreateModel( migrations.CreateModel(
name='Material', name="Material",
fields=[ fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), (
('name', models.CharField(max_length=128, verbose_name='Název')), "id",
('link', models.URLField(blank=True, max_length=256, null=True, verbose_name='Odkaz')), models.BigAutoField(
('file', models.FileField(blank=True, null=True, upload_to='', verbose_name='Soubor')), auto_created=True,
('event', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='materials', to='lectures.lecture', verbose_name='Událost')), primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("name", models.CharField(max_length=128, verbose_name="Název")),
(
"link",
models.URLField(
blank=True, max_length=256, null=True, verbose_name="Odkaz"
),
),
(
"file",
models.FileField(
blank=True, null=True, upload_to="", verbose_name="Soubor"
),
),
(
"event",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="materials",
to="lectures.lecture",
verbose_name="Událost",
),
),
], ],
options={ options={
'verbose_name': 'Materiál', "verbose_name": "Materiál",
'verbose_name_plural': 'Materiály', "verbose_name_plural": "Materiály",
}, },
), ),
migrations.CreateModel( migrations.CreateModel(
name='LectureRecording', name="LectureRecording",
fields=[ fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), (
('name', models.CharField(max_length=128, verbose_name='Název')), "id",
('link', models.URLField(blank=True, max_length=256, null=True, verbose_name='Odkaz')), models.BigAutoField(
('event', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='recordings', to='lectures.lecture', verbose_name='Událost')), auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("name", models.CharField(max_length=128, verbose_name="Název")),
(
"link",
models.URLField(
blank=True, max_length=256, null=True, verbose_name="Odkaz"
),
),
(
"event",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="recordings",
to="lectures.lecture",
verbose_name="Událost",
),
),
], ],
options={ options={
'verbose_name': 'Nahrávka', "verbose_name": "Nahrávka",
'verbose_name_plural': 'Nahrávky', "verbose_name_plural": "Nahrávky",
}, },
), ),
migrations.CreateModel( migrations.CreateModel(
name='LectureLector', name="LectureLector",
fields=[ fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), (
('name', models.CharField(max_length=128, verbose_name='Jméno')), "id",
('link', models.URLField(blank=True, max_length=256, null=True, verbose_name='Odkaz')), models.BigAutoField(
('event', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='lectors', to='lectures.lecture', verbose_name='Událost')), auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("name", models.CharField(max_length=128, verbose_name="Jméno")),
(
"link",
models.URLField(
blank=True, max_length=256, null=True, verbose_name="Odkaz"
),
),
(
"event",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="lectors",
to="lectures.lecture",
verbose_name="Událost",
),
),
], ],
options={ options={
'verbose_name': 'Lektor', "verbose_name": "Lektor",
'verbose_name_plural': 'Lektoři', "verbose_name_plural": "Lektoři",
}, },
), ),
] ]
# Generated by Django 4.1.4 on 2023-04-18 07:33
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('lectures', '0001_initial'),
]
operations = [
migrations.CreateModel(
name='LectureMaterial',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=128, verbose_name='Název')),
('link', models.URLField(blank=True, max_length=256, null=True, verbose_name='Odkaz')),
('file', models.FileField(blank=True, null=True, upload_to='', verbose_name='Soubor')),
('lecture', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='materials', to='lectures.lecture', verbose_name='Událost')),
],
options={
'verbose_name': 'Materiál',
'verbose_name_plural': 'Materiály',
},
),
migrations.RenameField(
model_name='lecturelector',
old_name='event',
new_name='lecture',
),
migrations.RenameField(
model_name='lecturerecording',
old_name='event',
new_name='lecture',
),
migrations.DeleteModel(
name='Material',
),
]
# Generated by Django 4.1.4 on 2023-04-18 07:56
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('lectures', '0002_lecturematerial_rename_event_lecturelector_lecture_and_more'),
]
operations = [
migrations.AlterField(
model_name='lecturematerial',
name='file',
field=models.FileField(blank=True, help_text='Zadej prosím pouze odkaz, nebo soubor.', null=True, upload_to='', verbose_name='Soubor'),
),
migrations.AlterField(
model_name='lecturematerial',
name='link',
field=models.URLField(blank=True, help_text='Zadej prosím pouze odkaz, nebo soubor.', max_length=256, null=True, verbose_name='Odkaz'),
),
]
# Generated by Django 4.1.4 on 2023-04-18 07:58
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('lectures', '0003_alter_lecturematerial_file_and_more'),
]
operations = [
migrations.AlterField(
model_name='lecturematerial',
name='file',
field=models.FileField(blank=True, help_text='Pokud máš vložený soubor, nemůžeš definovat odkaz.', null=True, upload_to='', verbose_name='Soubor'),
),
migrations.AlterField(
model_name='lecturematerial',
name='link',
field=models.URLField(blank=True, help_text='Pokud máš zadaný odkaz, nemůžeš definovat soubor.', max_length=256, null=True, verbose_name='Odkaz'),
),
]
# Generated by Django 4.1.4 on 2023-04-18 09:54
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('auth', '0012_alter_user_first_name_max_length'),
('lectures', '0004_alter_lecturematerial_file_and_more'),
]
operations = [
migrations.CreateModel(
name='LectureGroup',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=128, verbose_name='Jméno')),
('lectures', models.ManyToManyField(blank=True, related_name='groups', to='lectures.lecture', verbose_name='Lekce')),
('user_groups', models.ManyToManyField(to='auth.group', verbose_name='Uživatelské skupiny')),
],
options={
'verbose_name': 'Skupina',
'verbose_name_plural': 'Skupiny',
},
),
]
# Generated by Django 4.1.4 on 2023-04-18 10:12
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('auth', '0012_alter_user_first_name_max_length'),
('lectures', '0005_lecturegroup'),
]
operations = [
migrations.AlterModelOptions(
name='lecturegroup',
options={'verbose_name': 'Výuková skupina', 'verbose_name_plural': 'Výukové skupiny'},
),
migrations.AlterField(
model_name='lecturegroup',
name='user_groups',
field=models.ManyToManyField(blank=True, help_text='Pokud nedefinuješ žádné, lekce ve skupině jsou dostupné všem.', to='auth.group', verbose_name='Uživatelské skupiny'),
),
migrations.AlterField(
model_name='lecturelector',
name='lecture',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='lectors', to='lectures.lecture', verbose_name='Lekce'),
),
migrations.AlterField(
model_name='lecturematerial',
name='lecture',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='materials', to='lectures.lecture', verbose_name='Lekce'),
),
migrations.AlterField(
model_name='lecturerecording',
name='lecture',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='recordings', to='lectures.lecture', verbose_name='Lekce'),
),
]
# Generated by Django 4.1.4 on 2023-04-18 10:20
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('lectures', '0006_alter_lecturegroup_options_and_more'),
]
operations = [
migrations.AlterModelOptions(
name='lecture',
options={'ordering': ('-timestamp',), 'verbose_name': 'Lekce', 'verbose_name_plural': 'Lekce'},
),
]
# Generated by Django 4.1.4 on 2023-04-18 10:21
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('lectures', '0007_alter_lecture_options'),
]
operations = [
migrations.AlterModelOptions(
name='lecture',
options={'ordering': ('-timestamp', '-name'), 'verbose_name': 'Lekce', 'verbose_name_plural': 'Lekce'},
),
]
# Generated by Django 4.1.4 on 2023-04-18 10:28
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('lectures', '0008_alter_lecture_options'),
]
operations = [
migrations.RemoveField(
model_name='lecturegroup',
name='lectures',
),
migrations.AddField(
model_name='lecture',
name='groups',
field=models.ManyToManyField(blank=True, related_name='lectures', to='lectures.lecturegroup', verbose_name='Výukové skupiny'),
),
]
# Generated by Django 4.1.4 on 2023-04-18 10:29
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('lectures', '0009_remove_lecturegroup_lectures_lecture_groups'),
]
operations = [
migrations.AlterModelOptions(
name='lecturegroup',
options={'ordering': ('name',), 'verbose_name': 'Výuková skupina', 'verbose_name_plural': 'Výukové skupiny'},
),
]
from datetime import timedelta from datetime import timedelta
from django.contrib.auth.models import Group
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.db import models from django.db import models
from django.utils import timezone from django.utils import timezone
from markdownx.models import MarkdownxField from markdownx.models import MarkdownxField
from shared.models import NameStrMixin
# Create your models here. # Create your models here.
class Lecture(models.Model): class LectureGroup(NameStrMixin, models.Model):
name = models.CharField(
max_length=128,
verbose_name="Jméno",
)
user_groups = models.ManyToManyField(
Group,
blank=True,
verbose_name="Uživatelské skupiny",
help_text=("Pokud nedefinuješ žádné, lekce ve skupině jsou dostupné všem."),
)
class Meta:
verbose_name = "Výuková skupina"
verbose_name_plural = "Výukové skupiny"
ordering = ("name",)
class Lecture(NameStrMixin, models.Model):
is_current_treshold = timedelta(hours=8)
timestamp = models.DateTimeField( timestamp = models.DateTimeField(
verbose_name="Datum a čas konání", verbose_name="Datum a čas konání",
blank=True, blank=True,
...@@ -19,6 +43,13 @@ class Lecture(models.Model): ...@@ -19,6 +43,13 @@ class Lecture(models.Model):
RECOMMENDED = "recommended", "Doporučené" RECOMMENDED = "recommended", "Doporučené"
OPTIONAL = "optional", "Volitelné" OPTIONAL = "optional", "Volitelné"
groups = models.ManyToManyField(
LectureGroup,
blank=True,
related_name="lectures",
verbose_name="Výukové skupiny",
)
type = models.CharField( type = models.CharField(
choices=TypeChoices.choices, choices=TypeChoices.choices,
max_length=11, max_length=11,
...@@ -40,19 +71,20 @@ class Lecture(models.Model): ...@@ -40,19 +71,20 @@ class Lecture(models.Model):
@property @property
def is_current(self) -> bool: def is_current(self) -> bool:
# On or after the current time, minus 8 hours # On or after the current time, minus 8 hours
return self.timestamp >= (timezone.now() - timedelta(hours=8)) return self.timestamp >= (timezone.now() - self.is_current_treshold)
class Meta: class Meta:
verbose_name = "Lekce" verbose_name = "Lekce"
verbose_name_plural = verbose_name verbose_name_plural = verbose_name
ordering = ("-timestamp", "-name")
class LectureLector(models.Model): class LectureLector(NameStrMixin, models.Model):
event = models.ForeignKey( lecture = models.ForeignKey(
"Lecture", "Lecture",
on_delete=models.CASCADE, on_delete=models.CASCADE,
related_name="lectors", related_name="lectors",
verbose_name="Událost", verbose_name="Lekce",
) )
name = models.CharField( name = models.CharField(
...@@ -72,12 +104,12 @@ class LectureLector(models.Model): ...@@ -72,12 +104,12 @@ class LectureLector(models.Model):
verbose_name_plural = "Lektoři" verbose_name_plural = "Lektoři"
class LectureRecording(models.Model): class LectureRecording(NameStrMixin, models.Model):
event = models.ForeignKey( lecture = models.ForeignKey(
"Lecture", "Lecture",
on_delete=models.CASCADE, on_delete=models.CASCADE,
related_name="recordings", related_name="recordings",
verbose_name="Událost", verbose_name="Lekce",
) )
name = models.CharField( name = models.CharField(
...@@ -97,12 +129,12 @@ class LectureRecording(models.Model): ...@@ -97,12 +129,12 @@ class LectureRecording(models.Model):
verbose_name_plural = "Nahrávky" verbose_name_plural = "Nahrávky"
class Material(models.Model): class LectureMaterial(NameStrMixin, models.Model):
event = models.ForeignKey( lecture = models.ForeignKey(
"Lecture", "Lecture",
on_delete=models.CASCADE, on_delete=models.CASCADE,
related_name="materials", related_name="materials",
verbose_name="Událost", verbose_name="Lekce",
) )
name = models.CharField( name = models.CharField(
...@@ -115,25 +147,28 @@ class Material(models.Model): ...@@ -115,25 +147,28 @@ class Material(models.Model):
blank=True, blank=True,
null=True, null=True,
verbose_name="Odkaz", verbose_name="Odkaz",
help_text="Pokud máš zadaný odkaz, nemůžeš definovat soubor.",
) )
file = models.FileField( file = models.FileField(
blank=True, blank=True,
null=True, null=True,
verbose_name="Soubor", verbose_name="Soubor",
help_text="Pokud máš vložený soubor, nemůžeš definovat odkaz.",
) )
def clean(self) -> None: def clean(self) -> None:
BOTH_FILE_AND_LINK_DEFINED_ERROR = ( BOTH_FILE_AND_LINK_DEFINED_ERROR = (
"Definuj prosím pouze odkaz, nebo soubor. " "Definuj prosím pouze odkaz, nebo soubor. Nemůžeš mít oboje najednou."
"Nemůžeš mít oboje najednou."
) )
if self.file and self.link: if self.file and self.link:
raise ValidationError({ raise ValidationError(
{
"link": BOTH_FILE_AND_LINK_DEFINED_ERROR, "link": BOTH_FILE_AND_LINK_DEFINED_ERROR,
"file": BOTH_FILE_AND_LINK_DEFINED_ERROR, "file": BOTH_FILE_AND_LINK_DEFINED_ERROR,
}) }
)
class Meta: class Meta:
verbose_name = "Materiál" verbose_name = "Materiál"
......
{% extends "shared/includes/base.html" %}
{% load markdownify %}
{% block content %}
a
{% endblock %}
from django.urls import path
from . import models, views
app_name = "lectures"
urlpatterns = [
path("", views.view_avilable_groups, name="view_avilable_groups"),
]
from django.shortcuts import render from django.db import models
from django.shortcuts import get_object_or_404, render
from guardian.shortcuts import get_objects_for_user
# Create your views here. from .models import LectureGroup
def view_avilable_groups(request):
lecture_groups = (
get_objects_for_user(request.user, "lectures.view_lecturegroup")
.filter(user_groups__in=request.user.groups.all())
.distinct()
.all()
)
return render(
request,
"lectures/view_groups.html",
{
"title": "Výukové skupiny",
"site_url": "https://ucebnice.pirati.cz", # TODO
"description": "Kurzy a školení zaměřené na politickou práci a organizaci kampaní.",
"header_name": "Pirátský e-Learning",
"lecture_groups": lecture_groups,
},
)
def view_lectures(request, group_id: int):
group = get_object_or_404(
get_objects_for_user(request.user, "lectures.view_lecturegroup"),
id=group_id,
)
lectures = (
get_objects_for_user(request.user, "lectures.view_lecture")
.filter(groups=group)
.all()
)
return render(
request,
"lectures/view_lectures.html",
{
"title": f"Výuka pro {group.name}",
"site_url": "https://ucebnice.pirati.cz", # TODO
"description": f"e-Learningová výuka pro skupinu {group.name}.",
"header_name": group.name,
"lectures": lectures,
},
)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment