From ec305302a17fddddea32e2a4550e7f7ceec05c60 Mon Sep 17 00:00:00 2001 From: usaturn Date: Sat, 18 Jan 2025 09:15:40 +0900 Subject: [PATCH] AI usaturn --- config/__init__.py | 0 config/asgi.py | 16 +++ config/settings.py | 129 +++++++++++++++++++++ config/urls.py | 26 +++++ config/wsgi.py | 16 +++ events/__init__.py | 0 events/admin.py | 3 + events/apps.py | 6 + events/forms.py | 25 ++++ events/migrations/0001_initial.py | 75 ++++++++++++ events/migrations/__init__.py | 0 events/models.py | 30 +++++ events/templates/events/base.html | 41 +++++++ events/templates/events/event_detail.html | 33 ++++++ events/templates/events/event_form.html | 25 ++++ events/templates/events/event_list.html | 28 +++++ events/templates/events/user_register.html | 33 ++++++ events/templates/registration/login.html | 24 ++++ events/tests.py | 3 + events/urls.py | 10 ++ events/views.py | 54 +++++++++ hello.py | 6 + hello/__init__.py | 0 hello/admin.py | 3 + hello/apps.py | 6 + hello/migrations/__init__.py | 0 hello/models.py | 3 + hello/templates/hello/index.html | 10 ++ hello/tests.py | 3 + hello/urls.py | 8 ++ hello/views.py | 4 + manage.py | 22 ++++ pyproject.toml | 6 +- uv.lock | 107 ++++++++++++++++- 34 files changed, 750 insertions(+), 5 deletions(-) create mode 100644 config/__init__.py create mode 100644 config/asgi.py create mode 100644 config/settings.py create mode 100644 config/urls.py create mode 100644 config/wsgi.py create mode 100644 events/__init__.py create mode 100644 events/admin.py create mode 100644 events/apps.py create mode 100644 events/forms.py create mode 100644 events/migrations/0001_initial.py create mode 100644 events/migrations/__init__.py create mode 100644 events/models.py create mode 100644 events/templates/events/base.html create mode 100644 events/templates/events/event_detail.html create mode 100644 events/templates/events/event_form.html create mode 100644 events/templates/events/event_list.html create mode 100644 events/templates/events/user_register.html create mode 100644 events/templates/registration/login.html create mode 100644 events/tests.py create mode 100644 events/urls.py create mode 100644 events/views.py create mode 100644 hello.py create mode 100644 hello/__init__.py create mode 100644 hello/admin.py create mode 100644 hello/apps.py create mode 100644 hello/migrations/__init__.py create mode 100644 hello/models.py create mode 100644 hello/templates/hello/index.html create mode 100644 hello/tests.py create mode 100644 hello/urls.py create mode 100644 hello/views.py create mode 100755 manage.py diff --git a/config/__init__.py b/config/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/config/asgi.py b/config/asgi.py new file mode 100644 index 0000000..787b362 --- /dev/null +++ b/config/asgi.py @@ -0,0 +1,16 @@ +""" +ASGI config for config project. + +It exposes the ASGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/4.2/howto/deployment/asgi/ +""" + +import os + +from django.core.asgi import get_asgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings') + +application = get_asgi_application() diff --git a/config/settings.py b/config/settings.py new file mode 100644 index 0000000..bf6ff83 --- /dev/null +++ b/config/settings.py @@ -0,0 +1,129 @@ +""" +Django settings for config project. + +Generated by 'django-admin startproject' using Django 4.2. + +For more information on this file, see +https://docs.djangoproject.com/en/4.2/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/4.2/ref/settings/ +""" + +from pathlib import Path + +# Build paths inside the project like this: BASE_DIR / 'subdir'. +BASE_DIR = Path(__file__).resolve().parent.parent + + +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/4.2/howto/deployment/checklist/ + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = 'django-insecure-o#nbn-&f()kby&qz6+kw8^@r-9(5t-cd!2$(ki086l(d-h2211' + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = True + +ALLOWED_HOSTS = [] + + +# Application definition + +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'events', +] + +AUTH_USER_MODEL = 'events.User' +LOGIN_REDIRECT_URL = 'event_list' +LOGOUT_REDIRECT_URL = 'event_list' + +MIDDLEWARE = [ + 'django.middleware.security.SecurityMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', +] + +ROOT_URLCONF = 'config.urls' + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.debug', + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +] + +WSGI_APPLICATION = 'config.wsgi.application' + + +# Database +# https://docs.djangoproject.com/en/4.2/ref/settings/#databases + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': BASE_DIR / 'db.sqlite3', + } +} + + +# Password validation +# https://docs.djangoproject.com/en/4.2/ref/settings/#auth-password-validators + +AUTH_PASSWORD_VALIDATORS = [ + { + 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', + }, +] + + +# Internationalization +# https://docs.djangoproject.com/en/4.2/topics/i18n/ + +LANGUAGE_CODE = 'en-us' + +TIME_ZONE = 'UTC' + +USE_I18N = True + +USE_TZ = True + + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/4.2/howto/static-files/ + +STATIC_URL = 'static/' + +# Default primary key field type +# https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field + +DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' + diff --git a/config/urls.py b/config/urls.py new file mode 100644 index 0000000..09199ad --- /dev/null +++ b/config/urls.py @@ -0,0 +1,26 @@ +""" +URL configuration for config project. + +The `urlpatterns` list routes URLs to views. For more information please see: + https://docs.djangoproject.com/en/4.2/topics/http/urls/ +Examples: +Function views + 1. Add an import: from my_app import views + 2. Add a URL to urlpatterns: path('', views.home, name='home') +Class-based views + 1. Add an import: from other_app.views import Home + 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') +Including another URLconf + 1. Import the include() function: from django.urls import include, path + 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) +""" +from django.contrib import admin +from django.urls import path, include +from events import views + +urlpatterns = [ + path('admin/', admin.site.urls), + path('', views.event_list, name='event_list'), + path('events/', include('events.urls')), + path('accounts/', include('django.contrib.auth.urls')), +] diff --git a/config/wsgi.py b/config/wsgi.py new file mode 100644 index 0000000..8ae71e3 --- /dev/null +++ b/config/wsgi.py @@ -0,0 +1,16 @@ +""" +WSGI config for config project. + +It exposes the WSGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/4.2/howto/deployment/wsgi/ +""" + +import os + +from django.core.wsgi import get_wsgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings') + +application = get_wsgi_application() diff --git a/events/__init__.py b/events/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/events/admin.py b/events/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/events/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/events/apps.py b/events/apps.py new file mode 100644 index 0000000..20f48f2 --- /dev/null +++ b/events/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class EventsConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'events' diff --git a/events/forms.py b/events/forms.py new file mode 100644 index 0000000..3a23231 --- /dev/null +++ b/events/forms.py @@ -0,0 +1,25 @@ +from django import forms +from .models import Event, User + +class EventForm(forms.ModelForm): + class Meta: + model = Event + fields = ['name', 'description', 'event_date'] + widgets = { + 'event_date': forms.DateTimeInput(attrs={'type': 'datetime-local'}), + } + +class UserRegistrationForm(forms.ModelForm): + password = forms.CharField(widget=forms.PasswordInput) + password_confirmation = forms.CharField(widget=forms.PasswordInput) + + class Meta: + model = User + fields = ['display_name', 'email', 'username'] + + def clean(self): + cleaned_data = super().clean() + if cleaned_data.get('password') != cleaned_data.get('password_confirmation'): + raise forms.ValidationError('パスワードが一致しません') + return cleaned_data + diff --git a/events/migrations/0001_initial.py b/events/migrations/0001_initial.py new file mode 100644 index 0000000..fbb7463 --- /dev/null +++ b/events/migrations/0001_initial.py @@ -0,0 +1,75 @@ +# Generated by Django 4.2 on 2025-01-17 15:14 + +from django.conf import settings +import django.contrib.auth.models +import django.contrib.auth.validators +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('auth', '0012_alter_user_first_name_max_length'), + ] + + operations = [ + migrations.CreateModel( + name='User', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('password', models.CharField(max_length=128, verbose_name='password')), + ('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')), + ('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')), + ('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=150, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='username')), + ('first_name', models.CharField(blank=True, max_length=150, verbose_name='first name')), + ('last_name', models.CharField(blank=True, max_length=150, verbose_name='last name')), + ('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')), + ('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')), + ('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')), + ('display_name', models.CharField(max_length=100)), + ('email', models.EmailField(max_length=254, unique=True)), + ('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.group', verbose_name='groups')), + ('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.permission', verbose_name='user permissions')), + ], + options={ + 'verbose_name': 'user', + 'verbose_name_plural': 'users', + 'abstract': False, + }, + managers=[ + ('objects', django.contrib.auth.models.UserManager()), + ], + ), + migrations.CreateModel( + name='Event', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=200)), + ('description', models.TextField()), + ('event_date', models.DateTimeField()), + ('created_at', models.DateTimeField(default=django.utils.timezone.now)), + ('organizer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='organized_events', to=settings.AUTH_USER_MODEL)), + ], + ), + migrations.CreateModel( + name='EventParticipation', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('registered_at', models.DateTimeField(default=django.utils.timezone.now)), + ('event', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='events.event')), + ('participant', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ], + options={ + 'unique_together': {('event', 'participant')}, + }, + ), + migrations.AddField( + model_name='event', + name='participants', + field=models.ManyToManyField(related_name='participating_events', through='events.EventParticipation', to=settings.AUTH_USER_MODEL), + ), + ] diff --git a/events/migrations/__init__.py b/events/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/events/models.py b/events/models.py new file mode 100644 index 0000000..7a092e2 --- /dev/null +++ b/events/models.py @@ -0,0 +1,30 @@ +from django.db import models +from django.contrib.auth.models import AbstractUser +from django.utils import timezone + +class User(AbstractUser): + display_name = models.CharField(max_length=100) + email = models.EmailField(unique=True) + + def __str__(self): + return self.display_name + +class Event(models.Model): + name = models.CharField(max_length=200) + description = models.TextField() + organizer = models.ForeignKey(User, on_delete=models.CASCADE, related_name='organized_events') + event_date = models.DateTimeField() + created_at = models.DateTimeField(default=timezone.now) + participants = models.ManyToManyField(User, through='EventParticipation', related_name='participating_events') + + def __str__(self): + return self.name + +class EventParticipation(models.Model): + event = models.ForeignKey(Event, on_delete=models.CASCADE) + participant = models.ForeignKey(User, on_delete=models.CASCADE) + registered_at = models.DateTimeField(default=timezone.now) + + class Meta: + unique_together = ('event', 'participant') + diff --git a/events/templates/events/base.html b/events/templates/events/base.html new file mode 100644 index 0000000..37e278b --- /dev/null +++ b/events/templates/events/base.html @@ -0,0 +1,41 @@ + + + + + {% block title %}イベント管理システム{% endblock %} + + + + + +
+ {% if messages %} + {% for message in messages %} +
+ {{ message }} +
+ {% endfor %} + {% endif %} + + {% block content %} + {% endblock %} +
+ + + + + diff --git a/events/templates/events/event_detail.html b/events/templates/events/event_detail.html new file mode 100644 index 0000000..7b28bdf --- /dev/null +++ b/events/templates/events/event_detail.html @@ -0,0 +1,33 @@ + +{% extends 'events/base.html' %} + +{% block title %}{{ event.name }}{% endblock %} + +{% block content %} +
+
+

