diff --git a/accounts/__pycache__/forms.cpython-313.pyc b/accounts/__pycache__/forms.cpython-313.pyc index 29c917a..90fb9f6 100644 Binary files a/accounts/__pycache__/forms.cpython-313.pyc and b/accounts/__pycache__/forms.cpython-313.pyc differ diff --git a/accounts/__pycache__/models.cpython-313.pyc b/accounts/__pycache__/models.cpython-313.pyc index 90cbcdd..41adae9 100644 Binary files a/accounts/__pycache__/models.cpython-313.pyc and b/accounts/__pycache__/models.cpython-313.pyc differ diff --git a/accounts/__pycache__/urls.cpython-313.pyc b/accounts/__pycache__/urls.cpython-313.pyc index a3046a6..c024d90 100644 Binary files a/accounts/__pycache__/urls.cpython-313.pyc and b/accounts/__pycache__/urls.cpython-313.pyc differ diff --git a/accounts/__pycache__/views.cpython-313.pyc b/accounts/__pycache__/views.cpython-313.pyc index 15cb9fc..fc7da10 100644 Binary files a/accounts/__pycache__/views.cpython-313.pyc and b/accounts/__pycache__/views.cpython-313.pyc differ diff --git a/accounts/forms.py b/accounts/forms.py index d67316f..d7ab0e9 100644 --- a/accounts/forms.py +++ b/accounts/forms.py @@ -20,3 +20,9 @@ class CustomUserCreationForm(forms.ModelForm): class Meta: model = CustomUser fields = ('username', 'first_name', 'last_name', 'email', 'birth_date', 'player_number', 'password') + +class CustomUserChangeForm(forms.ModelForm): + birth_date = forms.DateField(input_formats=['%d.%m.%Y'], widget=forms.DateInput(format='%d.%m.%Y')) + class Meta: + model = CustomUser + fields = ('username', 'first_name', 'last_name', 'email', 'birth_date', 'player_number', 'team') diff --git a/accounts/migrations/0002_customuser_team.py b/accounts/migrations/0002_customuser_team.py new file mode 100644 index 0000000..3d946ff --- /dev/null +++ b/accounts/migrations/0002_customuser_team.py @@ -0,0 +1,20 @@ +# Generated by Django 5.2.6 on 2025-09-30 18:09 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('accounts', '0001_initial'), + ('clubs', '0001_initial'), + ] + + operations = [ + migrations.AddField( + model_name='customuser', + name='team', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='players', to='clubs.team'), + ), + ] diff --git a/accounts/migrations/__pycache__/0002_customuser_team.cpython-313.pyc b/accounts/migrations/__pycache__/0002_customuser_team.cpython-313.pyc new file mode 100644 index 0000000..4c8aace Binary files /dev/null and b/accounts/migrations/__pycache__/0002_customuser_team.cpython-313.pyc differ diff --git a/accounts/models.py b/accounts/models.py index b4ff1bc..4d87b3a 100644 --- a/accounts/models.py +++ b/accounts/models.py @@ -6,6 +6,7 @@ import datetime class CustomUser(AbstractUser): birth_date = models.DateField(null=True, blank=True) player_number = models.IntegerField(default=999) + team = models.ForeignKey('clubs.Team', on_delete=models.SET_NULL, null=True, blank=True, related_name='players') @property def age(self): diff --git a/accounts/templates/accounts/edit_profile.html b/accounts/templates/accounts/edit_profile.html new file mode 100644 index 0000000..fce7e77 --- /dev/null +++ b/accounts/templates/accounts/edit_profile.html @@ -0,0 +1,10 @@ +{% extends "base.html" %} + +{% block content %} +

Edit Profile