{{ event.name }}

+

{{ event.description }}

+

+ 主催者: {{ event.organizer.display_name }}
+ 開催日時: {{ event.event_date }}
+ 作成日時: {{ event.created_at }} +

+ + {% if user.is_authenticated and not is_participant %} +
+ {% csrf_token %} + +
+ {% endif %} + +

参加者一覧

+
    + {% for participant in participants %} +
  • {{ participant.display_name }}
  • + {% endfor %} +
+
+
+{% endblock %} + diff --git a/events/templates/events/event_form.html b/events/templates/events/event_form.html new file mode 100644 index 0000000..5b75791 --- /dev/null +++ b/events/templates/events/event_form.html @@ -0,0 +1,25 @@ + +{% extends 'events/base.html' %} + +{% block title %}イベント作成{% endblock %} + +{% block content %} +

イベント作成

+
+ {% csrf_token %} +
+ {{ form.name.label_tag }} + {{ form.name }} +
+
+ {{ form.description.label_tag }} + {{ form.description }} +
+
+ {{ form.event_date.label_tag }} + {{ form.event_date }} +
+ +
+{% endblock %} + diff --git a/events/templates/events/event_list.html b/events/templates/events/event_list.html new file mode 100644 index 0000000..f397d84 --- /dev/null +++ b/events/templates/events/event_list.html @@ -0,0 +1,28 @@ + +{% extends 'events/base.html' %} + +{% block title %}イベント一覧{% endblock %} + +{% block content %} +

イベント一覧

+
+ {% for event in events %} +
+
+
+
{{ event.name }}
+

{{ event.description|truncatewords:30 }}

+

+ + 主催者: {{ event.organizer.display_name }}
+ 開催日時: {{ event.event_date }} +
+

+ 詳細を見る +
+
+
+ {% endfor %} +
+{% endblock %} + diff --git a/events/templates/events/user_register.html b/events/templates/events/user_register.html new file mode 100644 index 0000000..3c8ed43 --- /dev/null +++ b/events/templates/events/user_register.html @@ -0,0 +1,33 @@ + +{% extends 'events/base.html' %} + +{% block title %}ユーザー登録{% endblock %} + +{% block content %} +

ユーザー登録

+
+ {% csrf_token %} +
+ {{ form.display_name.label_tag }} + {{ form.display_name }} +
+
+ {{ form.email.label_tag }} + {{ form.email }} +
+
+ {{ form.username.label_tag }} + {{ form.username }} +
+
+ {{ form.password.label_tag }} + {{ form.password }} +
+
+ {{ form.password_confirmation.label_tag }} + {{ form.password_confirmation }} +
+ +
+{% endblock %} + diff --git a/events/templates/registration/login.html b/events/templates/registration/login.html new file mode 100644 index 0000000..97ef482 --- /dev/null +++ b/events/templates/registration/login.html @@ -0,0 +1,24 @@ + +{% extends 'events/base.html' %} + +{% block title %}ログイン{% endblock %} + +{% block content %} +