+
+ {% csrf_token %} + {{ form.as_p }} + +
+{% endblock %} diff --git a/accounts/urls.py b/accounts/urls.py index af5d7a2..ab96f4f 100644 --- a/accounts/urls.py +++ b/accounts/urls.py @@ -7,4 +7,5 @@ urlpatterns = [ path('register/', views.register_view, name='register'), path('login/', auth_views.LoginView.as_view(template_name='accounts/login.html'), name='login'), path('logout/', auth_views.LogoutView.as_view(), name='logout'), + path('profile/', views.edit_profile, name='edit_profile'), ] \ No newline at end of file diff --git a/accounts/views.py b/accounts/views.py index a7cbea1..b15b898 100644 --- a/accounts/views.py +++ b/accounts/views.py @@ -1,6 +1,7 @@ from django.shortcuts import render, redirect -from .forms import InvitationCodeForm, CustomUserCreationForm +from .forms import InvitationCodeForm, CustomUserCreationForm, CustomUserChangeForm from .models import InvitationCode +from django.contrib.auth.decorators import login_required def invitation_code_view(request): if request.method == 'POST': @@ -40,4 +41,15 @@ def register_view(request): return redirect('login') # Or wherever you want to redirect after registration else: form = CustomUserCreationForm() - return render(request, 'accounts/register.html', {'form': form}) \ No newline at end of file + return render(request, 'accounts/register.html', {'form': form}) + +@login_required +def edit_profile(request): + if request.method == 'POST': + form = CustomUserChangeForm(request.POST, instance=request.user) + if form.is_valid(): + form.save() + return redirect('edit_profile') # Or wherever you want to redirect + else: + form = CustomUserChangeForm(instance=request.user) + return render(request, 'accounts/edit_profile.html', {'form': form}) \ No newline at end of file diff --git a/clubs/__pycache__/admin.cpython-313.pyc b/clubs/__pycache__/admin.cpython-313.pyc index 65bf394..fe41b54 100644 Binary files a/clubs/__pycache__/admin.cpython-313.pyc and b/clubs/__pycache__/admin.cpython-313.pyc differ diff --git a/clubs/__pycache__/models.cpython-313.pyc b/clubs/__pycache__/models.cpython-313.pyc index ed09050..8e522ed 100644 Binary files a/clubs/__pycache__/models.cpython-313.pyc and b/clubs/__pycache__/models.cpython-313.pyc differ diff --git a/clubs/admin.py b/clubs/admin.py index 8c38f3f..6e99afe 100644 --- a/clubs/admin.py +++ b/clubs/admin.py @@ -1,3 +1,5 @@ from django.contrib import admin +from .models import Club, Team -# Register your models here. +admin.site.register(Club) +admin.site.register(Team) \ No newline at end of file diff --git a/clubs/migrations/0001_initial.py b/clubs/migrations/0001_initial.py new file mode 100644 index 0000000..92d38c5 --- /dev/null +++ b/clubs/migrations/0001_initial.py @@ -0,0 +1,37 @@ +# Generated by Django 5.2.6 on 2025-09-30 18:09 + +import django.db.models.deletion +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='Club', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=255)), + ('website', models.URLField(blank=True)), + ('administrators', models.ManyToManyField(related_name='administered_clubs', to=settings.AUTH_USER_MODEL)), + ], + ), + migrations.CreateModel( + name='Team', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=255)), + ('assistant_coaches', models.ManyToManyField(blank=True, related_name='assisted_teams', to=settings.AUTH_USER_MODEL)), + ('club', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='teams', to='clubs.club')), + ('head_coach', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='coached_teams', to=settings.AUTH_USER_MODEL)), + ('parent_team', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='child_teams', to='clubs.team')), + ], + ), + ] diff --git a/clubs/migrations/__pycache__/0001_initial.cpython-313.pyc b/clubs/migrations/__pycache__/0001_initial.cpython-313.pyc new file mode 100644 index 0000000..b63a962 Binary files /dev/null and b/clubs/migrations/__pycache__/0001_initial.cpython-313.pyc differ diff --git a/clubs/models.py b/clubs/models.py index 71a8362..940cd6c 100644 --- a/clubs/models.py +++ b/clubs/models.py @@ -1,3 +1,20 @@ from django.db import models +from django.conf import settings -# Create your models here. +class Club(models.Model): + name = models.CharField(max_length=255) + website = models.URLField(blank=True) + administrators = models.ManyToManyField(settings.AUTH_USER_MODEL, related_name='administered_clubs') + + def __str__(self): + return self.name + +class Team(models.Model): + name = models.CharField(max_length=255) + club = models.ForeignKey(Club, on_delete=models.CASCADE, related_name='teams') + head_coach = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.SET_NULL, null=True, blank=True, related_name='coached_teams') + assistant_coaches = models.ManyToManyField(settings.AUTH_USER_MODEL, related_name='assisted_teams', blank=True) + parent_team = models.ForeignKey('self', on_delete=models.SET_NULL, null=True, blank=True, related_name='child_teams') + + def __str__(self): + return self.name \ No newline at end of file diff --git a/db.sqlite3 b/db.sqlite3 index e3016ee..985bf46 100644 Binary files a/db.sqlite3 and b/db.sqlite3 differ diff --git a/docs/phase3.md b/docs/phase3.md new file mode 100644 index 0000000..c63bacd --- /dev/null +++ b/docs/phase3.md @@ -0,0 +1,27 @@ +## Phase 3: Organisationsstruktur + +Diese Phase befasst sich mit den Modellen für Clubs, Mannschaften und Teams. + + Schritt 1: Club-Modell erstellen + + Navigiere in das clubs-Verzeichnis und öffne models.py. + + Erstelle ein Club-Modell mit den Feldern name und website. + + Verknüpfe den Club mit dem User-Modell, um Administratoren zuzuweisen. + + Schritt 2: Mannschafts- und Team-Modelle erstellen + + Erstelle ein Team-Modell, das die Mannschaft repräsentiert, da in der Projektbeschreibung die Mannschaft als Team behandelt werden kann. Ein is_team Feld könnte hier nützlich sein, ist aber nicht notwendig, da die Beziehungen zu parent_team die Hierarchie festlegen. + + Ein Team-Modell hat die Felder: name, head_coach (Fremdschlüssel zu User), assistant_coaches (ManyToMany-Feld zu User), und parent_team (Fremdschlüssel zu sich selbst für die Untergliederung). + + Ein Team gehört zu einem Club. + + Schritt 3: Benutzerbeziehungen implementieren + + Stelle sicher, dass die Beziehungen zwischen User und Team korrekt definiert sind: + + Ein User kann Player sein und einem Team zugewiesen werden. + + Ein User kann HeadCoach oder AssistantCoach eines Team sein. diff --git a/docs/traceback/trace1.log b/docs/traceback/trace1.log new file mode 100644 index 0000000..c12817e --- /dev/null +++ b/docs/traceback/trace1.log @@ -0,0 +1,69 @@ +Traceback (most recent call last): + File "/usr/lib64/python3.13/threading.py", line 1043, in _bootstrap_inner + self.run() + ~~~~~~~~^^ + File "/usr/lib64/python3.13/threading.py", line 994, in run + self._target(*self._args, **self._kwargs) + ~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/mnagel/Projekte/baseball_organisator/venv/lib64/python3.13/site-packages/django/utils/autoreload.py", line 64, in wrapper + fn(*args, **kwargs) + ~~^^^^^^^^^^^^^^^^^ + File "/home/mnagel/Projekte/baseball_organisator/venv/lib64/python3.13/site-packages/django/core/management/commands/runserver.py", line 134, in inner_run + self.check(**check_kwargs) + ~~~~~~~~~~^^^^^^^^^^^^^^^^ + File "/home/mnagel/Projekte/baseball_organisator/venv/lib64/python3.13/site-packages/django/core/management/base.py", line 492, in check + all_issues = checks.run_checks( + app_configs=app_configs, + ...<2 lines>... + databases=databases, + ) + File "/home/mnagel/Projekte/baseball_organisator/venv/lib64/python3.13/site-packages/django/core/checks/registry.py", line 89, in run_checks + new_errors = check(app_configs=app_configs, databases=databases) + File "/home/mnagel/Projekte/baseball_organisator/venv/lib64/python3.13/site-packages/django/core/checks/urls.py", line 16, in check_url_config + return check_resolver(resolver) + File "/home/mnagel/Projekte/baseball_organisator/venv/lib64/python3.13/site-packages/django/core/checks/urls.py", line 26, in check_resolver + return check_method() + File "/home/mnagel/Projekte/baseball_organisator/venv/lib64/python3.13/site-packages/django/urls/resolvers.py", line 531, in check + for pattern in self.url_patterns: + ^^^^^^^^^^^^^^^^^ + File "/home/mnagel/Projekte/baseball_organisator/venv/lib64/python3.13/site-packages/django/utils/functional.py", line 47, in __get__ + res = instance.__dict__[self.name] = self.func(instance) + ~~~~~~~~~^^^^^^^^^^ + File "/home/mnagel/Projekte/baseball_organisator/venv/lib64/python3.13/site-packages/django/urls/resolvers.py", line 718, in url_patterns + patterns = getattr(self.urlconf_module, "urlpatterns", self.urlconf_module) + ^^^^^^^^^^^^^^^^^^^ + File "/home/mnagel/Projekte/baseball_organisator/venv/lib64/python3.13/site-packages/django/utils/functional.py", line 47, in __get__ + res = instance.__dict__[self.name] = self.func(instance) + ~~~~~~~~~^^^^^^^^^^ + File "/home/mnagel/Projekte/baseball_organisator/venv/lib64/python3.13/site-packages/django/urls/resolvers.py", line 711, in urlconf_module + return import_module(self.urlconf_name) + File "/usr/lib64/python3.13/importlib/__init__.py", line 88, in import_module + return _bootstrap._gcd_import(name[level:], package, level) + ~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "", line 1387, in _gcd_import + File "", line 1360, in _find_and_load + File "", line 1331, in _find_and_load_unlocked + File "", line 935, in _load_unlocked + File "", line 1026, in exec_module + File "", line 488, in _call_with_frames_removed + File "/home/mnagel/Projekte/baseball_organisator/baseball_organisator/urls.py", line 22, in + path('accounts/', include('accounts.urls')), + ~~~~~~~^^^^^^^^^^^^^^^^^ + File "/home/mnagel/Projekte/baseball_organisator/venv/lib64/python3.13/site-packages/django/urls/conf.py", line 39, in include + urlconf_module = import_module(urlconf_module) + File "/usr/lib64/python3.13/importlib/__init__.py", line 88, in import_module + return _bootstrap._gcd_import(name[level:], package, level) + ~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "", line 1387, in _gcd_import + File "", line 1360, in _find_and_load + File "", line 1331, in _find_and_load_unlocked + File "", line 935, in _load_unlocked + File "", line 1026, in exec_module + File "", line 488, in _call_with_frames_removed + File "/home/mnagel/Projekte/baseball_organisator/accounts/urls.py", line 2, in + from . import views + File "/home/mnagel/Projekte/baseball_organisator/accounts/views.py", line 2, in + @login_required + ^^^^^^^^^^^^^^ +NameError: name 'login_required' is not defined +