ログイン

+
+ {% csrf_token %} +
+ + +
+
+ + +
+ +
+

+ アカウントをお持ちでない方はこちらから登録してください。 +

+{% endblock %} + diff --git a/events/tests.py b/events/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/events/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/events/urls.py b/events/urls.py new file mode 100644 index 0000000..4c00cfe --- /dev/null +++ b/events/urls.py @@ -0,0 +1,10 @@ +from django.urls import path +from . import views + +urlpatterns = [ + path('create/', views.event_create, name='event_create'), + path('/', views.event_detail, name='event_detail'), + path('/participate/', views.event_participate, name='event_participate'), + path('register/', views.user_register, name='user_register'), +] + diff --git a/events/views.py b/events/views.py new file mode 100644 index 0000000..57ad2b9 --- /dev/null +++ b/events/views.py @@ -0,0 +1,54 @@ +from django.shortcuts import render, redirect, get_object_or_404 +from django.contrib.auth.decorators import login_required +from django.contrib import messages +from .models import Event, EventParticipation +from .forms import EventForm, UserRegistrationForm + +def event_list(request): + events = Event.objects.all().order_by('-event_date') + return render(request, 'events/event_list.html', {'events': events}) + +@login_required +def event_create(request): + if request.method == 'POST': + form = EventForm(request.POST) + if form.is_valid(): + event = form.save(commit=False) + event.organizer = request.user + event.save() + return redirect('event_detail', event_id=event.id) + else: + form = EventForm() + return render(request, 'events/event_form.html', {'form': form}) + +def event_detail(request, event_id): + event = get_object_or_404(Event, id=event_id) + participants = event.participants.all() + is_participant = request.user.is_authenticated and event.participants.filter(id=request.user.id).exists() + return render(request, 'events/event_detail.html', { + 'event': event, + 'participants': participants, + 'is_participant': is_participant + }) + +@login_required +def event_participate(request, event_id): + event = get_object_or_404(Event, id=event_id) + if not EventParticipation.objects.filter(event=event, participant=request.user).exists(): + EventParticipation.objects.create(event=event, participant=request.user) + messages.success(request, 'イベントへの参加が完了しました') + return redirect('event_detail', event_id=event.id) + +def user_register(request): + if request.method == 'POST': + form = UserRegistrationForm(request.POST) + if form.is_valid(): + user = form.save(commit=False) + user.set_password(form.cleaned_data['password']) + user.save() + messages.success(request, 'ユーザー登録が完了しました') + return redirect('login') + else: + form = UserRegistrationForm() + return render(request, 'events/user_register.html', {'form': form}) + diff --git a/hello.py b/hello.py new file mode 100644 index 0000000..21b6854 --- /dev/null +++ b/hello.py @@ -0,0 +1,6 @@ +def main(): + print("Hello from pyhack!") + + +if __name__ == "__main__": + main() diff --git a/hello/__init__.py b/hello/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/hello/admin.py b/hello/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/hello/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/hello/apps.py b/hello/apps.py new file mode 100644 index 0000000..bfc55f0 --- /dev/null +++ b/hello/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class HelloConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'hello' diff --git a/hello/migrations/__init__.py b/hello/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/hello/models.py b/hello/models.py new file mode 100644 index 0000000..71a8362 --- /dev/null +++ b/hello/models.py @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. diff --git a/hello/templates/hello/index.html b/hello/templates/hello/index.html new file mode 100644 index 0000000..2bc8e3b --- /dev/null +++ b/hello/templates/hello/index.html @@ -0,0 +1,10 @@ + + + + Hello World + + +

Hello World

+ + + diff --git a/hello/tests.py b/hello/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/hello/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/hello/urls.py b/hello/urls.py new file mode 100644 index 0000000..19c1fd1 --- /dev/null +++ b/hello/urls.py @@ -0,0 +1,8 @@ +from django.urls import path +from . import views + +app_name = 'hello' +urlpatterns = [ + path('', views.index, name='index'), +] + diff --git a/hello/views.py b/hello/views.py new file mode 100644 index 0000000..3aa4536 --- /dev/null +++ b/hello/views.py @@ -0,0 +1,4 @@ +from django.shortcuts import render + +def index(request): + return render(request, 'hello/index.html') diff --git a/manage.py b/manage.py new file mode 100755 index 0000000..8e7ac79 --- /dev/null +++ b/manage.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python +"""Django's command-line utility for administrative tasks.""" +import os +import sys + + +def main(): + """Run administrative tasks.""" + os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings') + try: + from django.core.management import execute_from_command_line + except ImportError as exc: + raise ImportError( + "Couldn't import Django. Are you sure it's installed and " + "available on your PYTHONPATH environment variable? Did you " + "forget to activate a virtual environment?" + ) from exc + execute_from_command_line(sys.argv) + + +if __name__ == '__main__': + main() diff --git a/pyproject.toml b/pyproject.toml index d074d89..78876d5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,5 +5,9 @@ description = "Add your description here" readme = "README.md" requires-python = ">=3.12" dependencies = [ - "django>=5.1.5", + "django==4.2", + "django-ninja>=1.3.0", ] + +[tool.uv.workspace] +members = ["pyhack"] diff --git a/uv.lock b/uv.lock index 130c4c0..26d3587 100644 --- a/uv.lock +++ b/uv.lock @@ -1,6 +1,21 @@ version = 1 requires-python = ">=3.12" +[manifest] +members = [ + "demo-ai-django-pyhack", + "pyhack", +] + +[[package]] +name = "annotated-types" +version = "0.7.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ee/67/531ea369ba64dcff5ec9c3402f9f51bf748cec26dde048a2f973a4eea7f5/annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89", size = 16081 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643 }, +] + [[package]] name = "asgiref" version = "3.8.1" @@ -16,25 +31,100 @@ version = "0.1.0" source = { virtual = "." } dependencies = [ { name = "django" }, + { name = "django-ninja" }, ] [package.metadata] -requires-dist = [{ name = "django", specifier = ">=5.1.5" }] +requires-dist = [ + { name = "django", specifier = "==4.2" }, + { name = "django-ninja", specifier = ">=1.3.0" }, +] [[package]] name = "django" -version = "5.1.5" +version = "4.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "asgiref" }, { name = "sqlparse" }, { name = "tzdata", marker = "sys_platform == 'win32'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/e4/17/834e3e08d590dcc27d4cc3c5cd4e2fb757b7a92bab9de8ee402455732952/Django-5.1.5.tar.gz", hash = "sha256:19bbca786df50b9eca23cee79d495facf55c8f5c54c529d9bf1fe7b5ea086af3", size = 10700031 } +sdist = { url = "https://files.pythonhosted.org/packages/9a/bb/48aa3e0850923096dff2766d21a6004d6e1a3317f0bd400ba81f586754e1/Django-4.2.tar.gz", hash = "sha256:c36e2ab12824e2ac36afa8b2515a70c53c7742f0d6eaefa7311ec379558db997", size = 10415665 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d9/40/6012f98b14b64b4d3dc47b0c2f116fccbd0795ab35515d0c40dac73b81b8/Django-4.2-py3-none-any.whl", hash = "sha256:ad33ed68db9398f5dfb33282704925bce044bef4261cd4fb59e4e7f9ae505a78", size = 7988617 }, +] + +[[package]] +name = "django-ninja" +version = "1.3.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "django" }, + { name = "pydantic" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/9c/77/89ee4ebaa5151b7d85cebaf8d6ec0b9e5074326c3ad8259c763763306d51/django_ninja-1.3.0.tar.gz", hash = "sha256:5b320e2dc0f41a6032bfa7e1ebc33559ae1e911a426f0c6be6674a50b20819be", size = 3702324 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/00/72/fd2589323b40893d3224e174eeec0c4ce5a42c7d2d384d11ba269ad4d050/django_ninja-1.3.0-py3-none-any.whl", hash = "sha256:f58096b6c767d1403dfd6c49743f82d780d7b9688d9302ecab316ac1fa6131bb", size = 2423381 }, +] + +[[package]] +name = "pydantic" +version = "2.10.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "annotated-types" }, + { name = "pydantic-core" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/6a/c7/ca334c2ef6f2e046b1144fe4bb2a5da8a4c574e7f2ebf7e16b34a6a2fa92/pydantic-2.10.5.tar.gz", hash = "sha256:278b38dbbaec562011d659ee05f63346951b3a248a6f3642e1bc68894ea2b4ff", size = 761287 } wheels = [ - { url = "https://files.pythonhosted.org/packages/11/e6/e92c8c788b83d109f34d933c5e817095d85722719cb4483472abc135f44e/Django-5.1.5-py3-none-any.whl", hash = "sha256:c46eb936111fffe6ec4bc9930035524a8be98ec2f74d8a0ff351226a3e52f459", size = 8276957 }, + { url = "https://files.pythonhosted.org/packages/58/26/82663c79010b28eddf29dcdd0ea723439535fa917fce5905885c0e9ba562/pydantic-2.10.5-py3-none-any.whl", hash = "sha256:4dd4e322dbe55472cb7ca7e73f4b63574eecccf2835ffa2af9021ce113c83c53", size = 431426 }, ] +[[package]] +name = "pydantic-core" +version = "2.27.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/fc/01/f3e5ac5e7c25833db5eb555f7b7ab24cd6f8c322d3a3ad2d67a952dc0abc/pydantic_core-2.27.2.tar.gz", hash = "sha256:eb026e5a4c1fee05726072337ff51d1efb6f59090b7da90d30ea58625b1ffb39", size = 413443 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d6/74/51c8a5482ca447871c93e142d9d4a92ead74de6c8dc5e66733e22c9bba89/pydantic_core-2.27.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:9e0c8cfefa0ef83b4da9588448b6d8d2a2bf1a53c3f1ae5fca39eb3061e2f0b0", size = 1893127 }, + { url = "https://files.pythonhosted.org/packages/d3/f3/c97e80721735868313c58b89d2de85fa80fe8dfeeed84dc51598b92a135e/pydantic_core-2.27.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:83097677b8e3bd7eaa6775720ec8e0405f1575015a463285a92bfdfe254529ef", size = 1811340 }, + { url = "https://files.pythonhosted.org/packages/9e/91/840ec1375e686dbae1bd80a9e46c26a1e0083e1186abc610efa3d9a36180/pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:172fce187655fece0c90d90a678424b013f8fbb0ca8b036ac266749c09438cb7", size = 1822900 }, + { url = "https://files.pythonhosted.org/packages/f6/31/4240bc96025035500c18adc149aa6ffdf1a0062a4b525c932065ceb4d868/pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:519f29f5213271eeeeb3093f662ba2fd512b91c5f188f3bb7b27bc5973816934", size = 1869177 }, + { url = "https://files.pythonhosted.org/packages/fa/20/02fbaadb7808be578317015c462655c317a77a7c8f0ef274bc016a784c54/pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:05e3a55d124407fffba0dd6b0c0cd056d10e983ceb4e5dbd10dda135c31071d6", size = 2038046 }, + { url = "https://files.pythonhosted.org/packages/06/86/7f306b904e6c9eccf0668248b3f272090e49c275bc488a7b88b0823444a4/pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9c3ed807c7b91de05e63930188f19e921d1fe90de6b4f5cd43ee7fcc3525cb8c", size = 2685386 }, + { url = "https://files.pythonhosted.org/packages/8d/f0/49129b27c43396581a635d8710dae54a791b17dfc50c70164866bbf865e3/pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6fb4aadc0b9a0c063206846d603b92030eb6f03069151a625667f982887153e2", size = 1997060 }, + { url = "https://files.pythonhosted.org/packages/0d/0f/943b4af7cd416c477fd40b187036c4f89b416a33d3cc0ab7b82708a667aa/pydantic_core-2.27.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:28ccb213807e037460326424ceb8b5245acb88f32f3d2777427476e1b32c48c4", size = 2004870 }, + { url = "https://files.pythonhosted.org/packages/35/40/aea70b5b1a63911c53a4c8117c0a828d6790483f858041f47bab0b779f44/pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:de3cd1899e2c279b140adde9357c4495ed9d47131b4a4eaff9052f23398076b3", size = 1999822 }, + { url = "https://files.pythonhosted.org/packages/f2/b3/807b94fd337d58effc5498fd1a7a4d9d59af4133e83e32ae39a96fddec9d/pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:220f892729375e2d736b97d0e51466252ad84c51857d4d15f5e9692f9ef12be4", size = 2130364 }, + { url = "https://files.pythonhosted.org/packages/fc/df/791c827cd4ee6efd59248dca9369fb35e80a9484462c33c6649a8d02b565/pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a0fcd29cd6b4e74fe8ddd2c90330fd8edf2e30cb52acda47f06dd615ae72da57", size = 2158303 }, + { url = "https://files.pythonhosted.org/packages/9b/67/4e197c300976af185b7cef4c02203e175fb127e414125916bf1128b639a9/pydantic_core-2.27.2-cp312-cp312-win32.whl", hash = "sha256:1e2cb691ed9834cd6a8be61228471d0a503731abfb42f82458ff27be7b2186fc", size = 1834064 }, + { url = "https://files.pythonhosted.org/packages/1f/ea/cd7209a889163b8dcca139fe32b9687dd05249161a3edda62860430457a5/pydantic_core-2.27.2-cp312-cp312-win_amd64.whl", hash = "sha256:cc3f1a99a4f4f9dd1de4fe0312c114e740b5ddead65bb4102884b384c15d8bc9", size = 1989046 }, + { url = "https://files.pythonhosted.org/packages/bc/49/c54baab2f4658c26ac633d798dab66b4c3a9bbf47cff5284e9c182f4137a/pydantic_core-2.27.2-cp312-cp312-win_arm64.whl", hash = "sha256:3911ac9284cd8a1792d3cb26a2da18f3ca26c6908cc434a18f730dc0db7bfa3b", size = 1885092 }, + { url = "https://files.pythonhosted.org/packages/41/b1/9bc383f48f8002f99104e3acff6cba1231b29ef76cfa45d1506a5cad1f84/pydantic_core-2.27.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:7d14bd329640e63852364c306f4d23eb744e0f8193148d4044dd3dacdaacbd8b", size = 1892709 }, + { url = "https://files.pythonhosted.org/packages/10/6c/e62b8657b834f3eb2961b49ec8e301eb99946245e70bf42c8817350cbefc/pydantic_core-2.27.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:82f91663004eb8ed30ff478d77c4d1179b3563df6cdb15c0817cd1cdaf34d154", size = 1811273 }, + { url = "https://files.pythonhosted.org/packages/ba/15/52cfe49c8c986e081b863b102d6b859d9defc63446b642ccbbb3742bf371/pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:71b24c7d61131bb83df10cc7e687433609963a944ccf45190cfc21e0887b08c9", size = 1823027 }, + { url = "https://files.pythonhosted.org/packages/b1/1c/b6f402cfc18ec0024120602bdbcebc7bdd5b856528c013bd4d13865ca473/pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fa8e459d4954f608fa26116118bb67f56b93b209c39b008277ace29937453dc9", size = 1868888 }, + { url = "https://files.pythonhosted.org/packages/bd/7b/8cb75b66ac37bc2975a3b7de99f3c6f355fcc4d89820b61dffa8f1e81677/pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce8918cbebc8da707ba805b7fd0b382816858728ae7fe19a942080c24e5b7cd1", size = 2037738 }, + { url = "https://files.pythonhosted.org/packages/c8/f1/786d8fe78970a06f61df22cba58e365ce304bf9b9f46cc71c8c424e0c334/pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:eda3f5c2a021bbc5d976107bb302e0131351c2ba54343f8a496dc8783d3d3a6a", size = 2685138 }, + { url = "https://files.pythonhosted.org/packages/a6/74/d12b2cd841d8724dc8ffb13fc5cef86566a53ed358103150209ecd5d1999/pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bd8086fa684c4775c27f03f062cbb9eaa6e17f064307e86b21b9e0abc9c0f02e", size = 1997025 }, + { url = "https://files.pythonhosted.org/packages/a0/6e/940bcd631bc4d9a06c9539b51f070b66e8f370ed0933f392db6ff350d873/pydantic_core-2.27.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8d9b3388db186ba0c099a6d20f0604a44eabdeef1777ddd94786cdae158729e4", size = 2004633 }, + { url = "https://files.pythonhosted.org/packages/50/cc/a46b34f1708d82498c227d5d80ce615b2dd502ddcfd8376fc14a36655af1/pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:7a66efda2387de898c8f38c0cf7f14fca0b51a8ef0b24bfea5849f1b3c95af27", size = 1999404 }, + { url = "https://files.pythonhosted.org/packages/ca/2d/c365cfa930ed23bc58c41463bae347d1005537dc8db79e998af8ba28d35e/pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:18a101c168e4e092ab40dbc2503bdc0f62010e95d292b27827871dc85450d7ee", size = 2130130 }, + { url = "https://files.pythonhosted.org/packages/f4/d7/eb64d015c350b7cdb371145b54d96c919d4db516817f31cd1c650cae3b21/pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ba5dd002f88b78a4215ed2f8ddbdf85e8513382820ba15ad5ad8955ce0ca19a1", size = 2157946 }, + { url = "https://files.pythonhosted.org/packages/a4/99/bddde3ddde76c03b65dfd5a66ab436c4e58ffc42927d4ff1198ffbf96f5f/pydantic_core-2.27.2-cp313-cp313-win32.whl", hash = "sha256:1ebaf1d0481914d004a573394f4be3a7616334be70261007e47c2a6fe7e50130", size = 1834387 }, + { url = "https://files.pythonhosted.org/packages/71/47/82b5e846e01b26ac6f1893d3c5f9f3a2eb6ba79be26eef0b759b4fe72946/pydantic_core-2.27.2-cp313-cp313-win_amd64.whl", hash = "sha256:953101387ecf2f5652883208769a79e48db18c6df442568a0b5ccd8c2723abee", size = 1990453 }, + { url = "https://files.pythonhosted.org/packages/51/b2/b2b50d5ecf21acf870190ae5d093602d95f66c9c31f9d5de6062eb329ad1/pydantic_core-2.27.2-cp313-cp313-win_arm64.whl", hash = "sha256:ac4dbfd1691affb8f48c2c13241a2e3b60ff23247cbcf981759c768b6633cf8b", size = 1885186 }, +] + +[[package]] +name = "pyhack" +version = "0.1.0" +source = { virtual = "pyhack" } + [[package]] name = "sqlparse" version = "0.5.3" @@ -44,6 +134,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/a9/5c/bfd6bd0bf979426d405cc6e71eceb8701b148b16c21d2dc3c261efc61c7b/sqlparse-0.5.3-py3-none-any.whl", hash = "sha256:cf2196ed3418f3ba5de6af7e82c694a9fbdbfecccdfc72e281548517081f16ca", size = 44415 }, ] +[[package]] +name = "typing-extensions" +version = "4.12.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/df/db/f35a00659bc03fec321ba8bce9420de607a1d37f8342eee1863174c69557/typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8", size = 85321 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/26/9f/ad63fc0248c5379346306f8668cda6e2e2e9c95e01216d2b8ffd9ff037d0/typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d", size = 37438 }, +] + [[package]] name = "tzdata" version = "2024.2"