From f67f8d2b69f20299c1b535d65518434a8281498f Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Mon, 27 Mar 2023 09:18:09 +0300 Subject: [PATCH 001/144] Updated automatic tests --- tox.ini | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/tox.ini b/tox.ini index da224ca..0e5c0d3 100644 --- a/tox.ini +++ b/tox.ini @@ -1,20 +1,14 @@ [tox] minversion = 3.8.0 -envlist = py310, flake8, mypy +envlist = django, flake8, mypy isolated_build = true [gh-actions] python = - 3.10: py310, mypy, flake8 - -; [testenv] -; setenv = -; PYTHONPATH = {toxinidir} -; deps = -; -r{toxinidir}/requirements_dev.txt + 3.10: django, mypy, flake8 -[testenv] +[testenv:django] basepython = python3.10 deps = django commands = python manage.py test From f3e4cb2652e860b57062ac0a3733cdf64bdb6da3 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Mon, 27 Mar 2023 09:19:44 +0300 Subject: [PATCH 002/144] Added automatic tests to github workflows --- .github/workflows/lint.yml | 23 ----------------------- .github/workflows/test.yml | 4 ++-- 2 files changed, 2 insertions(+), 25 deletions(-) delete mode 100644 .github/workflows/lint.yml diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml deleted file mode 100644 index 776c8ea..0000000 --- a/.github/workflows/lint.yml +++ /dev/null @@ -1,23 +0,0 @@ -name: Lint -on: - - push - - pull_request -jobs: - test: - runs-on: ${{ matrix.os }} - strategy: - matrix: - os: [ubuntu-latest, windows-latest] - python-version: ["3.10"] - steps: - - uses: actions/checkout@v2 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 - with: - python-version: ${{ matrix.python-version }} - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install tox tox-gh-actions - - name: Lint with tox - run: tox diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 81c4998..25fa3fb 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -18,6 +18,6 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install django + pip install tox tox-gh-actions - name: Lint with tox - run: python manage.py test + run: tox From 6dc7acbd7ca0e5d99e3cd4c014b7c0f77baaf7a6 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Mon, 27 Mar 2023 09:23:17 +0300 Subject: [PATCH 003/144] Changes `'` to `"` --- FOSSDB_web/apps/fossdb/apps.py | 4 ++-- FOSSDB_web/urls.py | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/FOSSDB_web/apps/fossdb/apps.py b/FOSSDB_web/apps/fossdb/apps.py index 6c8b002..ba8e8cd 100644 --- a/FOSSDB_web/apps/fossdb/apps.py +++ b/FOSSDB_web/apps/fossdb/apps.py @@ -2,5 +2,5 @@ from django.apps import AppConfig class FossdbConfig(AppConfig): - default_auto_field = 'django.db.models.BigAutoField' - name = 'fossdb' + default_auto_field = "django.db.models.BigAutoField" + name = "fossdb" diff --git a/FOSSDB_web/urls.py b/FOSSDB_web/urls.py index 4025788..3d97689 100644 --- a/FOSSDB_web/urls.py +++ b/FOSSDB_web/urls.py @@ -1,17 +1,17 @@ -"""OSSDB_web URL Configuration +"""FOSSDB_web URL Configuration The `urlpatterns` list routes URLs to views. For more information please see: https://docs.djangoproject.com/en/4.0/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') + 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') + 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')) + 2. Add a URL to urlpatterns: path("blog/", include("blog.urls")) """ from django.contrib import admin from django.urls import path From c3a3d67752e1733b6fd151dbd76de480239b3bf2 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Mon, 27 Mar 2023 20:25:32 +0300 Subject: [PATCH 004/144] Created user registration form --- FOSSDB_web/apps/account/__init__.py | 0 FOSSDB_web/apps/account/admin.py | 3 +++ FOSSDB_web/apps/account/apps.py | 6 ++++++ FOSSDB_web/apps/account/forms.py | 11 +++++++++++ FOSSDB_web/apps/account/tests.py | 3 +++ FOSSDB_web/apps/account/urls.py | 9 +++++++++ FOSSDB_web/apps/account/views.py | 20 ++++++++++++++++++++ FOSSDB_web/settings.py | 2 +- FOSSDB_web/urls.py | 4 +++- 9 files changed, 56 insertions(+), 2 deletions(-) create mode 100644 FOSSDB_web/apps/account/__init__.py create mode 100644 FOSSDB_web/apps/account/admin.py create mode 100644 FOSSDB_web/apps/account/apps.py create mode 100644 FOSSDB_web/apps/account/forms.py create mode 100644 FOSSDB_web/apps/account/tests.py create mode 100644 FOSSDB_web/apps/account/urls.py create mode 100644 FOSSDB_web/apps/account/views.py diff --git a/FOSSDB_web/apps/account/__init__.py b/FOSSDB_web/apps/account/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/FOSSDB_web/apps/account/admin.py b/FOSSDB_web/apps/account/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/FOSSDB_web/apps/account/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/FOSSDB_web/apps/account/apps.py b/FOSSDB_web/apps/account/apps.py new file mode 100644 index 0000000..2c684a9 --- /dev/null +++ b/FOSSDB_web/apps/account/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class AccountConfig(AppConfig): + default_auto_field = "django.db.models.BigAutoField" + name = "account" diff --git a/FOSSDB_web/apps/account/forms.py b/FOSSDB_web/apps/account/forms.py new file mode 100644 index 0000000..1b47e64 --- /dev/null +++ b/FOSSDB_web/apps/account/forms.py @@ -0,0 +1,11 @@ +from django import forms +from django.contrib.auth.forms import UserCreationForm +from django.contrib.auth.models import User + + +class RegisterForm(UserCreationForm): + email = forms.EmailField(required=True) + + class Meta: + model = User + fields = ["username", "email", "password1", "password2"] diff --git a/FOSSDB_web/apps/account/tests.py b/FOSSDB_web/apps/account/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/FOSSDB_web/apps/account/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/FOSSDB_web/apps/account/urls.py b/FOSSDB_web/apps/account/urls.py new file mode 100644 index 0000000..8fa14e8 --- /dev/null +++ b/FOSSDB_web/apps/account/urls.py @@ -0,0 +1,9 @@ +from django.urls import path + +from . import views + +urlpatterns = [ + path("", views.sign_up, name="singup"), + path("signup", views.sign_up, name="signup"), + path("login", views.login_, name="login"), +] diff --git a/FOSSDB_web/apps/account/views.py b/FOSSDB_web/apps/account/views.py new file mode 100644 index 0000000..db7ddd5 --- /dev/null +++ b/FOSSDB_web/apps/account/views.py @@ -0,0 +1,20 @@ +from django.contrib.auth import login +from django.shortcuts import redirect, render + +from .forms import RegisterForm + + +def sign_up(request): + if request.method == "POST": + form = RegisterForm(request.POST) + if form.is_valid(): + user = form.save() + login(request, user) + return redirect("/") + else: + form = RegisterForm() + return render(request, "registration/sign_up.html", {"form": form}) + + +def login_(request): + return render(request, "registration/login.html") diff --git a/FOSSDB_web/settings.py b/FOSSDB_web/settings.py index 34fb5ca..cd26433 100644 --- a/FOSSDB_web/settings.py +++ b/FOSSDB_web/settings.py @@ -24,7 +24,6 @@ DEBUG = BASE_PATH.joinpath("debug").is_file() # Quick-start development settings - unsuitable for production # See https://docs.djangoproject.com/en/4.0/howto/deployment/checklist/ - with open(BASE_PATH.joinpath("config.json"), "r", encoding="UTF-8") as config_file: config = json.load(config_file) @@ -37,6 +36,7 @@ ALLOWED_HOSTS = config["ALLOWED_HOSTS"] # Application definition INSTALLED_APPS = [ + "account", "django.contrib.admin", "django.contrib.auth", "django.contrib.contenttypes", diff --git a/FOSSDB_web/urls.py b/FOSSDB_web/urls.py index 3d97689..4e84863 100644 --- a/FOSSDB_web/urls.py +++ b/FOSSDB_web/urls.py @@ -14,8 +14,10 @@ Including another URLconf 2. Add a URL to urlpatterns: path("blog/", include("blog.urls")) """ from django.contrib import admin -from django.urls import path +from django.urls import include, path urlpatterns = [ path("admin/", admin.site.urls), + path("", include("django.contrib.auth.urls")), + path("account/", include("account.urls")), ] From be727ce4ebfe2d63da6f63bbdb750e9ad4e6c990 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Mon, 27 Mar 2023 20:26:05 +0300 Subject: [PATCH 005/144] Changed default timezone --- FOSSDB_web/settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FOSSDB_web/settings.py b/FOSSDB_web/settings.py index cd26433..ace8085 100644 --- a/FOSSDB_web/settings.py +++ b/FOSSDB_web/settings.py @@ -115,7 +115,7 @@ AUTH_PASSWORD_VALIDATORS = [ LANGUAGE_CODE = "en-us" -TIME_ZONE = "Europe/Riga" +TIME_ZONE = "UTC" USE_I18N = True From 5448d0e624dbda5f2ce1fb128cdec71ec36a643e Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Mon, 27 Mar 2023 20:26:19 +0300 Subject: [PATCH 006/144] Set login/logout redirect --- FOSSDB_web/settings.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/FOSSDB_web/settings.py b/FOSSDB_web/settings.py index ace8085..e18612d 100644 --- a/FOSSDB_web/settings.py +++ b/FOSSDB_web/settings.py @@ -133,3 +133,5 @@ MEDIA_ROOT = BASE_PATH.joinpath("media") # https://docs.djangoproject.com/en/4.0/ref/settings/#default-auto-field DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField" +LOGIN_REDIRECT_URL = "" +LOGOUT_REDIRECT_URL = "" From 7dd314b08cdbd7a907cdb54c02fa443876082c40 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Mon, 27 Mar 2023 20:48:27 +0300 Subject: [PATCH 007/144] Created `Project` model --- FOSSDB_web/apps/fossdb/forms.py | 9 +++++++++ FOSSDB_web/apps/fossdb/models.py | 14 +++++++++++++- FOSSDB_web/apps/fossdb/urls.py | 7 +++++++ FOSSDB_web/apps/fossdb/views.py | 26 ++++++++++++++++++++++++-- FOSSDB_web/settings.py | 1 + FOSSDB_web/urls.py | 8 +++++++- 6 files changed, 61 insertions(+), 4 deletions(-) create mode 100644 FOSSDB_web/apps/fossdb/forms.py create mode 100644 FOSSDB_web/apps/fossdb/urls.py diff --git a/FOSSDB_web/apps/fossdb/forms.py b/FOSSDB_web/apps/fossdb/forms.py new file mode 100644 index 0000000..9603689 --- /dev/null +++ b/FOSSDB_web/apps/fossdb/forms.py @@ -0,0 +1,9 @@ +from django import forms + +from .models import Project + + +class ProjectForm(forms.ModelForm): + class Meta: + model = Project + fields = ["title", "description"] diff --git a/FOSSDB_web/apps/fossdb/models.py b/FOSSDB_web/apps/fossdb/models.py index 71a8362..e61e920 100644 --- a/FOSSDB_web/apps/fossdb/models.py +++ b/FOSSDB_web/apps/fossdb/models.py @@ -1,3 +1,15 @@ +from django.contrib.auth.models import User from django.db import models -# Create your models here. + +class Project(models.Model): + author = models.ForeignKey(User, on_delete=models.CASCADE) + title = models.CharField(max_length=255) + description = models.TextField() + create_date = models.DateTimeField(auto_now_add=True) + + def __str__(self): + return self.repo_name + + def get_absolute_url(self): + return f"/projects/{self.id}" diff --git a/FOSSDB_web/apps/fossdb/urls.py b/FOSSDB_web/apps/fossdb/urls.py new file mode 100644 index 0000000..2d9cdc0 --- /dev/null +++ b/FOSSDB_web/apps/fossdb/urls.py @@ -0,0 +1,7 @@ +from django.urls import path + +from . import views + +urlpatterns = [ + path("", views.index, name="index") +] diff --git a/FOSSDB_web/apps/fossdb/views.py b/FOSSDB_web/apps/fossdb/views.py index 91ea44a..c84bc6a 100644 --- a/FOSSDB_web/apps/fossdb/views.py +++ b/FOSSDB_web/apps/fossdb/views.py @@ -1,3 +1,25 @@ -from django.shortcuts import render +from django.contrib.auth.decorators import login_required, permission_required +from django.shortcuts import redirect, render -# Create your views here. +from .forms import ProjectForm +from .models import Project + + +def index(request): + projects = Project.objects.all() + return render(request, "fossdb/index.html", {"title": "FOSSDB", "projects": projects}) + + +@login_required(login_url="account/login/") +@permission_required("fossdb.add_post)", login_url="account/login/", raise_exception=True) +def create_project(request): + if request.method == "POST": + project = ProjectForm(request.POST) + if project.is_valid(): + post = project.save(commit=False) + post.author = request.user + post.save() + return redirect("") + else: + project = ProjectForm() + return render(request, "main/create_project.html", {"title": "Add project", "form": project}) diff --git a/FOSSDB_web/settings.py b/FOSSDB_web/settings.py index 34fb5ca..ba3d2d0 100644 --- a/FOSSDB_web/settings.py +++ b/FOSSDB_web/settings.py @@ -37,6 +37,7 @@ ALLOWED_HOSTS = config["ALLOWED_HOSTS"] # Application definition INSTALLED_APPS = [ + "fossdb", "django.contrib.admin", "django.contrib.auth", "django.contrib.contenttypes", diff --git a/FOSSDB_web/urls.py b/FOSSDB_web/urls.py index 3d97689..b4a15ab 100644 --- a/FOSSDB_web/urls.py +++ b/FOSSDB_web/urls.py @@ -13,9 +13,15 @@ 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.conf import settings +from django.conf.urls.static import static from django.contrib import admin -from django.urls import path +from django.urls import include, path urlpatterns = [ + path("", include("fossdb.urls")), path("admin/", admin.site.urls), + ] + +urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) From 9959ec5b164f7e4ebceec7cc30eab124ada7be85 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Mon, 27 Mar 2023 20:48:38 +0300 Subject: [PATCH 008/144] Created `layout.html` --- templates/layout.html | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 templates/layout.html diff --git a/templates/layout.html b/templates/layout.html new file mode 100644 index 0000000..08fe90d --- /dev/null +++ b/templates/layout.html @@ -0,0 +1,15 @@ +{% load static %} + + + + + + + {% block title %}{% endblock %} + + {% block meta %}{% endblock %} + + + {% block content %}{% endblock %} + + From 30dc13adcc237f031d1d47195fe90593c6933f23 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Mon, 27 Mar 2023 20:48:56 +0300 Subject: [PATCH 009/144] Created homepage --- templates/fossdb/index.html | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 templates/fossdb/index.html diff --git a/templates/fossdb/index.html b/templates/fossdb/index.html new file mode 100644 index 0000000..c7843d8 --- /dev/null +++ b/templates/fossdb/index.html @@ -0,0 +1,13 @@ +{% extends "layout.html" %} +{% load static %} +{% block title %}{{ title }}{% endblock %} +{% block meta %}{% endblock %} +{% block content %} + {% for project in projects %} + @{{ project.author.username }} +
{{ project.title }}
+

{{ project.description }}

+ {% empty %} +

No projects yet (

+ {% endfor %} +{% endblock %} From 67cc48e8224478adb73b16d6b8dd546293557712 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Mon, 27 Mar 2023 20:49:02 +0300 Subject: [PATCH 010/144] Fix typo --- FOSSDB_web/settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FOSSDB_web/settings.py b/FOSSDB_web/settings.py index ba3d2d0..cc0962b 100644 --- a/FOSSDB_web/settings.py +++ b/FOSSDB_web/settings.py @@ -87,7 +87,7 @@ DATABASES = { "USER": config["DATABASE"]["USER"], "PASSWORD": config["DATABASE"]["PASSWORD"], "HOST": config["DATABASE"]["HOST"], - "PORT": config["DATABASE"]["PORT"] + "PORT": config["DATABASE"]["PORT"], } } From 02680dbdadf3d7503b78c3b71b55c95453aa2d68 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Mon, 27 Mar 2023 20:49:20 +0300 Subject: [PATCH 011/144] Add migrations --- .../apps/fossdb/migrations/0001_initial.py | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 FOSSDB_web/apps/fossdb/migrations/0001_initial.py diff --git a/FOSSDB_web/apps/fossdb/migrations/0001_initial.py b/FOSSDB_web/apps/fossdb/migrations/0001_initial.py new file mode 100644 index 0000000..def7053 --- /dev/null +++ b/FOSSDB_web/apps/fossdb/migrations/0001_initial.py @@ -0,0 +1,27 @@ +# Generated by Django 4.1 on 2023-03-27 17:46 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='Project', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('title', models.CharField(max_length=255)), + ('description', models.TextField()), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ], + ), + ] From 70a1d9e02c7d393d55cafc3ac9bd70244f53aada Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Mon, 27 Mar 2023 20:53:14 +0300 Subject: [PATCH 012/144] Removed redundant code --- FOSSDB_web/apps/fossdb/admin.py | 3 --- FOSSDB_web/apps/fossdb/tests.py | 3 --- 2 files changed, 6 deletions(-) diff --git a/FOSSDB_web/apps/fossdb/admin.py b/FOSSDB_web/apps/fossdb/admin.py index 8c38f3f..e69de29 100644 --- a/FOSSDB_web/apps/fossdb/admin.py +++ b/FOSSDB_web/apps/fossdb/admin.py @@ -1,3 +0,0 @@ -from django.contrib import admin - -# Register your models here. diff --git a/FOSSDB_web/apps/fossdb/tests.py b/FOSSDB_web/apps/fossdb/tests.py index 7ce503c..e69de29 100644 --- a/FOSSDB_web/apps/fossdb/tests.py +++ b/FOSSDB_web/apps/fossdb/tests.py @@ -1,3 +0,0 @@ -from django.test import TestCase - -# Create your tests here. From af5f735070711353431ff05c15e0ec7d1850424b Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Mon, 27 Mar 2023 20:53:36 +0300 Subject: [PATCH 013/144] Renamed `create_project` to `add_project` --- FOSSDB_web/apps/fossdb/urls.py | 3 ++- FOSSDB_web/apps/fossdb/views.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/FOSSDB_web/apps/fossdb/urls.py b/FOSSDB_web/apps/fossdb/urls.py index 2d9cdc0..11fbdee 100644 --- a/FOSSDB_web/apps/fossdb/urls.py +++ b/FOSSDB_web/apps/fossdb/urls.py @@ -3,5 +3,6 @@ from django.urls import path from . import views urlpatterns = [ - path("", views.index, name="index") + path("", views.index, name="index"), + path("add", views.add_project, name="add-project"), ] diff --git a/FOSSDB_web/apps/fossdb/views.py b/FOSSDB_web/apps/fossdb/views.py index c84bc6a..35c3d5a 100644 --- a/FOSSDB_web/apps/fossdb/views.py +++ b/FOSSDB_web/apps/fossdb/views.py @@ -12,7 +12,7 @@ def index(request): @login_required(login_url="account/login/") @permission_required("fossdb.add_post)", login_url="account/login/", raise_exception=True) -def create_project(request): +def add_project(request): if request.method == "POST": project = ProjectForm(request.POST) if project.is_valid(): From 4351d5ca6d5467561244f6507e2664ad6075af5e Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Mon, 27 Mar 2023 21:42:41 +0300 Subject: [PATCH 014/144] Fixed redirect urls --- FOSSDB_web/apps/account/views.py | 2 +- FOSSDB_web/apps/fossdb/views.py | 2 +- FOSSDB_web/settings.py | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/FOSSDB_web/apps/account/views.py b/FOSSDB_web/apps/account/views.py index db7ddd5..b78fd14 100644 --- a/FOSSDB_web/apps/account/views.py +++ b/FOSSDB_web/apps/account/views.py @@ -10,7 +10,7 @@ def sign_up(request): if form.is_valid(): user = form.save() login(request, user) - return redirect("/") + return redirect("") else: form = RegisterForm() return render(request, "registration/sign_up.html", {"form": form}) diff --git a/FOSSDB_web/apps/fossdb/views.py b/FOSSDB_web/apps/fossdb/views.py index 35c3d5a..42f5ff8 100644 --- a/FOSSDB_web/apps/fossdb/views.py +++ b/FOSSDB_web/apps/fossdb/views.py @@ -19,7 +19,7 @@ def add_project(request): post = project.save(commit=False) post.author = request.user post.save() - return redirect("") + return redirect("/") else: project = ProjectForm() return render(request, "main/create_project.html", {"title": "Add project", "form": project}) diff --git a/FOSSDB_web/settings.py b/FOSSDB_web/settings.py index c9ddb15..e4d3655 100644 --- a/FOSSDB_web/settings.py +++ b/FOSSDB_web/settings.py @@ -134,5 +134,5 @@ MEDIA_ROOT = BASE_PATH.joinpath("media") # https://docs.djangoproject.com/en/4.0/ref/settings/#default-auto-field DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField" -LOGIN_REDIRECT_URL = "" -LOGOUT_REDIRECT_URL = "" +LOGIN_REDIRECT_URL = "/" +LOGOUT_REDIRECT_URL = "/" From 8d8677218258fd5f0173b7b589a9b0d295f63842 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Mon, 27 Mar 2023 21:43:01 +0300 Subject: [PATCH 015/144] Added title --- FOSSDB_web/apps/account/views.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/FOSSDB_web/apps/account/views.py b/FOSSDB_web/apps/account/views.py index b78fd14..4bf3238 100644 --- a/FOSSDB_web/apps/account/views.py +++ b/FOSSDB_web/apps/account/views.py @@ -13,8 +13,8 @@ def sign_up(request): return redirect("") else: form = RegisterForm() - return render(request, "registration/sign_up.html", {"form": form}) + return render(request, "registration/sign_up.html", {"title": "Sign Up", "form": form}) def login_(request): - return render(request, "registration/login.html") + return render(request, "registration/login.html", {"title": "Login"}) From 6236d25ab423c6cf7ae059bc9afd65b95c1dd8e0 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Mon, 27 Mar 2023 21:43:56 +0300 Subject: [PATCH 016/144] Rename variable --- FOSSDB_web/apps/fossdb/views.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/FOSSDB_web/apps/fossdb/views.py b/FOSSDB_web/apps/fossdb/views.py index 42f5ff8..3b3a3a8 100644 --- a/FOSSDB_web/apps/fossdb/views.py +++ b/FOSSDB_web/apps/fossdb/views.py @@ -10,16 +10,16 @@ def index(request): return render(request, "fossdb/index.html", {"title": "FOSSDB", "projects": projects}) -@login_required(login_url="account/login/") -@permission_required("fossdb.add_post)", login_url="account/login/", raise_exception=True) +@login_required(login_url="login/") +@permission_required("fossdb.add_post)", login_url="login/", raise_exception=True) def add_project(request): if request.method == "POST": - project = ProjectForm(request.POST) - if project.is_valid(): - post = project.save(commit=False) + form = ProjectForm(request.POST) + if form.is_valid(): + post = form.save(commit=False) post.author = request.user post.save() return redirect("/") else: - project = ProjectForm() - return render(request, "main/create_project.html", {"title": "Add project", "form": project}) + form = ProjectForm() + return render(request, "fossdb/add_project.html", {"title": "Add project", "form": form}) From 88701203ecec42a56884976752f631ff543095ea Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Mon, 27 Mar 2023 21:44:12 +0300 Subject: [PATCH 017/144] Created `add_project.html` file --- templates/fossdb/add_project.html | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 templates/fossdb/add_project.html diff --git a/templates/fossdb/add_project.html b/templates/fossdb/add_project.html new file mode 100644 index 0000000..52b018a --- /dev/null +++ b/templates/fossdb/add_project.html @@ -0,0 +1,10 @@ +{% extends "layout.html" %} +{% load static %} +{% block title %}{{ title }}{% endblock %} +{% block meta %}{% endblock %} +{% block content %} +
+ {% csrf_token %}{{ form }} + +
+{% endblock %} From dcf849257e7b2e7d20e6740eee2b1ba6aebaa548 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Mon, 27 Mar 2023 21:44:30 +0300 Subject: [PATCH 018/144] Added `login` file --- templates/registration/login.html | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 templates/registration/login.html diff --git a/templates/registration/login.html b/templates/registration/login.html new file mode 100644 index 0000000..e1ca078 --- /dev/null +++ b/templates/registration/login.html @@ -0,0 +1,13 @@ +{% extends "layout.html" %} +{% load static %} +{% block title %}{{ title }}{% endblock %} +{% block meta %}{% endblock %} +{% block content %} +
+ {% csrf_token %}{{ form }} +

+ Don't have an account? Create one Here! +

+ +
+{% endblock %} From 27a70f6b5c5c919ef29d857d2485689fdfd86083 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Mon, 27 Mar 2023 21:44:41 +0300 Subject: [PATCH 019/144] Added `signup` file --- templates/registration/sign_up.html | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 templates/registration/sign_up.html diff --git a/templates/registration/sign_up.html b/templates/registration/sign_up.html new file mode 100644 index 0000000..40b7bad --- /dev/null +++ b/templates/registration/sign_up.html @@ -0,0 +1,11 @@ +{% extends "layout.html" %} +{% block title %}Sign Up{% endblock %} +{% block content %} +
+ {% csrf_token %}{{ form }} +

+ Have an account? Login Here! +

+ +
+{% endblock %} From b103f9a56eb519c8a0707203e684c8561e73be93 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Mon, 27 Mar 2023 21:44:57 +0300 Subject: [PATCH 020/144] Changed account path --- FOSSDB_web/urls.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FOSSDB_web/urls.py b/FOSSDB_web/urls.py index 9aa8c44..a68021a 100644 --- a/FOSSDB_web/urls.py +++ b/FOSSDB_web/urls.py @@ -20,9 +20,9 @@ from django.urls import include, path urlpatterns = [ path("", include("fossdb.urls")), + path("", include("account.urls")), path("admin/", admin.site.urls), path("", include("django.contrib.auth.urls")), - path("account/", include("account.urls")), ] urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) From 3fcef9d5cb2866f3494fc1a776a32d598cc5f1e7 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Mon, 27 Mar 2023 21:47:55 +0300 Subject: [PATCH 021/144] Removed redundant code --- FOSSDB_web/apps/account/admin.py | 3 --- FOSSDB_web/apps/account/tests.py | 3 --- 2 files changed, 6 deletions(-) diff --git a/FOSSDB_web/apps/account/admin.py b/FOSSDB_web/apps/account/admin.py index 8c38f3f..e69de29 100644 --- a/FOSSDB_web/apps/account/admin.py +++ b/FOSSDB_web/apps/account/admin.py @@ -1,3 +0,0 @@ -from django.contrib import admin - -# Register your models here. diff --git a/FOSSDB_web/apps/account/tests.py b/FOSSDB_web/apps/account/tests.py index 7ce503c..e69de29 100644 --- a/FOSSDB_web/apps/account/tests.py +++ b/FOSSDB_web/apps/account/tests.py @@ -1,3 +0,0 @@ -from django.test import TestCase - -# Create your tests here. From 2a06b9b792fd96d586827e5512723cd749a7cde1 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Mon, 27 Mar 2023 22:04:26 +0300 Subject: [PATCH 022/144] Updated django version --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 6f74b38..4e4add1 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,3 @@ -Django==4.1 +Django==4.1.7 fontawesomefree==6.2.1 mysqlclient==2.1.1 From 082fd1c21baa5eb74e860aef74d1efaae1284fa2 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Fri, 7 Apr 2023 14:28:56 +0300 Subject: [PATCH 023/144] Make migrations --- FOSSDB_web/apps/fossdb/migrations/0001_initial.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/FOSSDB_web/apps/fossdb/migrations/0001_initial.py b/FOSSDB_web/apps/fossdb/migrations/0001_initial.py index def7053..c6fd294 100644 --- a/FOSSDB_web/apps/fossdb/migrations/0001_initial.py +++ b/FOSSDB_web/apps/fossdb/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 4.1 on 2023-03-27 17:46 +# Generated by Django 4.1.7 on 2023-04-07 11:28 from django.conf import settings from django.db import migrations, models @@ -14,6 +14,16 @@ class Migration(migrations.Migration): ] operations = [ + migrations.CreateModel( + name='License', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('short_name', models.CharField(max_length=50)), + ('full_name', models.CharField(blank=True, max_length=100, null=True)), + ('url', models.URLField(blank=True, null=True)), + ('description', models.TextField(blank=True, null=True)), + ], + ), migrations.CreateModel( name='Project', fields=[ @@ -22,6 +32,7 @@ class Migration(migrations.Migration): ('description', models.TextField()), ('create_date', models.DateTimeField(auto_now_add=True)), ('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ('license', models.ManyToManyField(to='fossdb.license')), ], ), ] From 341ce260b9adbe1ab0af6405a1de18bbc0b735e6 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Fri, 7 Apr 2023 14:29:38 +0300 Subject: [PATCH 024/144] Created License model --- FOSSDB_web/apps/fossdb/models.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/FOSSDB_web/apps/fossdb/models.py b/FOSSDB_web/apps/fossdb/models.py index e61e920..b62e83c 100644 --- a/FOSSDB_web/apps/fossdb/models.py +++ b/FOSSDB_web/apps/fossdb/models.py @@ -2,10 +2,21 @@ from django.contrib.auth.models import User from django.db import models +class License(models.Model): + short_name = models.CharField(max_length=50) + full_name = models.CharField(max_length=100, null=True, blank=True) + url = models.URLField(null=True, blank=True) + description = models.TextField(null=True, blank=True) + + def __str__(self): + return self.short_name + + class Project(models.Model): author = models.ForeignKey(User, on_delete=models.CASCADE) title = models.CharField(max_length=255) description = models.TextField() + license = models.ManyToManyField(License) create_date = models.DateTimeField(auto_now_add=True) def __str__(self): From a00d932f3c9cdab889052c66799e0d04b3ff3ce9 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Fri, 7 Apr 2023 14:29:53 +0300 Subject: [PATCH 025/144] Minor fixes --- FOSSDB_web/apps/fossdb/models.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/FOSSDB_web/apps/fossdb/models.py b/FOSSDB_web/apps/fossdb/models.py index b62e83c..1784573 100644 --- a/FOSSDB_web/apps/fossdb/models.py +++ b/FOSSDB_web/apps/fossdb/models.py @@ -14,13 +14,13 @@ class License(models.Model): class Project(models.Model): author = models.ForeignKey(User, on_delete=models.CASCADE) - title = models.CharField(max_length=255) + title = models.CharField(max_length=255, null=False) description = models.TextField() license = models.ManyToManyField(License) create_date = models.DateTimeField(auto_now_add=True) def __str__(self): - return self.repo_name + return f"{self.author} | {self.title}" def get_absolute_url(self): return f"/projects/{self.id}" From 50c74ff9b60a8e232b75e6c586596650fe668f03 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Fri, 7 Apr 2023 14:31:08 +0300 Subject: [PATCH 026/144] Renamed variable --- FOSSDB_web/apps/fossdb/views.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/FOSSDB_web/apps/fossdb/views.py b/FOSSDB_web/apps/fossdb/views.py index 3b3a3a8..1811a24 100644 --- a/FOSSDB_web/apps/fossdb/views.py +++ b/FOSSDB_web/apps/fossdb/views.py @@ -15,10 +15,12 @@ def index(request): def add_project(request): if request.method == "POST": form = ProjectForm(request.POST) + if form.is_valid(): - post = form.save(commit=False) - post.author = request.user - post.save() + project = form.save(commit=False) + project.author = request.user + project.save() + form.save_m2m() return redirect("/") else: form = ProjectForm() From 0caa73b3dcd8f59631578e24b825465368068630 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Fri, 7 Apr 2023 14:31:41 +0300 Subject: [PATCH 027/144] Added buttons for convinience --- templates/fossdb/index.html | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/templates/fossdb/index.html b/templates/fossdb/index.html index c7843d8..5bb61ea 100644 --- a/templates/fossdb/index.html +++ b/templates/fossdb/index.html @@ -3,6 +3,13 @@ {% block title %}{{ title }}{% endblock %} {% block meta %}{% endblock %} {% block content %} + + +
{% for project in projects %} @{{ project.author.username }}
{{ project.title }}
From 5d5944fa49aee48d6516544d744afec4df40e093 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Fri, 7 Apr 2023 14:32:08 +0300 Subject: [PATCH 028/144] Created License form --- FOSSDB_web/apps/fossdb/forms.py | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/FOSSDB_web/apps/fossdb/forms.py b/FOSSDB_web/apps/fossdb/forms.py index 9603689..c6e1981 100644 --- a/FOSSDB_web/apps/fossdb/forms.py +++ b/FOSSDB_web/apps/fossdb/forms.py @@ -1,9 +1,29 @@ -from django import forms +from django.forms import (CheckboxSelectMultiple, ModelForm, + ModelMultipleChoiceField, TextInput) -from .models import Project +from .models import License, Project -class ProjectForm(forms.ModelForm): +class ProjectForm(ModelForm): + class Meta: model = Project - fields = ["title", "description"] + fields = ["title", "description", "license"] + + widgets = { + "title": TextInput(attrs={ + "class": "form-control", + "placeholder": "Project name", + }), + "description": TextInput(attrs={ + "class": "form-control", + "placeholder": "Description", + }), + } + license = ModelMultipleChoiceField(queryset=License.objects.all(), widget=CheckboxSelectMultiple) + + +class LicenseForm(ModelForm): + class Meta: + model = License + fields = ["short_name", "full_name", "url", "description"] From 022f4f8c9b373256800c7db8f0ccb8e8c4f73f25 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Fri, 7 Apr 2023 14:32:24 +0300 Subject: [PATCH 029/144] Added Project and License models to admin --- FOSSDB_web/apps/fossdb/admin.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/FOSSDB_web/apps/fossdb/admin.py b/FOSSDB_web/apps/fossdb/admin.py index e69de29..dbe7c58 100644 --- a/FOSSDB_web/apps/fossdb/admin.py +++ b/FOSSDB_web/apps/fossdb/admin.py @@ -0,0 +1,6 @@ +from django.contrib import admin + +from .models import License, Project + +admin.site.register(Project) +admin.site.register(License) From 3991385be7d0c8f91026bb403319b7552eaf7827 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Fri, 7 Apr 2023 14:32:36 +0300 Subject: [PATCH 030/144] Display licenses of project --- templates/fossdb/index.html | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/templates/fossdb/index.html b/templates/fossdb/index.html index 5bb61ea..1882b08 100644 --- a/templates/fossdb/index.html +++ b/templates/fossdb/index.html @@ -14,6 +14,17 @@ @{{ project.author.username }}
{{ project.title }}

{{ project.description }}

+ +
+

{{ project.create_date }}

{% empty %}

No projects yet (

{% endfor %} From c95614aedff2da8d449684f42e789a7bb2983484 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Fri, 7 Apr 2023 22:55:33 +0300 Subject: [PATCH 031/144] Fix typo --- FOSSDB_web/apps/fossdb/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FOSSDB_web/apps/fossdb/views.py b/FOSSDB_web/apps/fossdb/views.py index 1811a24..1de238b 100644 --- a/FOSSDB_web/apps/fossdb/views.py +++ b/FOSSDB_web/apps/fossdb/views.py @@ -11,7 +11,7 @@ def index(request): @login_required(login_url="login/") -@permission_required("fossdb.add_post)", login_url="login/", raise_exception=True) +@permission_required("fossdb.add_post", login_url="login/", raise_exception=True) def add_project(request): if request.method == "POST": form = ProjectForm(request.POST) From ed36aba8e0fcff7fe9f4f66c5e3e50fd9d99a780 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Fri, 7 Apr 2023 22:59:09 +0300 Subject: [PATCH 032/144] Moved to context --- FOSSDB_web/apps/fossdb/views.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/FOSSDB_web/apps/fossdb/views.py b/FOSSDB_web/apps/fossdb/views.py index 1de238b..e860d6b 100644 --- a/FOSSDB_web/apps/fossdb/views.py +++ b/FOSSDB_web/apps/fossdb/views.py @@ -6,8 +6,11 @@ from .models import Project def index(request): - projects = Project.objects.all() - return render(request, "fossdb/index.html", {"title": "FOSSDB", "projects": projects}) + context = { + "title": "FOSSDB", + "projects": Project.objects.all() + } + return render(request, "fossdb/index.html", context) @login_required(login_url="login/") From 581bd74e575ac4de0000632fb937d52002dffa1b Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Fri, 7 Apr 2023 23:00:00 +0300 Subject: [PATCH 033/144] Renamed variable --- FOSSDB_web/apps/fossdb/views.py | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/FOSSDB_web/apps/fossdb/views.py b/FOSSDB_web/apps/fossdb/views.py index e860d6b..5e0b370 100644 --- a/FOSSDB_web/apps/fossdb/views.py +++ b/FOSSDB_web/apps/fossdb/views.py @@ -17,14 +17,20 @@ def index(request): @permission_required("fossdb.add_post", login_url="login/", raise_exception=True) def add_project(request): if request.method == "POST": - form = ProjectForm(request.POST) + project_form = ProjectForm(request.POST) - if form.is_valid(): - project = form.save(commit=False) + if project_form.is_valid(): + project = project_form.save(commit=False) project.author = request.user project.save() - form.save_m2m() + project_form.save_m2m() return redirect("/") else: - form = ProjectForm() - return render(request, "fossdb/add_project.html", {"title": "Add project", "form": form}) + project_form = ProjectForm() + + context = { + "title": "Add project", + "project_form": project_form, + # "language_formset": language_formset + } + return render(request, "fossdb/add_project.html", context) From 2cff08747c658c74cbf1da48b4c127235541b29a Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Fri, 7 Apr 2023 23:40:27 +0300 Subject: [PATCH 034/144] Created ProgrammingLanguage model --- FOSSDB_web/apps/fossdb/models.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/FOSSDB_web/apps/fossdb/models.py b/FOSSDB_web/apps/fossdb/models.py index 1784573..fd03cd8 100644 --- a/FOSSDB_web/apps/fossdb/models.py +++ b/FOSSDB_web/apps/fossdb/models.py @@ -12,6 +12,13 @@ class License(models.Model): return self.short_name +class ProgrammingLanguage(models.Model): + name = models.CharField(max_length=100) + + def __str__(self): + return self.name + + class Project(models.Model): author = models.ForeignKey(User, on_delete=models.CASCADE) title = models.CharField(max_length=255, null=False) From 5c082c724d64f0ef3ecda33c24fa5a34c33a19cf Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Fri, 7 Apr 2023 23:41:10 +0300 Subject: [PATCH 035/144] Created ProjectProgrammingLanguage model --- FOSSDB_web/apps/fossdb/models.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/FOSSDB_web/apps/fossdb/models.py b/FOSSDB_web/apps/fossdb/models.py index fd03cd8..3153a76 100644 --- a/FOSSDB_web/apps/fossdb/models.py +++ b/FOSSDB_web/apps/fossdb/models.py @@ -19,6 +19,15 @@ class ProgrammingLanguage(models.Model): return self.name +class ProjectProgrammingLanguage(models.Model): + project = models.ForeignKey("Project", on_delete=models.CASCADE) + language = models.ForeignKey(ProgrammingLanguage, on_delete=models.CASCADE) + percentage = models.PositiveIntegerField() + + def __str__(self): + return f"{self.project} | {self.language} | {self.percentage}%" + + class Project(models.Model): author = models.ForeignKey(User, on_delete=models.CASCADE) title = models.CharField(max_length=255, null=False) From ff396a11928ace2042fdfb13afee1b567b93f6f3 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Fri, 7 Apr 2023 23:42:19 +0300 Subject: [PATCH 036/144] Renamed variable --- FOSSDB_web/apps/fossdb/models.py | 4 ++-- templates/fossdb/index.html | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/FOSSDB_web/apps/fossdb/models.py b/FOSSDB_web/apps/fossdb/models.py index 3153a76..239fdaa 100644 --- a/FOSSDB_web/apps/fossdb/models.py +++ b/FOSSDB_web/apps/fossdb/models.py @@ -30,13 +30,13 @@ class ProjectProgrammingLanguage(models.Model): class Project(models.Model): author = models.ForeignKey(User, on_delete=models.CASCADE) - title = models.CharField(max_length=255, null=False) + name = models.CharField(max_length=255, null=False) description = models.TextField() license = models.ManyToManyField(License) create_date = models.DateTimeField(auto_now_add=True) def __str__(self): - return f"{self.author} | {self.title}" + return f"{self.author} | {self.name}" def get_absolute_url(self): return f"/projects/{self.id}" diff --git a/templates/fossdb/index.html b/templates/fossdb/index.html index 1882b08..b1fff40 100644 --- a/templates/fossdb/index.html +++ b/templates/fossdb/index.html @@ -12,7 +12,7 @@
{% for project in projects %} @{{ project.author.username }} -
{{ project.title }}
+

{{ project.name }}

{{ project.description }}

    {% for license in project.license.all %} From 6c259d2e967e63c3606c8fb2fd7e1738f961b63e Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Fri, 7 Apr 2023 23:43:30 +0300 Subject: [PATCH 037/144] Renamed variables --- FOSSDB_web/apps/fossdb/models.py | 4 ++-- templates/fossdb/index.html | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/FOSSDB_web/apps/fossdb/models.py b/FOSSDB_web/apps/fossdb/models.py index 239fdaa..ead28f4 100644 --- a/FOSSDB_web/apps/fossdb/models.py +++ b/FOSSDB_web/apps/fossdb/models.py @@ -32,8 +32,8 @@ class Project(models.Model): author = models.ForeignKey(User, on_delete=models.CASCADE) name = models.CharField(max_length=255, null=False) description = models.TextField() - license = models.ManyToManyField(License) - create_date = models.DateTimeField(auto_now_add=True) + licenses = models.ManyToManyField(License) + date_created = models.DateTimeField(auto_now_add=True) def __str__(self): return f"{self.author} | {self.name}" diff --git a/templates/fossdb/index.html b/templates/fossdb/index.html index b1fff40..bde03bb 100644 --- a/templates/fossdb/index.html +++ b/templates/fossdb/index.html @@ -24,7 +24,7 @@ {% endfor %}

-

{{ project.create_date }}

+

{{ project.date_created }}

{% empty %}

No projects yet (

{% endfor %} From 8ac7f73806e1b1a95c0bca54dc7c7a1a4835b3e9 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Fri, 7 Apr 2023 23:48:32 +0300 Subject: [PATCH 038/144] Added languages attribute to Projects model --- FOSSDB_web/apps/fossdb/models.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/FOSSDB_web/apps/fossdb/models.py b/FOSSDB_web/apps/fossdb/models.py index ead28f4..c006ce6 100644 --- a/FOSSDB_web/apps/fossdb/models.py +++ b/FOSSDB_web/apps/fossdb/models.py @@ -33,10 +33,9 @@ class Project(models.Model): name = models.CharField(max_length=255, null=False) description = models.TextField() licenses = models.ManyToManyField(License) + programming_languages = models.ManyToManyField(ProgrammingLanguage, through="ProjectProgrammingLanguage", related_name="projects") date_created = models.DateTimeField(auto_now_add=True) def __str__(self): return f"{self.author} | {self.name}" - def get_absolute_url(self): - return f"/projects/{self.id}" From 4791e5477ab53656407a29e29a0b7f47a93ea21e Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Fri, 7 Apr 2023 23:50:20 +0300 Subject: [PATCH 039/144] Show language % of each project --- templates/fossdb/add_project.html | 2 +- templates/fossdb/index.html | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/templates/fossdb/add_project.html b/templates/fossdb/add_project.html index 52b018a..99282da 100644 --- a/templates/fossdb/add_project.html +++ b/templates/fossdb/add_project.html @@ -4,7 +4,7 @@ {% block meta %}{% endblock %} {% block content %}
- {% csrf_token %}{{ form }} + {% csrf_token %}{{ project_form }}
{% endblock %} diff --git a/templates/fossdb/index.html b/templates/fossdb/index.html index bde03bb..49af468 100644 --- a/templates/fossdb/index.html +++ b/templates/fossdb/index.html @@ -15,7 +15,7 @@

{{ project.name }}

{{ project.description }}

    - {% for license in project.license.all %} + {% for license in project.licenses.all %}
  • {{ license.short_name }}
  • @@ -23,6 +23,13 @@

    No license

    {% endfor %}
+
    + {% for language in project.projectprogramminglanguage_set.all %} +
  • {{ language.language.name }} | {{ language.percentage }}%
  • + {% empty %} +

    No language

    + {% endfor %} +

{{ project.date_created }}

{% empty %} From 2544256b50a8e103e611380c5cc16265a3e48fca Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Fri, 7 Apr 2023 23:50:36 +0300 Subject: [PATCH 040/144] Added language form --- FOSSDB_web/apps/fossdb/views.py | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/FOSSDB_web/apps/fossdb/views.py b/FOSSDB_web/apps/fossdb/views.py index 5e0b370..4d2496f 100644 --- a/FOSSDB_web/apps/fossdb/views.py +++ b/FOSSDB_web/apps/fossdb/views.py @@ -1,14 +1,15 @@ from django.contrib.auth.decorators import login_required, permission_required +from django.forms import formset_factory from django.shortcuts import redirect, render -from .forms import ProjectForm -from .models import Project +from .forms import ProjectForm, ProjectProgrammingLanguageForm +from .models import ProgrammingLanguage, Project def index(request): context = { "title": "FOSSDB", - "projects": Project.objects.all() + "projects": Project.objects.all(), } return render(request, "fossdb/index.html", context) @@ -16,21 +17,31 @@ def index(request): @login_required(login_url="login/") @permission_required("fossdb.add_post", login_url="login/", raise_exception=True) def add_project(request): + ProgrammingLanguageFormSet = formset_factory(ProjectProgrammingLanguageForm, extra=1) if request.method == "POST": project_form = ProjectForm(request.POST) + language_formset = ProgrammingLanguageFormSet(request.POST) - if project_form.is_valid(): + if project_form.is_valid() and language_formset.is_valid(): project = project_form.save(commit=False) project.author = request.user project.save() + + for language_form in language_formset: + if language_formset.is_valid(): + language = language_form.save(commit=False) + language.project = project + language.save() + project_form.save_m2m() return redirect("/") else: project_form = ProjectForm() + language_formset = ProgrammingLanguageFormSet() context = { "title": "Add project", "project_form": project_form, - # "language_formset": language_formset + "language_formset": language_formset } return render(request, "fossdb/add_project.html", context) From 18dacd78bfd6ca833931aa4683fa06daf025e94a Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Fri, 7 Apr 2023 23:50:49 +0300 Subject: [PATCH 041/144] Updated admin panel --- FOSSDB_web/apps/fossdb/admin.py | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/FOSSDB_web/apps/fossdb/admin.py b/FOSSDB_web/apps/fossdb/admin.py index dbe7c58..632e081 100644 --- a/FOSSDB_web/apps/fossdb/admin.py +++ b/FOSSDB_web/apps/fossdb/admin.py @@ -1,6 +1,24 @@ from django.contrib import admin +from django.forms import inlineformset_factory + +from .models import (License, ProgrammingLanguage, Project, + ProjectProgrammingLanguage) + + +class ProjectProgrammingLanguageInline(admin.TabularInline): + model = ProjectProgrammingLanguage + extra = 1 + + +class ProjectAdmin(admin.ModelAdmin): + inlines = [ProjectProgrammingLanguageInline] + list_display = ("author", "name", "get_languages") + + def get_languages(self, object): + return " | ".join([i.language.name for i in object.projectprogramminglanguage_set.all()]) -from .models import License, Project -admin.site.register(Project) admin.site.register(License) +admin.site.register(ProgrammingLanguage) +admin.site.register(Project, ProjectAdmin) +# admin.site.register(HostingPlatform) From 9f56f4de86c479d7d51fa5e8b6fc5d22cb380c8c Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Fri, 7 Apr 2023 23:52:03 +0300 Subject: [PATCH 042/144] Added language form --- FOSSDB_web/apps/fossdb/forms.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/FOSSDB_web/apps/fossdb/forms.py b/FOSSDB_web/apps/fossdb/forms.py index c6e1981..1d946c8 100644 --- a/FOSSDB_web/apps/fossdb/forms.py +++ b/FOSSDB_web/apps/fossdb/forms.py @@ -1,29 +1,30 @@ -from django.forms import (CheckboxSelectMultiple, ModelForm, - ModelMultipleChoiceField, TextInput) +from django import forms -from .models import License, Project +from .models import License, Project, ProjectProgrammingLanguage -class ProjectForm(ModelForm): +class ProjectForm(forms.ModelForm): class Meta: model = Project - fields = ["title", "description", "license"] + fields = ["name", "description", "licenses", "programming_languages"] widgets = { - "title": TextInput(attrs={ + "name": forms.TextInput(attrs={ "class": "form-control", "placeholder": "Project name", }), - "description": TextInput(attrs={ + "description": forms.Textarea(attrs={ "class": "form-control", "placeholder": "Description", }), + "licenses": forms.CheckboxSelectMultiple(), + "programming_languages": forms.CheckboxSelectMultiple(), } - license = ModelMultipleChoiceField(queryset=License.objects.all(), widget=CheckboxSelectMultiple) -class LicenseForm(ModelForm): +class LicenseForm(forms.ModelForm): class Meta: model = License fields = ["short_name", "full_name", "url", "description"] + From 4ef0b5bcb835b461e3bba03887a6c8449da5d683 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Fri, 7 Apr 2023 23:52:23 +0300 Subject: [PATCH 043/144] Update migrations --- .../apps/fossdb/migrations/0001_initial.py | 38 --------- ...r_projectprogramminglanguage_percentage.py | 82 +++++++++++++++++++ 2 files changed, 82 insertions(+), 38 deletions(-) delete mode 100644 FOSSDB_web/apps/fossdb/migrations/0001_initial.py create mode 100644 FOSSDB_web/apps/fossdb/migrations/0001_squashed_0004_alter_projectprogramminglanguage_percentage.py diff --git a/FOSSDB_web/apps/fossdb/migrations/0001_initial.py b/FOSSDB_web/apps/fossdb/migrations/0001_initial.py deleted file mode 100644 index c6fd294..0000000 --- a/FOSSDB_web/apps/fossdb/migrations/0001_initial.py +++ /dev/null @@ -1,38 +0,0 @@ -# Generated by Django 4.1.7 on 2023-04-07 11:28 - -from django.conf import settings -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - initial = True - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ] - - operations = [ - migrations.CreateModel( - name='License', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('short_name', models.CharField(max_length=50)), - ('full_name', models.CharField(blank=True, max_length=100, null=True)), - ('url', models.URLField(blank=True, null=True)), - ('description', models.TextField(blank=True, null=True)), - ], - ), - migrations.CreateModel( - name='Project', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('title', models.CharField(max_length=255)), - ('description', models.TextField()), - ('create_date', models.DateTimeField(auto_now_add=True)), - ('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), - ('license', models.ManyToManyField(to='fossdb.license')), - ], - ), - ] diff --git a/FOSSDB_web/apps/fossdb/migrations/0001_squashed_0004_alter_projectprogramminglanguage_percentage.py b/FOSSDB_web/apps/fossdb/migrations/0001_squashed_0004_alter_projectprogramminglanguage_percentage.py new file mode 100644 index 0000000..3a7b6a4 --- /dev/null +++ b/FOSSDB_web/apps/fossdb/migrations/0001_squashed_0004_alter_projectprogramminglanguage_percentage.py @@ -0,0 +1,82 @@ +# Generated by Django 4.1.7 on 2023-04-07 20:39 + +from django.conf import settings +import django.core.validators +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + replaces = [('fossdb', '0001_initial'), ('fossdb', '0002_alter_projectprogramminglanguage_project'), ('fossdb', '0003_alter_project_licenses_and_more'), ('fossdb', '0004_alter_projectprogramminglanguage_percentage')] + + initial = True + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='License', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('short_name', models.CharField(max_length=50)), + ('full_name', models.CharField(blank=True, max_length=100, null=True)), + ('url', models.URLField(blank=True, null=True)), + ('description', models.TextField(blank=True, null=True)), + ], + ), + migrations.CreateModel( + name='ProgrammingLanguage', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=100)), + ], + ), + migrations.CreateModel( + name='Project', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=255)), + ('description', models.TextField()), + ('date_created', models.DateTimeField(auto_now_add=True)), + ('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ('licenses', models.ManyToManyField(related_name='projects', to='fossdb.license')), + ], + ), + migrations.CreateModel( + name='ProjectProgrammingLanguage', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('percentage', models.PositiveIntegerField(default=0, validators=[django.core.validators.MaxValueValidator(100)])), + ('language', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='fossdb.programminglanguage')), + ('project', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='fossdb.project')), + ], + ), + migrations.AddField( + model_name='project', + name='programming_languages', + field=models.ManyToManyField(related_name='projects', through='fossdb.ProjectProgrammingLanguage', to='fossdb.programminglanguage'), + ), + migrations.AlterField( + model_name='projectprogramminglanguage', + name='project', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='project_languages', to='fossdb.project'), + ), + migrations.AlterField( + model_name='project', + name='licenses', + field=models.ManyToManyField(to='fossdb.license'), + ), + migrations.AlterField( + model_name='projectprogramminglanguage', + name='project', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='fossdb.project'), + ), + migrations.AlterField( + model_name='projectprogramminglanguage', + name='percentage', + field=models.PositiveIntegerField(), + ), + ] From a969a900070c4f08b00832ec3425fb8c45ccd5b5 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Sat, 8 Apr 2023 00:59:15 +0300 Subject: [PATCH 044/144] Renamed variable --- FOSSDB_web/apps/fossdb/admin.py | 3 +-- FOSSDB_web/apps/fossdb/models.py | 5 ++--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/FOSSDB_web/apps/fossdb/admin.py b/FOSSDB_web/apps/fossdb/admin.py index 632e081..1c328f2 100644 --- a/FOSSDB_web/apps/fossdb/admin.py +++ b/FOSSDB_web/apps/fossdb/admin.py @@ -1,5 +1,4 @@ from django.contrib import admin -from django.forms import inlineformset_factory from .models import (License, ProgrammingLanguage, Project, ProjectProgrammingLanguage) @@ -15,7 +14,7 @@ class ProjectAdmin(admin.ModelAdmin): list_display = ("author", "name", "get_languages") def get_languages(self, object): - return " | ".join([i.language.name for i in object.projectprogramminglanguage_set.all()]) + return " | ".join([i.language.language for i in object.projectprogramminglanguage_set.all()]) admin.site.register(License) diff --git a/FOSSDB_web/apps/fossdb/models.py b/FOSSDB_web/apps/fossdb/models.py index c006ce6..1fa7430 100644 --- a/FOSSDB_web/apps/fossdb/models.py +++ b/FOSSDB_web/apps/fossdb/models.py @@ -13,10 +13,10 @@ class License(models.Model): class ProgrammingLanguage(models.Model): - name = models.CharField(max_length=100) + language = models.CharField(max_length=100) def __str__(self): - return self.name + return self.language class ProjectProgrammingLanguage(models.Model): @@ -38,4 +38,3 @@ class Project(models.Model): def __str__(self): return f"{self.author} | {self.name}" - From 7da126c2f00ee60c94e130b83491345b0f1becfb Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Sat, 8 Apr 2023 01:00:01 +0300 Subject: [PATCH 045/144] Fix language % input --- FOSSDB_web/apps/fossdb/views.py | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/FOSSDB_web/apps/fossdb/views.py b/FOSSDB_web/apps/fossdb/views.py index 4d2496f..87c9b9f 100644 --- a/FOSSDB_web/apps/fossdb/views.py +++ b/FOSSDB_web/apps/fossdb/views.py @@ -1,9 +1,8 @@ from django.contrib.auth.decorators import login_required, permission_required -from django.forms import formset_factory from django.shortcuts import redirect, render -from .forms import ProjectForm, ProjectProgrammingLanguageForm -from .models import ProgrammingLanguage, Project +from .forms import ProjectForm, ProjectProgrammingLanguageFormSet +from .models import Project def index(request): @@ -17,27 +16,23 @@ def index(request): @login_required(login_url="login/") @permission_required("fossdb.add_post", login_url="login/", raise_exception=True) def add_project(request): - ProgrammingLanguageFormSet = formset_factory(ProjectProgrammingLanguageForm, extra=1) if request.method == "POST": project_form = ProjectForm(request.POST) - language_formset = ProgrammingLanguageFormSet(request.POST) + language_formset = ProjectProgrammingLanguageFormSet(request.POST, instance=Project()) if project_form.is_valid() and language_formset.is_valid(): project = project_form.save(commit=False) project.author = request.user project.save() - for language_form in language_formset: - if language_formset.is_valid(): - language = language_form.save(commit=False) - language.project = project - language.save() + language_formset.instance = project + language_formset.save() project_form.save_m2m() return redirect("/") else: project_form = ProjectForm() - language_formset = ProgrammingLanguageFormSet() + language_formset = ProjectProgrammingLanguageFormSet() context = { "title": "Add project", From b04757c176f47423d2b051dad2be4911753678ae Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Sat, 8 Apr 2023 01:00:28 +0300 Subject: [PATCH 046/144] Made language input as table --- templates/fossdb/add_project.html | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/templates/fossdb/add_project.html b/templates/fossdb/add_project.html index 99282da..f560f60 100644 --- a/templates/fossdb/add_project.html +++ b/templates/fossdb/add_project.html @@ -4,7 +4,18 @@ {% block meta %}{% endblock %} {% block content %}
- {% csrf_token %}{{ project_form }} + {% csrf_token %} + {{ project_form.as_p }} + + {{ language_formset.management_form }} + {% for form in language_formset %} + + + + + + {% endfor %} +
{{ form.language.label_tag }}{{ form.language }}{{ form.percentage }}
{% endblock %} From 73428cddfb8a4bc77626518a7a7f81ddcfaea0e8 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Sat, 8 Apr 2023 01:00:55 +0300 Subject: [PATCH 047/144] Minor fix --- FOSSDB_web/apps/fossdb/forms.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/FOSSDB_web/apps/fossdb/forms.py b/FOSSDB_web/apps/fossdb/forms.py index 1d946c8..c80ed03 100644 --- a/FOSSDB_web/apps/fossdb/forms.py +++ b/FOSSDB_web/apps/fossdb/forms.py @@ -1,13 +1,14 @@ from django import forms -from .models import License, Project, ProjectProgrammingLanguage +from .models import (License, ProgrammingLanguage, Project, + ProjectProgrammingLanguage) class ProjectForm(forms.ModelForm): class Meta: model = Project - fields = ["name", "description", "licenses", "programming_languages"] + fields = ["name", "description", "licenses"] widgets = { "name": forms.TextInput(attrs={ @@ -19,7 +20,6 @@ class ProjectForm(forms.ModelForm): "placeholder": "Description", }), "licenses": forms.CheckboxSelectMultiple(), - "programming_languages": forms.CheckboxSelectMultiple(), } From 7fa3e03cdc21a84386793ed246ff5834ed351cd4 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Sat, 8 Apr 2023 01:01:45 +0300 Subject: [PATCH 048/144] Fix language showing in homepage --- templates/fossdb/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/fossdb/index.html b/templates/fossdb/index.html index 49af468..3b062bb 100644 --- a/templates/fossdb/index.html +++ b/templates/fossdb/index.html @@ -25,7 +25,7 @@
    {% for language in project.projectprogramminglanguage_set.all %} -
  • {{ language.language.name }} | {{ language.percentage }}%
  • +
  • {{ language.language }} | {{ language.percentage }}%
  • {% empty %}

    No language

    {% endfor %} From f34cf827c83483fbc4735d01f96fbc7fae984815 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Sat, 8 Apr 2023 01:24:54 +0300 Subject: [PATCH 049/144] Added HostingPlatform --- FOSSDB_web/apps/fossdb/admin.py | 22 ++++++++++++------ FOSSDB_web/apps/fossdb/forms.py | 37 +++++++++++++++++++++++++++++-- FOSSDB_web/apps/fossdb/models.py | 17 ++++++++++++++ FOSSDB_web/apps/fossdb/views.py | 13 ++++++++--- templates/fossdb/add_project.html | 1 + 5 files changed, 78 insertions(+), 12 deletions(-) diff --git a/FOSSDB_web/apps/fossdb/admin.py b/FOSSDB_web/apps/fossdb/admin.py index 1c328f2..353a014 100644 --- a/FOSSDB_web/apps/fossdb/admin.py +++ b/FOSSDB_web/apps/fossdb/admin.py @@ -1,7 +1,7 @@ from django.contrib import admin -from .models import (License, ProgrammingLanguage, Project, - ProjectProgrammingLanguage) +from .models import (HostingPlatform, License, ProgrammingLanguage, Project, + ProjectHostingPlatform, ProjectProgrammingLanguage) class ProjectProgrammingLanguageInline(admin.TabularInline): @@ -9,15 +9,23 @@ class ProjectProgrammingLanguageInline(admin.TabularInline): extra = 1 -class ProjectAdmin(admin.ModelAdmin): - inlines = [ProjectProgrammingLanguageInline] - list_display = ("author", "name", "get_languages") +class ProjectHostingPlatformInline(admin.TabularInline): + model = ProjectHostingPlatform + extra = 1 - def get_languages(self, object): + +class ProjectAdmin(admin.ModelAdmin): + inlines = [ProjectProgrammingLanguageInline, ProjectHostingPlatformInline] + list_display = ("author", "name", "_languages", "_hosting_platform") + + def _languages(self, object): return " | ".join([i.language.language for i in object.projectprogramminglanguage_set.all()]) + def _hosting_platform(self, object): + return " | ".join([i.hosting_platform.hosting_platform for i in object.projecthostingplatform_set.all()]) + admin.site.register(License) admin.site.register(ProgrammingLanguage) +admin.site.register(HostingPlatform) admin.site.register(Project, ProjectAdmin) -# admin.site.register(HostingPlatform) diff --git a/FOSSDB_web/apps/fossdb/forms.py b/FOSSDB_web/apps/fossdb/forms.py index c80ed03..9da02f4 100644 --- a/FOSSDB_web/apps/fossdb/forms.py +++ b/FOSSDB_web/apps/fossdb/forms.py @@ -1,7 +1,7 @@ from django import forms -from .models import (License, ProgrammingLanguage, Project, - ProjectProgrammingLanguage) +from .models import (HostingPlatform, License, ProgrammingLanguage, Project, + ProjectHostingPlatform, ProjectProgrammingLanguage) class ProjectForm(forms.ModelForm): @@ -28,3 +28,36 @@ class LicenseForm(forms.ModelForm): model = License fields = ["short_name", "full_name", "url", "description"] + +class ProgrammingLanguageForm(forms.ModelForm): + percentage = forms.IntegerField(min_value=0, max_value=100) + + class Meta: + model = ProgrammingLanguage + fields = ["language", "percentage"] + + +ProjectProgrammingLanguageFormSet = forms.inlineformset_factory( + Project, + ProjectProgrammingLanguage, + form=ProgrammingLanguageForm, + extra=1, + can_delete=True, +) + + +class HostingPlatformForm(forms.ModelForm): + url = forms.URLField() + + class Meta: + model = HostingPlatform + fields = ["hosting_platform", "url"] + + +ProjectHostingPlatformFormSet = forms.inlineformset_factory( + Project, + ProjectHostingPlatform, + form=HostingPlatformForm, + extra=1, + can_delete=False +) diff --git a/FOSSDB_web/apps/fossdb/models.py b/FOSSDB_web/apps/fossdb/models.py index 1fa7430..9485b59 100644 --- a/FOSSDB_web/apps/fossdb/models.py +++ b/FOSSDB_web/apps/fossdb/models.py @@ -28,12 +28,29 @@ class ProjectProgrammingLanguage(models.Model): return f"{self.project} | {self.language} | {self.percentage}%" +class HostingPlatform(models.Model): + hosting_platform = models.CharField(max_length=100) + + def __str__(self): + return self.hosting_platform + + +class ProjectHostingPlatform(models.Model): + project = models.ForeignKey("Project", on_delete=models.CASCADE) + hosting_platform = models.ForeignKey(HostingPlatform, on_delete=models.CASCADE) + url = models.URLField() + + def __str__(self): + return f"{self.project} | {self.hosting_platform}" + + class Project(models.Model): author = models.ForeignKey(User, on_delete=models.CASCADE) name = models.CharField(max_length=255, null=False) description = models.TextField() licenses = models.ManyToManyField(License) programming_languages = models.ManyToManyField(ProgrammingLanguage, through="ProjectProgrammingLanguage", related_name="projects") + hosting_platform = models.ManyToManyField(HostingPlatform, through="ProjectHostingPlatform", related_name="projects") date_created = models.DateTimeField(auto_now_add=True) def __str__(self): diff --git a/FOSSDB_web/apps/fossdb/views.py b/FOSSDB_web/apps/fossdb/views.py index 87c9b9f..19b6d09 100644 --- a/FOSSDB_web/apps/fossdb/views.py +++ b/FOSSDB_web/apps/fossdb/views.py @@ -1,7 +1,8 @@ from django.contrib.auth.decorators import login_required, permission_required from django.shortcuts import redirect, render -from .forms import ProjectForm, ProjectProgrammingLanguageFormSet +from .forms import (ProjectForm, ProjectHostingPlatformFormSet, + ProjectProgrammingLanguageFormSet) from .models import Project @@ -19,8 +20,9 @@ def add_project(request): if request.method == "POST": project_form = ProjectForm(request.POST) language_formset = ProjectProgrammingLanguageFormSet(request.POST, instance=Project()) + host_formset = ProjectHostingPlatformFormSet(request.POST, instance=Project()) - if project_form.is_valid() and language_formset.is_valid(): + if project_form.is_valid() and language_formset.is_valid() and host_formset.is_valid(): project = project_form.save(commit=False) project.author = request.user project.save() @@ -28,15 +30,20 @@ def add_project(request): language_formset.instance = project language_formset.save() + host_formset.instance = project + host_formset.save() + project_form.save_m2m() return redirect("/") else: project_form = ProjectForm() language_formset = ProjectProgrammingLanguageFormSet() + host_formset = ProjectHostingPlatformFormSet() context = { "title": "Add project", "project_form": project_form, - "language_formset": language_formset + "language_formset": language_formset, + "host_formset": host_formset, } return render(request, "fossdb/add_project.html", context) diff --git a/templates/fossdb/add_project.html b/templates/fossdb/add_project.html index f560f60..d414e16 100644 --- a/templates/fossdb/add_project.html +++ b/templates/fossdb/add_project.html @@ -16,6 +16,7 @@ {% endfor %} + {{ host_formset.as_p }} {% endblock %} From f25759bb5b7b13fa17092c2af42cf9b04dfcb563 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Sat, 8 Apr 2023 02:19:09 +0300 Subject: [PATCH 050/144] Changed id to uuid --- FOSSDB_web/apps/fossdb/models.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/FOSSDB_web/apps/fossdb/models.py b/FOSSDB_web/apps/fossdb/models.py index 9485b59..d21d940 100644 --- a/FOSSDB_web/apps/fossdb/models.py +++ b/FOSSDB_web/apps/fossdb/models.py @@ -1,3 +1,5 @@ +import uuid + from django.contrib.auth.models import User from django.db import models @@ -45,6 +47,7 @@ class ProjectHostingPlatform(models.Model): class Project(models.Model): + uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) author = models.ForeignKey(User, on_delete=models.CASCADE) name = models.CharField(max_length=255, null=False) description = models.TextField() @@ -53,5 +56,10 @@ class Project(models.Model): hosting_platform = models.ManyToManyField(HostingPlatform, through="ProjectHostingPlatform", related_name="projects") date_created = models.DateTimeField(auto_now_add=True) + def save(self, *args, **kwargs): + if not self.uuid: + self.uuid = uuid.uuid5(uuid.NAMESPACE_URL, f"{self.author.username}-{self.name}") + super().save(*args, **kwargs) + def __str__(self): return f"{self.author} | {self.name}" From 4b97d321bc202f8008b4b3e3c86951ed3a8856da Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Sat, 8 Apr 2023 02:19:28 +0300 Subject: [PATCH 051/144] Migrations --- ...language_percentage.py => 0001_initial.py} | 59 ++++++++++--------- 1 file changed, 31 insertions(+), 28 deletions(-) rename FOSSDB_web/apps/fossdb/migrations/{0001_squashed_0004_alter_projectprogramminglanguage_percentage.py => 0001_initial.py} (66%) diff --git a/FOSSDB_web/apps/fossdb/migrations/0001_squashed_0004_alter_projectprogramminglanguage_percentage.py b/FOSSDB_web/apps/fossdb/migrations/0001_initial.py similarity index 66% rename from FOSSDB_web/apps/fossdb/migrations/0001_squashed_0004_alter_projectprogramminglanguage_percentage.py rename to FOSSDB_web/apps/fossdb/migrations/0001_initial.py index 3a7b6a4..d43573f 100644 --- a/FOSSDB_web/apps/fossdb/migrations/0001_squashed_0004_alter_projectprogramminglanguage_percentage.py +++ b/FOSSDB_web/apps/fossdb/migrations/0001_initial.py @@ -1,15 +1,13 @@ -# Generated by Django 4.1.7 on 2023-04-07 20:39 +# Generated by Django 4.1.7 on 2023-04-07 23:05 from django.conf import settings -import django.core.validators from django.db import migrations, models import django.db.models.deletion +import uuid class Migration(migrations.Migration): - replaces = [('fossdb', '0001_initial'), ('fossdb', '0002_alter_projectprogramminglanguage_project'), ('fossdb', '0003_alter_project_licenses_and_more'), ('fossdb', '0004_alter_projectprogramminglanguage_percentage')] - initial = True dependencies = [ @@ -17,6 +15,13 @@ class Migration(migrations.Migration): ] operations = [ + migrations.CreateModel( + name='HostingPlatform', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('hosting_platform', models.CharField(max_length=100)), + ], + ), migrations.CreateModel( name='License', fields=[ @@ -31,52 +36,50 @@ class Migration(migrations.Migration): name='ProgrammingLanguage', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=100)), + ('language', models.CharField(max_length=100)), ], ), migrations.CreateModel( name='Project', fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('uuid', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), ('name', models.CharField(max_length=255)), ('description', models.TextField()), ('date_created', models.DateTimeField(auto_now_add=True)), ('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), - ('licenses', models.ManyToManyField(related_name='projects', to='fossdb.license')), ], ), migrations.CreateModel( name='ProjectProgrammingLanguage', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('percentage', models.PositiveIntegerField(default=0, validators=[django.core.validators.MaxValueValidator(100)])), + ('percentage', models.PositiveIntegerField()), ('language', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='fossdb.programminglanguage')), ('project', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='fossdb.project')), ], ), + migrations.CreateModel( + name='ProjectHostingPlatform', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('url', models.URLField()), + ('hosting_platform', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='fossdb.hostingplatform')), + ('project', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='fossdb.project')), + ], + ), + migrations.AddField( + model_name='project', + name='hosting_platform', + field=models.ManyToManyField(related_name='projects', through='fossdb.ProjectHostingPlatform', to='fossdb.hostingplatform'), + ), + migrations.AddField( + model_name='project', + name='licenses', + field=models.ManyToManyField(to='fossdb.license'), + ), migrations.AddField( model_name='project', name='programming_languages', field=models.ManyToManyField(related_name='projects', through='fossdb.ProjectProgrammingLanguage', to='fossdb.programminglanguage'), ), - migrations.AlterField( - model_name='projectprogramminglanguage', - name='project', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='project_languages', to='fossdb.project'), - ), - migrations.AlterField( - model_name='project', - name='licenses', - field=models.ManyToManyField(to='fossdb.license'), - ), - migrations.AlterField( - model_name='projectprogramminglanguage', - name='project', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='fossdb.project'), - ), - migrations.AlterField( - model_name='projectprogramminglanguage', - name='percentage', - field=models.PositiveIntegerField(), - ), ] From d5bf12cf29423ac8f1f993e7870ad7a39acb4915 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Sat, 8 Apr 2023 13:10:28 +0300 Subject: [PATCH 052/144] Created License app --- FOSSDB_web/apps/license/__init__.py | 0 FOSSDB_web/apps/license/admin.py | 3 +++ FOSSDB_web/apps/license/apps.py | 6 ++++++ FOSSDB_web/apps/license/migrations/__init__.py | 0 FOSSDB_web/apps/license/models.py | 3 +++ FOSSDB_web/apps/license/tests.py | 3 +++ FOSSDB_web/apps/license/views.py | 3 +++ 7 files changed, 18 insertions(+) create mode 100644 FOSSDB_web/apps/license/__init__.py create mode 100644 FOSSDB_web/apps/license/admin.py create mode 100644 FOSSDB_web/apps/license/apps.py create mode 100644 FOSSDB_web/apps/license/migrations/__init__.py create mode 100644 FOSSDB_web/apps/license/models.py create mode 100644 FOSSDB_web/apps/license/tests.py create mode 100644 FOSSDB_web/apps/license/views.py diff --git a/FOSSDB_web/apps/license/__init__.py b/FOSSDB_web/apps/license/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/FOSSDB_web/apps/license/admin.py b/FOSSDB_web/apps/license/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/FOSSDB_web/apps/license/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/FOSSDB_web/apps/license/apps.py b/FOSSDB_web/apps/license/apps.py new file mode 100644 index 0000000..af50348 --- /dev/null +++ b/FOSSDB_web/apps/license/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class LicenseConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'license' diff --git a/FOSSDB_web/apps/license/migrations/__init__.py b/FOSSDB_web/apps/license/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/FOSSDB_web/apps/license/models.py b/FOSSDB_web/apps/license/models.py new file mode 100644 index 0000000..71a8362 --- /dev/null +++ b/FOSSDB_web/apps/license/models.py @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. diff --git a/FOSSDB_web/apps/license/tests.py b/FOSSDB_web/apps/license/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/FOSSDB_web/apps/license/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/FOSSDB_web/apps/license/views.py b/FOSSDB_web/apps/license/views.py new file mode 100644 index 0000000..91ea44a --- /dev/null +++ b/FOSSDB_web/apps/license/views.py @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here. From a055cbe47659775fad268616b56ea787cd776026 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Sat, 8 Apr 2023 13:16:38 +0300 Subject: [PATCH 053/144] Moved License code to separate app --- FOSSDB_web/apps/fossdb/admin.py | 3 +-- FOSSDB_web/apps/fossdb/forms.py | 8 +------ ...2_delete_license_alter_project_licenses.py | 22 +++++++++++++++++ FOSSDB_web/apps/fossdb/models.py | 10 +------- FOSSDB_web/apps/license/admin.py | 4 +++- FOSSDB_web/apps/license/forms.py | 9 +++++++ .../apps/license/migrations/0001_initial.py | 24 +++++++++++++++++++ FOSSDB_web/apps/license/models.py | 10 +++++++- FOSSDB_web/apps/license/views.py | 3 --- FOSSDB_web/settings.py | 1 + 10 files changed, 71 insertions(+), 23 deletions(-) create mode 100644 FOSSDB_web/apps/fossdb/migrations/0002_delete_license_alter_project_licenses.py create mode 100644 FOSSDB_web/apps/license/forms.py create mode 100644 FOSSDB_web/apps/license/migrations/0001_initial.py diff --git a/FOSSDB_web/apps/fossdb/admin.py b/FOSSDB_web/apps/fossdb/admin.py index 353a014..e377288 100644 --- a/FOSSDB_web/apps/fossdb/admin.py +++ b/FOSSDB_web/apps/fossdb/admin.py @@ -1,6 +1,6 @@ from django.contrib import admin -from .models import (HostingPlatform, License, ProgrammingLanguage, Project, +from .models import (HostingPlatform, ProgrammingLanguage, Project, ProjectHostingPlatform, ProjectProgrammingLanguage) @@ -25,7 +25,6 @@ class ProjectAdmin(admin.ModelAdmin): return " | ".join([i.hosting_platform.hosting_platform for i in object.projecthostingplatform_set.all()]) -admin.site.register(License) admin.site.register(ProgrammingLanguage) admin.site.register(HostingPlatform) admin.site.register(Project, ProjectAdmin) diff --git a/FOSSDB_web/apps/fossdb/forms.py b/FOSSDB_web/apps/fossdb/forms.py index 9da02f4..0333317 100644 --- a/FOSSDB_web/apps/fossdb/forms.py +++ b/FOSSDB_web/apps/fossdb/forms.py @@ -1,6 +1,6 @@ from django import forms -from .models import (HostingPlatform, License, ProgrammingLanguage, Project, +from .models import (HostingPlatform, ProgrammingLanguage, Project, ProjectHostingPlatform, ProjectProgrammingLanguage) @@ -23,12 +23,6 @@ class ProjectForm(forms.ModelForm): } -class LicenseForm(forms.ModelForm): - class Meta: - model = License - fields = ["short_name", "full_name", "url", "description"] - - class ProgrammingLanguageForm(forms.ModelForm): percentage = forms.IntegerField(min_value=0, max_value=100) diff --git a/FOSSDB_web/apps/fossdb/migrations/0002_delete_license_alter_project_licenses.py b/FOSSDB_web/apps/fossdb/migrations/0002_delete_license_alter_project_licenses.py new file mode 100644 index 0000000..0244548 --- /dev/null +++ b/FOSSDB_web/apps/fossdb/migrations/0002_delete_license_alter_project_licenses.py @@ -0,0 +1,22 @@ +# Generated by Django 4.1.7 on 2023-04-08 10:14 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('license', '0001_initial'), + ('fossdb', '0001_initial'), + ] + + operations = [ + migrations.DeleteModel( + name='License', + ), + migrations.AlterField( + model_name='project', + name='licenses', + field=models.ManyToManyField(to='license.license'), + ), + ] diff --git a/FOSSDB_web/apps/fossdb/models.py b/FOSSDB_web/apps/fossdb/models.py index d21d940..d25faa4 100644 --- a/FOSSDB_web/apps/fossdb/models.py +++ b/FOSSDB_web/apps/fossdb/models.py @@ -3,15 +3,7 @@ import uuid from django.contrib.auth.models import User from django.db import models - -class License(models.Model): - short_name = models.CharField(max_length=50) - full_name = models.CharField(max_length=100, null=True, blank=True) - url = models.URLField(null=True, blank=True) - description = models.TextField(null=True, blank=True) - - def __str__(self): - return self.short_name +from license.models import License class ProgrammingLanguage(models.Model): diff --git a/FOSSDB_web/apps/license/admin.py b/FOSSDB_web/apps/license/admin.py index 8c38f3f..9908df0 100644 --- a/FOSSDB_web/apps/license/admin.py +++ b/FOSSDB_web/apps/license/admin.py @@ -1,3 +1,5 @@ from django.contrib import admin -# Register your models here. +from .models import License + +admin.site.register(License) diff --git a/FOSSDB_web/apps/license/forms.py b/FOSSDB_web/apps/license/forms.py new file mode 100644 index 0000000..0c180da --- /dev/null +++ b/FOSSDB_web/apps/license/forms.py @@ -0,0 +1,9 @@ +from django import forms + +from .models import License + + +class LicenseForm(forms.ModelForm): + class Meta: + model = License + fields = ["short_name", "full_name", "url", "description"] diff --git a/FOSSDB_web/apps/license/migrations/0001_initial.py b/FOSSDB_web/apps/license/migrations/0001_initial.py new file mode 100644 index 0000000..26024b3 --- /dev/null +++ b/FOSSDB_web/apps/license/migrations/0001_initial.py @@ -0,0 +1,24 @@ +# Generated by Django 4.1.7 on 2023-04-08 10:14 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='License', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('short_name', models.CharField(max_length=50)), + ('full_name', models.CharField(blank=True, max_length=100, null=True)), + ('url', models.URLField(blank=True, null=True)), + ('description', models.TextField(blank=True, null=True)), + ], + ), + ] diff --git a/FOSSDB_web/apps/license/models.py b/FOSSDB_web/apps/license/models.py index 71a8362..172f707 100644 --- a/FOSSDB_web/apps/license/models.py +++ b/FOSSDB_web/apps/license/models.py @@ -1,3 +1,11 @@ from django.db import models -# Create your models here. + +class License(models.Model): + short_name = models.CharField(max_length=50) + full_name = models.CharField(max_length=100, null=True, blank=True) + url = models.URLField(null=True, blank=True) + description = models.TextField(null=True, blank=True) + + def __str__(self): + return self.short_name diff --git a/FOSSDB_web/apps/license/views.py b/FOSSDB_web/apps/license/views.py index 91ea44a..e69de29 100644 --- a/FOSSDB_web/apps/license/views.py +++ b/FOSSDB_web/apps/license/views.py @@ -1,3 +0,0 @@ -from django.shortcuts import render - -# Create your views here. diff --git a/FOSSDB_web/settings.py b/FOSSDB_web/settings.py index e4d3655..5a28844 100644 --- a/FOSSDB_web/settings.py +++ b/FOSSDB_web/settings.py @@ -37,6 +37,7 @@ ALLOWED_HOSTS = config["ALLOWED_HOSTS"] INSTALLED_APPS = [ "fossdb", + "license", "account", "django.contrib.admin", "django.contrib.auth", From 89143d6d43fa74937c49a367b3156ac080642667 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Sat, 8 Apr 2023 13:18:13 +0300 Subject: [PATCH 054/144] Added Tag model --- FOSSDB_web/apps/fossdb/admin.py | 3 ++- FOSSDB_web/apps/fossdb/models.py | 15 ++++++++++++--- FOSSDB_web/settings.py | 14 +++++++++++++- 3 files changed, 27 insertions(+), 5 deletions(-) diff --git a/FOSSDB_web/apps/fossdb/admin.py b/FOSSDB_web/apps/fossdb/admin.py index 353a014..e7f018d 100644 --- a/FOSSDB_web/apps/fossdb/admin.py +++ b/FOSSDB_web/apps/fossdb/admin.py @@ -1,7 +1,7 @@ from django.contrib import admin from .models import (HostingPlatform, License, ProgrammingLanguage, Project, - ProjectHostingPlatform, ProjectProgrammingLanguage) + ProjectHostingPlatform, ProjectProgrammingLanguage, Tag) class ProjectProgrammingLanguageInline(admin.TabularInline): @@ -29,3 +29,4 @@ admin.site.register(License) admin.site.register(ProgrammingLanguage) admin.site.register(HostingPlatform) admin.site.register(Project, ProjectAdmin) +admin.site.register(Tag) diff --git a/FOSSDB_web/apps/fossdb/models.py b/FOSSDB_web/apps/fossdb/models.py index d21d940..f4a7079 100644 --- a/FOSSDB_web/apps/fossdb/models.py +++ b/FOSSDB_web/apps/fossdb/models.py @@ -1,12 +1,14 @@ import uuid -from django.contrib.auth.models import User +from django.conf import settings from django.db import models +User = settings.AUTH_USER_MODEL + class License(models.Model): short_name = models.CharField(max_length=50) - full_name = models.CharField(max_length=100, null=True, blank=True) + full_name = models.CharField(max_length=100, blank=True) url = models.URLField(null=True, blank=True) description = models.TextField(null=True, blank=True) @@ -24,7 +26,7 @@ class ProgrammingLanguage(models.Model): class ProjectProgrammingLanguage(models.Model): project = models.ForeignKey("Project", on_delete=models.CASCADE) language = models.ForeignKey(ProgrammingLanguage, on_delete=models.CASCADE) - percentage = models.PositiveIntegerField() + percentage = models.PositiveIntegerField(default=0) def __str__(self): return f"{self.project} | {self.language} | {self.percentage}%" @@ -46,6 +48,12 @@ class ProjectHostingPlatform(models.Model): return f"{self.project} | {self.hosting_platform}" +class Tag(models.Model): + name = models.CharField(max_length=100) + description = models.TextField(null=True, blank=True) + icon = models.ImageField(upload_to="types/icons/", null=True, blank=True) + + class Project(models.Model): uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) author = models.ForeignKey(User, on_delete=models.CASCADE) @@ -54,6 +62,7 @@ class Project(models.Model): licenses = models.ManyToManyField(License) programming_languages = models.ManyToManyField(ProgrammingLanguage, through="ProjectProgrammingLanguage", related_name="projects") hosting_platform = models.ManyToManyField(HostingPlatform, through="ProjectHostingPlatform", related_name="projects") + project_type = models.ForeignKey(Tag, on_delete=models.CASCADE, blank=True, null=True) date_created = models.DateTimeField(auto_now_add=True) def save(self, *args, **kwargs): diff --git a/FOSSDB_web/settings.py b/FOSSDB_web/settings.py index e4d3655..cd5514a 100644 --- a/FOSSDB_web/settings.py +++ b/FOSSDB_web/settings.py @@ -82,7 +82,7 @@ WSGI_APPLICATION = "FOSSDB_web.wsgi.application" DATABASES = { "default": { - "ENGINE": "django.db.backends.mysql", + "ENGINE": f"django.db.backends.{config['DATABASE']['ENGINE']}", "NAME": config["DATABASE"]["NAME"], "USER": config["DATABASE"]["USER"], "PASSWORD": config["DATABASE"]["PASSWORD"], @@ -128,6 +128,7 @@ USE_TZ = True STATIC_URL = "/static/" STATIC_ROOT = BASE_PATH.joinpath("static") +MEDIA_URL = "/media/" MEDIA_ROOT = BASE_PATH.joinpath("media") # Default primary key field type @@ -136,3 +137,14 @@ MEDIA_ROOT = BASE_PATH.joinpath("media") DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField" LOGIN_REDIRECT_URL = "/" LOGOUT_REDIRECT_URL = "/" + +# HTTPS settings +# SESSION_COOKIE_SECURE = True +# CSRF_COOKIE_SECURE = True +# SECURE_SSL_REDIRECT = True + +# HSTS settings +# SECURE_HSTS_SECONDS = 31536000 # 1 year +# SECURE_HSTS_SECONDS = 1 # 1 year +# SECURE_HSTS_PRELOAD = True +# SECURE_HSTS_INCLUDE_SUBDOMAINS = True From 1555f9d5e0bfcc4cad55ae111033f15eedffdd89 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Sat, 8 Apr 2023 13:26:12 +0300 Subject: [PATCH 055/144] Changed user --- FOSSDB_web/apps/fossdb/models.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/FOSSDB_web/apps/fossdb/models.py b/FOSSDB_web/apps/fossdb/models.py index 8ca8573..ff362d2 100644 --- a/FOSSDB_web/apps/fossdb/models.py +++ b/FOSSDB_web/apps/fossdb/models.py @@ -2,9 +2,10 @@ import uuid from django.conf import settings from django.db import models - from license.models import License +User = settings.AUTH_USER_MODEL + class ProgrammingLanguage(models.Model): language = models.CharField(max_length=100) From 2207738a2a8b5fdc562cf5e963258ac239782ac2 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Sat, 8 Apr 2023 13:46:59 +0300 Subject: [PATCH 056/144] Created ProgrammingLanguage app --- FOSSDB_web/apps/fossdb/admin.py | 10 ++------- FOSSDB_web/apps/fossdb/forms.py | 20 +----------------- FOSSDB_web/apps/fossdb/models.py | 17 +-------------- FOSSDB_web/apps/fossdb/views.py | 4 ++-- .../apps/programming_language/__init__.py | 0 FOSSDB_web/apps/programming_language/admin.py | 11 ++++++++++ FOSSDB_web/apps/programming_language/apps.py | 6 ++++++ FOSSDB_web/apps/programming_language/forms.py | 21 +++++++++++++++++++ .../migrations/__init__.py | 0 .../apps/programming_language/models.py | 17 +++++++++++++++ FOSSDB_web/apps/programming_language/tests.py | 3 +++ FOSSDB_web/apps/programming_language/views.py | 3 +++ FOSSDB_web/settings.py | 1 + 13 files changed, 68 insertions(+), 45 deletions(-) create mode 100644 FOSSDB_web/apps/programming_language/__init__.py create mode 100644 FOSSDB_web/apps/programming_language/admin.py create mode 100644 FOSSDB_web/apps/programming_language/apps.py create mode 100644 FOSSDB_web/apps/programming_language/forms.py create mode 100644 FOSSDB_web/apps/programming_language/migrations/__init__.py create mode 100644 FOSSDB_web/apps/programming_language/models.py create mode 100644 FOSSDB_web/apps/programming_language/tests.py create mode 100644 FOSSDB_web/apps/programming_language/views.py diff --git a/FOSSDB_web/apps/fossdb/admin.py b/FOSSDB_web/apps/fossdb/admin.py index 353a014..4bcb5bd 100644 --- a/FOSSDB_web/apps/fossdb/admin.py +++ b/FOSSDB_web/apps/fossdb/admin.py @@ -1,12 +1,7 @@ from django.contrib import admin +from programming_language.admin import ProjectProgrammingLanguageInline -from .models import (HostingPlatform, License, ProgrammingLanguage, Project, - ProjectHostingPlatform, ProjectProgrammingLanguage) - - -class ProjectProgrammingLanguageInline(admin.TabularInline): - model = ProjectProgrammingLanguage - extra = 1 +from .models import HostingPlatform, License, Project, ProjectHostingPlatform class ProjectHostingPlatformInline(admin.TabularInline): @@ -26,6 +21,5 @@ class ProjectAdmin(admin.ModelAdmin): admin.site.register(License) -admin.site.register(ProgrammingLanguage) admin.site.register(HostingPlatform) admin.site.register(Project, ProjectAdmin) diff --git a/FOSSDB_web/apps/fossdb/forms.py b/FOSSDB_web/apps/fossdb/forms.py index 9da02f4..355ed69 100644 --- a/FOSSDB_web/apps/fossdb/forms.py +++ b/FOSSDB_web/apps/fossdb/forms.py @@ -1,7 +1,6 @@ from django import forms -from .models import (HostingPlatform, License, ProgrammingLanguage, Project, - ProjectHostingPlatform, ProjectProgrammingLanguage) +from .models import HostingPlatform, License, Project, ProjectHostingPlatform class ProjectForm(forms.ModelForm): @@ -29,23 +28,6 @@ class LicenseForm(forms.ModelForm): fields = ["short_name", "full_name", "url", "description"] -class ProgrammingLanguageForm(forms.ModelForm): - percentage = forms.IntegerField(min_value=0, max_value=100) - - class Meta: - model = ProgrammingLanguage - fields = ["language", "percentage"] - - -ProjectProgrammingLanguageFormSet = forms.inlineformset_factory( - Project, - ProjectProgrammingLanguage, - form=ProgrammingLanguageForm, - extra=1, - can_delete=True, -) - - class HostingPlatformForm(forms.ModelForm): url = forms.URLField() diff --git a/FOSSDB_web/apps/fossdb/models.py b/FOSSDB_web/apps/fossdb/models.py index d21d940..1921743 100644 --- a/FOSSDB_web/apps/fossdb/models.py +++ b/FOSSDB_web/apps/fossdb/models.py @@ -2,6 +2,7 @@ import uuid from django.contrib.auth.models import User from django.db import models +from programming_language.models import ProgrammingLanguage class License(models.Model): @@ -14,22 +15,6 @@ class License(models.Model): return self.short_name -class ProgrammingLanguage(models.Model): - language = models.CharField(max_length=100) - - def __str__(self): - return self.language - - -class ProjectProgrammingLanguage(models.Model): - project = models.ForeignKey("Project", on_delete=models.CASCADE) - language = models.ForeignKey(ProgrammingLanguage, on_delete=models.CASCADE) - percentage = models.PositiveIntegerField() - - def __str__(self): - return f"{self.project} | {self.language} | {self.percentage}%" - - class HostingPlatform(models.Model): hosting_platform = models.CharField(max_length=100) diff --git a/FOSSDB_web/apps/fossdb/views.py b/FOSSDB_web/apps/fossdb/views.py index 19b6d09..63d4ae2 100644 --- a/FOSSDB_web/apps/fossdb/views.py +++ b/FOSSDB_web/apps/fossdb/views.py @@ -1,8 +1,8 @@ from django.contrib.auth.decorators import login_required, permission_required from django.shortcuts import redirect, render +from programming_language.forms import ProjectProgrammingLanguageFormSet -from .forms import (ProjectForm, ProjectHostingPlatformFormSet, - ProjectProgrammingLanguageFormSet) +from .forms import ProjectForm, ProjectHostingPlatformFormSet from .models import Project diff --git a/FOSSDB_web/apps/programming_language/__init__.py b/FOSSDB_web/apps/programming_language/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/FOSSDB_web/apps/programming_language/admin.py b/FOSSDB_web/apps/programming_language/admin.py new file mode 100644 index 0000000..74324bf --- /dev/null +++ b/FOSSDB_web/apps/programming_language/admin.py @@ -0,0 +1,11 @@ +from django.contrib import admin + +from .models import ProgrammingLanguage, ProjectProgrammingLanguage + + +class ProjectProgrammingLanguageInline(admin.TabularInline): + model = ProjectProgrammingLanguage + extra = 1 + + +admin.site.register(ProgrammingLanguage) diff --git a/FOSSDB_web/apps/programming_language/apps.py b/FOSSDB_web/apps/programming_language/apps.py new file mode 100644 index 0000000..4192b11 --- /dev/null +++ b/FOSSDB_web/apps/programming_language/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class ProgrammingLanguageConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'programming_language' diff --git a/FOSSDB_web/apps/programming_language/forms.py b/FOSSDB_web/apps/programming_language/forms.py new file mode 100644 index 0000000..4cc8775 --- /dev/null +++ b/FOSSDB_web/apps/programming_language/forms.py @@ -0,0 +1,21 @@ +from django import forms +from fossdb.models import Project + +from .models import ProgrammingLanguage, ProjectProgrammingLanguage + + +class ProgrammingLanguageForm(forms.ModelForm): + percentage = forms.IntegerField(min_value=0, max_value=100) + + class Meta: + model = ProgrammingLanguage + fields = ["language", "percentage"] + + +ProjectProgrammingLanguageFormSet = forms.inlineformset_factory( + Project, + ProjectProgrammingLanguage, + form=ProgrammingLanguageForm, + extra=1, + can_delete=True, +) diff --git a/FOSSDB_web/apps/programming_language/migrations/__init__.py b/FOSSDB_web/apps/programming_language/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/FOSSDB_web/apps/programming_language/models.py b/FOSSDB_web/apps/programming_language/models.py new file mode 100644 index 0000000..9a624f1 --- /dev/null +++ b/FOSSDB_web/apps/programming_language/models.py @@ -0,0 +1,17 @@ +from django.db import models + + +class ProgrammingLanguage(models.Model): + language = models.CharField(max_length=100) + + def __str__(self): + return self.language + + +class ProjectProgrammingLanguage(models.Model): + project = models.ForeignKey("Project", on_delete=models.CASCADE) + language = models.ForeignKey(ProgrammingLanguage, on_delete=models.CASCADE) + percentage = models.PositiveIntegerField() + + def __str__(self): + return f"{self.project} | {self.language} | {self.percentage}%" diff --git a/FOSSDB_web/apps/programming_language/tests.py b/FOSSDB_web/apps/programming_language/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/FOSSDB_web/apps/programming_language/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/FOSSDB_web/apps/programming_language/views.py b/FOSSDB_web/apps/programming_language/views.py new file mode 100644 index 0000000..91ea44a --- /dev/null +++ b/FOSSDB_web/apps/programming_language/views.py @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here. diff --git a/FOSSDB_web/settings.py b/FOSSDB_web/settings.py index e4d3655..4df1802 100644 --- a/FOSSDB_web/settings.py +++ b/FOSSDB_web/settings.py @@ -38,6 +38,7 @@ ALLOWED_HOSTS = config["ALLOWED_HOSTS"] INSTALLED_APPS = [ "fossdb", "account", + "programming_language", "django.contrib.admin", "django.contrib.auth", "django.contrib.contenttypes", From 816c430f29cc9a482e05101dc8ccc09d3d9a9be7 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Sat, 8 Apr 2023 13:50:45 +0300 Subject: [PATCH 057/144] Created HostingPlatform app --- FOSSDB_web/apps/hosting_platform/__init__.py | 0 FOSSDB_web/apps/hosting_platform/admin.py | 3 +++ FOSSDB_web/apps/hosting_platform/apps.py | 6 ++++++ FOSSDB_web/apps/hosting_platform/migrations/__init__.py | 0 FOSSDB_web/apps/hosting_platform/models.py | 3 +++ FOSSDB_web/apps/hosting_platform/tests.py | 3 +++ FOSSDB_web/apps/hosting_platform/views.py | 3 +++ FOSSDB_web/settings.py | 1 + 8 files changed, 19 insertions(+) create mode 100644 FOSSDB_web/apps/hosting_platform/__init__.py create mode 100644 FOSSDB_web/apps/hosting_platform/admin.py create mode 100644 FOSSDB_web/apps/hosting_platform/apps.py create mode 100644 FOSSDB_web/apps/hosting_platform/migrations/__init__.py create mode 100644 FOSSDB_web/apps/hosting_platform/models.py create mode 100644 FOSSDB_web/apps/hosting_platform/tests.py create mode 100644 FOSSDB_web/apps/hosting_platform/views.py diff --git a/FOSSDB_web/apps/hosting_platform/__init__.py b/FOSSDB_web/apps/hosting_platform/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/FOSSDB_web/apps/hosting_platform/admin.py b/FOSSDB_web/apps/hosting_platform/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/FOSSDB_web/apps/hosting_platform/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/FOSSDB_web/apps/hosting_platform/apps.py b/FOSSDB_web/apps/hosting_platform/apps.py new file mode 100644 index 0000000..c11d49f --- /dev/null +++ b/FOSSDB_web/apps/hosting_platform/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class HostingPlatformConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'hosting_platform' diff --git a/FOSSDB_web/apps/hosting_platform/migrations/__init__.py b/FOSSDB_web/apps/hosting_platform/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/FOSSDB_web/apps/hosting_platform/models.py b/FOSSDB_web/apps/hosting_platform/models.py new file mode 100644 index 0000000..71a8362 --- /dev/null +++ b/FOSSDB_web/apps/hosting_platform/models.py @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. diff --git a/FOSSDB_web/apps/hosting_platform/tests.py b/FOSSDB_web/apps/hosting_platform/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/FOSSDB_web/apps/hosting_platform/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/FOSSDB_web/apps/hosting_platform/views.py b/FOSSDB_web/apps/hosting_platform/views.py new file mode 100644 index 0000000..91ea44a --- /dev/null +++ b/FOSSDB_web/apps/hosting_platform/views.py @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here. diff --git a/FOSSDB_web/settings.py b/FOSSDB_web/settings.py index e4d3655..2f033e5 100644 --- a/FOSSDB_web/settings.py +++ b/FOSSDB_web/settings.py @@ -38,6 +38,7 @@ ALLOWED_HOSTS = config["ALLOWED_HOSTS"] INSTALLED_APPS = [ "fossdb", "account", + "hosting_platform", "django.contrib.admin", "django.contrib.auth", "django.contrib.contenttypes", From f28e74912efe05b3d9b8c07e73498d860e0bc05f Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Sat, 8 Apr 2023 13:56:24 +0300 Subject: [PATCH 058/144] Moved HostingPlatform model to separate app --- FOSSDB_web/apps/fossdb/admin.py | 10 ++-------- FOSSDB_web/apps/fossdb/forms.py | 19 +------------------ FOSSDB_web/apps/fossdb/models.py | 17 +---------------- FOSSDB_web/apps/fossdb/views.py | 3 ++- FOSSDB_web/apps/hosting_platform/admin.py | 10 +++++++++- FOSSDB_web/apps/hosting_platform/forms.py | 21 +++++++++++++++++++++ FOSSDB_web/apps/hosting_platform/models.py | 16 +++++++++++++++- 7 files changed, 51 insertions(+), 45 deletions(-) create mode 100644 FOSSDB_web/apps/hosting_platform/forms.py diff --git a/FOSSDB_web/apps/fossdb/admin.py b/FOSSDB_web/apps/fossdb/admin.py index 099f80d..a74ba9e 100644 --- a/FOSSDB_web/apps/fossdb/admin.py +++ b/FOSSDB_web/apps/fossdb/admin.py @@ -1,12 +1,8 @@ from django.contrib import admin +from hosting_platform.admin import ProjectHostingPlatformInline from programming_language.admin import ProjectProgrammingLanguageInline -from .models import HostingPlatform, License, Project, ProjectHostingPlatform - - -class ProjectHostingPlatformInline(admin.TabularInline): - model = ProjectHostingPlatform - extra = 1 +from .models import Project class ProjectAdmin(admin.ModelAdmin): @@ -20,7 +16,5 @@ class ProjectAdmin(admin.ModelAdmin): return " | ".join([i.hosting_platform.hosting_platform for i in object.projecthostingplatform_set.all()]) -admin.site.register(ProgrammingLanguage) -admin.site.register(HostingPlatform) admin.site.register(Project, ProjectAdmin) admin.site.register(Tag) diff --git a/FOSSDB_web/apps/fossdb/forms.py b/FOSSDB_web/apps/fossdb/forms.py index 1dde296..b1f60e2 100644 --- a/FOSSDB_web/apps/fossdb/forms.py +++ b/FOSSDB_web/apps/fossdb/forms.py @@ -1,6 +1,6 @@ from django import forms -from .models import HostingPlatform, Project, ProjectHostingPlatform +from .models import Project class ProjectForm(forms.ModelForm): @@ -20,20 +20,3 @@ class ProjectForm(forms.ModelForm): }), "licenses": forms.CheckboxSelectMultiple(), } - - -class HostingPlatformForm(forms.ModelForm): - url = forms.URLField() - - class Meta: - model = HostingPlatform - fields = ["hosting_platform", "url"] - - -ProjectHostingPlatformFormSet = forms.inlineformset_factory( - Project, - ProjectHostingPlatform, - form=HostingPlatformForm, - extra=1, - can_delete=False -) diff --git a/FOSSDB_web/apps/fossdb/models.py b/FOSSDB_web/apps/fossdb/models.py index bf9a7bd..4700ea9 100644 --- a/FOSSDB_web/apps/fossdb/models.py +++ b/FOSSDB_web/apps/fossdb/models.py @@ -2,28 +2,13 @@ import uuid from django.conf import settings from django.db import models +from hosting_platform.models import HostingPlatform from license.models import License from programming_language.models import ProgrammingLanguage User = settings.AUTH_USER_MODEL -class HostingPlatform(models.Model): - hosting_platform = models.CharField(max_length=100) - - def __str__(self): - return self.hosting_platform - - -class ProjectHostingPlatform(models.Model): - project = models.ForeignKey("Project", on_delete=models.CASCADE) - hosting_platform = models.ForeignKey(HostingPlatform, on_delete=models.CASCADE) - url = models.URLField() - - def __str__(self): - return f"{self.project} | {self.hosting_platform}" - - class Tag(models.Model): name = models.CharField(max_length=100) description = models.TextField(null=True, blank=True) diff --git a/FOSSDB_web/apps/fossdb/views.py b/FOSSDB_web/apps/fossdb/views.py index 63d4ae2..34bb139 100644 --- a/FOSSDB_web/apps/fossdb/views.py +++ b/FOSSDB_web/apps/fossdb/views.py @@ -1,8 +1,9 @@ from django.contrib.auth.decorators import login_required, permission_required from django.shortcuts import redirect, render +from hosting_platform.forms import ProjectHostingPlatformFormSet from programming_language.forms import ProjectProgrammingLanguageFormSet -from .forms import ProjectForm, ProjectHostingPlatformFormSet +from .forms import ProjectForm from .models import Project diff --git a/FOSSDB_web/apps/hosting_platform/admin.py b/FOSSDB_web/apps/hosting_platform/admin.py index 8c38f3f..22ac739 100644 --- a/FOSSDB_web/apps/hosting_platform/admin.py +++ b/FOSSDB_web/apps/hosting_platform/admin.py @@ -1,3 +1,11 @@ from django.contrib import admin -# Register your models here. +from .models import HostingPlatform, ProjectHostingPlatform + + +class ProjectHostingPlatformInline(admin.TabularInline): + model = ProjectHostingPlatform + extra = 1 + + +admin.site.register(HostingPlatform) diff --git a/FOSSDB_web/apps/hosting_platform/forms.py b/FOSSDB_web/apps/hosting_platform/forms.py new file mode 100644 index 0000000..7d39747 --- /dev/null +++ b/FOSSDB_web/apps/hosting_platform/forms.py @@ -0,0 +1,21 @@ +from django import forms +from fossdb.models import Project + +from .models import HostingPlatform, ProjectHostingPlatform + + +class HostingPlatformForm(forms.ModelForm): + url = forms.URLField() + + class Meta: + model = HostingPlatform + fields = ["hosting_platform", "url"] + + +ProjectHostingPlatformFormSet = forms.inlineformset_factory( + Project, + ProjectHostingPlatform, + form=HostingPlatformForm, + extra=1, + can_delete=False +) diff --git a/FOSSDB_web/apps/hosting_platform/models.py b/FOSSDB_web/apps/hosting_platform/models.py index 71a8362..c401aa0 100644 --- a/FOSSDB_web/apps/hosting_platform/models.py +++ b/FOSSDB_web/apps/hosting_platform/models.py @@ -1,3 +1,17 @@ from django.db import models -# Create your models here. + +class HostingPlatform(models.Model): + hosting_platform = models.CharField(max_length=100) + + def __str__(self): + return self.hosting_platform + + +class ProjectHostingPlatform(models.Model): + project = models.ForeignKey("Project", on_delete=models.CASCADE) + hosting_platform = models.ForeignKey(HostingPlatform, on_delete=models.CASCADE) + url = models.URLField() + + def __str__(self): + return f"{self.project} | {self.hosting_platform}" From 311780d2e2d139709f3076f715fd52adf8d9e07a Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Sat, 8 Apr 2023 13:59:22 +0300 Subject: [PATCH 059/144] Created Tag app --- FOSSDB_web/apps/fossdb/admin.py | 1 - FOSSDB_web/apps/tag/__init__.py | 0 FOSSDB_web/apps/tag/admin.py | 3 +++ FOSSDB_web/apps/tag/apps.py | 6 ++++++ FOSSDB_web/apps/tag/migrations/__init__.py | 0 FOSSDB_web/apps/tag/models.py | 3 +++ FOSSDB_web/apps/tag/tests.py | 3 +++ FOSSDB_web/apps/tag/views.py | 3 +++ FOSSDB_web/settings.py | 1 + 9 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 FOSSDB_web/apps/tag/__init__.py create mode 100644 FOSSDB_web/apps/tag/admin.py create mode 100644 FOSSDB_web/apps/tag/apps.py create mode 100644 FOSSDB_web/apps/tag/migrations/__init__.py create mode 100644 FOSSDB_web/apps/tag/models.py create mode 100644 FOSSDB_web/apps/tag/tests.py create mode 100644 FOSSDB_web/apps/tag/views.py diff --git a/FOSSDB_web/apps/fossdb/admin.py b/FOSSDB_web/apps/fossdb/admin.py index a74ba9e..00be6f8 100644 --- a/FOSSDB_web/apps/fossdb/admin.py +++ b/FOSSDB_web/apps/fossdb/admin.py @@ -17,4 +17,3 @@ class ProjectAdmin(admin.ModelAdmin): admin.site.register(Project, ProjectAdmin) -admin.site.register(Tag) diff --git a/FOSSDB_web/apps/tag/__init__.py b/FOSSDB_web/apps/tag/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/FOSSDB_web/apps/tag/admin.py b/FOSSDB_web/apps/tag/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/FOSSDB_web/apps/tag/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/FOSSDB_web/apps/tag/apps.py b/FOSSDB_web/apps/tag/apps.py new file mode 100644 index 0000000..72862e5 --- /dev/null +++ b/FOSSDB_web/apps/tag/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class TagConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'tag' diff --git a/FOSSDB_web/apps/tag/migrations/__init__.py b/FOSSDB_web/apps/tag/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/FOSSDB_web/apps/tag/models.py b/FOSSDB_web/apps/tag/models.py new file mode 100644 index 0000000..71a8362 --- /dev/null +++ b/FOSSDB_web/apps/tag/models.py @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. diff --git a/FOSSDB_web/apps/tag/tests.py b/FOSSDB_web/apps/tag/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/FOSSDB_web/apps/tag/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/FOSSDB_web/apps/tag/views.py b/FOSSDB_web/apps/tag/views.py new file mode 100644 index 0000000..91ea44a --- /dev/null +++ b/FOSSDB_web/apps/tag/views.py @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here. diff --git a/FOSSDB_web/settings.py b/FOSSDB_web/settings.py index f3438e9..f52db99 100644 --- a/FOSSDB_web/settings.py +++ b/FOSSDB_web/settings.py @@ -41,6 +41,7 @@ INSTALLED_APPS = [ "account", "programming_language", "hosting_platform", + "tag", "django.contrib.admin", "django.contrib.auth", "django.contrib.contenttypes", From 6272b312c236511ea0361385ec993a16d7687c0a Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Sat, 8 Apr 2023 14:01:07 +0300 Subject: [PATCH 060/144] Moved Tag model to separete app --- FOSSDB_web/apps/fossdb/models.py | 8 ++------ FOSSDB_web/apps/tag/admin.py | 4 +++- FOSSDB_web/apps/tag/models.py | 6 +++++- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/FOSSDB_web/apps/fossdb/models.py b/FOSSDB_web/apps/fossdb/models.py index 4700ea9..7ea3a6c 100644 --- a/FOSSDB_web/apps/fossdb/models.py +++ b/FOSSDB_web/apps/fossdb/models.py @@ -6,15 +6,11 @@ from hosting_platform.models import HostingPlatform from license.models import License from programming_language.models import ProgrammingLanguage +from tag.models import Tag + User = settings.AUTH_USER_MODEL -class Tag(models.Model): - name = models.CharField(max_length=100) - description = models.TextField(null=True, blank=True) - icon = models.ImageField(upload_to="types/icons/", null=True, blank=True) - - class Project(models.Model): uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) author = models.ForeignKey(User, on_delete=models.CASCADE) diff --git a/FOSSDB_web/apps/tag/admin.py b/FOSSDB_web/apps/tag/admin.py index 8c38f3f..1fdb041 100644 --- a/FOSSDB_web/apps/tag/admin.py +++ b/FOSSDB_web/apps/tag/admin.py @@ -1,3 +1,5 @@ from django.contrib import admin -# Register your models here. +from .models import Tag + +admin.site.register(Tag) diff --git a/FOSSDB_web/apps/tag/models.py b/FOSSDB_web/apps/tag/models.py index 71a8362..0172969 100644 --- a/FOSSDB_web/apps/tag/models.py +++ b/FOSSDB_web/apps/tag/models.py @@ -1,3 +1,7 @@ from django.db import models -# Create your models here. + +class Tag(models.Model): + name = models.CharField(max_length=100) + description = models.TextField(null=True, blank=True) + icon = models.ImageField(upload_to="types/icons/", null=True, blank=True) From a79a31154a30230e971828f51afa6425f9c8dbf7 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Sat, 8 Apr 2023 14:04:45 +0300 Subject: [PATCH 061/144] Set default fields --- FOSSDB_web/apps/fossdb/models.py | 5 ++--- FOSSDB_web/apps/license/models.py | 6 +++--- FOSSDB_web/apps/tag/models.py | 2 +- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/FOSSDB_web/apps/fossdb/models.py b/FOSSDB_web/apps/fossdb/models.py index 7ea3a6c..37fddeb 100644 --- a/FOSSDB_web/apps/fossdb/models.py +++ b/FOSSDB_web/apps/fossdb/models.py @@ -5,7 +5,6 @@ from django.db import models from hosting_platform.models import HostingPlatform from license.models import License from programming_language.models import ProgrammingLanguage - from tag.models import Tag User = settings.AUTH_USER_MODEL @@ -14,8 +13,8 @@ User = settings.AUTH_USER_MODEL class Project(models.Model): uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) author = models.ForeignKey(User, on_delete=models.CASCADE) - name = models.CharField(max_length=255, null=False) - description = models.TextField() + name = models.CharField(max_length=255) + description = models.TextField(blank=True, default="") licenses = models.ManyToManyField(License) programming_languages = models.ManyToManyField(ProgrammingLanguage, through="ProjectProgrammingLanguage", related_name="projects") hosting_platform = models.ManyToManyField(HostingPlatform, through="ProjectHostingPlatform", related_name="projects") diff --git a/FOSSDB_web/apps/license/models.py b/FOSSDB_web/apps/license/models.py index 172f707..572a0b4 100644 --- a/FOSSDB_web/apps/license/models.py +++ b/FOSSDB_web/apps/license/models.py @@ -3,9 +3,9 @@ from django.db import models class License(models.Model): short_name = models.CharField(max_length=50) - full_name = models.CharField(max_length=100, null=True, blank=True) - url = models.URLField(null=True, blank=True) - description = models.TextField(null=True, blank=True) + full_name = models.CharField(max_length=100, blank=True, default="") + url = models.URLField(blank=True, default="") + description = models.TextField(blank=True, default="") def __str__(self): return self.short_name diff --git a/FOSSDB_web/apps/tag/models.py b/FOSSDB_web/apps/tag/models.py index 0172969..99ab5f3 100644 --- a/FOSSDB_web/apps/tag/models.py +++ b/FOSSDB_web/apps/tag/models.py @@ -3,5 +3,5 @@ from django.db import models class Tag(models.Model): name = models.CharField(max_length=100) - description = models.TextField(null=True, blank=True) + description = models.TextField(blank=True, default="") icon = models.ImageField(upload_to="types/icons/", null=True, blank=True) From 17ad8a41f811e25a9d633a82ca29f78046cd0cd7 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Sat, 8 Apr 2023 15:16:34 +0300 Subject: [PATCH 062/144] Moved Project model to separate app --- FOSSDB_web/apps/fossdb/admin.py | 19 ----- FOSSDB_web/apps/fossdb/forms.py | 22 ----- .../{ => fossdb}/hosting_platform/__init__.py | 0 .../{ => fossdb}/hosting_platform/admin.py | 0 .../apps/fossdb/hosting_platform/apps.py | 6 ++ .../apps/fossdb/hosting_platform/forms.py | 11 +++ .../hosting_platform/migrations/__init__.py | 0 .../{ => fossdb}/hosting_platform/models.py | 0 .../{ => fossdb}/hosting_platform/tests.py | 0 .../{ => fossdb}/hosting_platform/views.py | 0 .../apps/{ => fossdb}/license/__init__.py | 0 FOSSDB_web/apps/{ => fossdb}/license/admin.py | 0 FOSSDB_web/apps/fossdb/license/apps.py | 6 ++ FOSSDB_web/apps/{ => fossdb}/license/forms.py | 0 .../license/migrations/__init__.py | 0 .../apps/{ => fossdb}/license/models.py | 0 FOSSDB_web/apps/{ => fossdb}/license/tests.py | 0 FOSSDB_web/apps/{ => fossdb}/license/views.py | 0 .../apps/fossdb/migrations/0001_initial.py | 85 ------------------- ...2_delete_license_alter_project_licenses.py | 22 ----- .../programming_language/__init__.py | 0 .../programming_language/admin.py | 0 .../apps/fossdb/programming_language/apps.py | 6 ++ .../apps/fossdb/programming_language/forms.py | 11 +++ .../migrations/__init__.py | 0 .../programming_language/models.py | 0 .../programming_language/tests.py | 0 .../programming_language/views.py | 0 .../apps/{tag => fossdb/project}/__init__.py | 0 FOSSDB_web/apps/fossdb/project/admin.py | 20 +++++ FOSSDB_web/apps/fossdb/project/apps.py | 6 ++ FOSSDB_web/apps/fossdb/project/forms.py | 45 ++++++++++ .../project}/migrations/__init__.py | 0 .../apps/fossdb/{ => project}/models.py | 15 ++-- FOSSDB_web/apps/fossdb/project/tests.py | 0 FOSSDB_web/apps/fossdb/project/views.py | 45 ++++++++++ FOSSDB_web/apps/fossdb/tag/__init__.py | 0 FOSSDB_web/apps/{ => fossdb}/tag/admin.py | 0 FOSSDB_web/apps/fossdb/tag/apps.py | 6 ++ .../apps/fossdb/tag/migrations/__init__.py | 0 FOSSDB_web/apps/{ => fossdb}/tag/models.py | 0 FOSSDB_web/apps/{ => fossdb}/tag/tests.py | 0 FOSSDB_web/apps/{ => fossdb}/tag/views.py | 0 FOSSDB_web/apps/fossdb/views.py | 43 +--------- FOSSDB_web/apps/hosting_platform/apps.py | 6 -- FOSSDB_web/apps/hosting_platform/forms.py | 21 ----- FOSSDB_web/apps/license/apps.py | 6 -- .../apps/license/migrations/0001_initial.py | 24 ------ FOSSDB_web/apps/programming_language/apps.py | 6 -- FOSSDB_web/apps/programming_language/forms.py | 21 ----- FOSSDB_web/apps/tag/apps.py | 6 -- FOSSDB_web/settings.py | 11 +-- 52 files changed, 179 insertions(+), 290 deletions(-) delete mode 100644 FOSSDB_web/apps/fossdb/forms.py rename FOSSDB_web/apps/{ => fossdb}/hosting_platform/__init__.py (100%) rename FOSSDB_web/apps/{ => fossdb}/hosting_platform/admin.py (100%) create mode 100644 FOSSDB_web/apps/fossdb/hosting_platform/apps.py create mode 100644 FOSSDB_web/apps/fossdb/hosting_platform/forms.py rename FOSSDB_web/apps/{ => fossdb}/hosting_platform/migrations/__init__.py (100%) rename FOSSDB_web/apps/{ => fossdb}/hosting_platform/models.py (100%) rename FOSSDB_web/apps/{ => fossdb}/hosting_platform/tests.py (100%) rename FOSSDB_web/apps/{ => fossdb}/hosting_platform/views.py (100%) rename FOSSDB_web/apps/{ => fossdb}/license/__init__.py (100%) rename FOSSDB_web/apps/{ => fossdb}/license/admin.py (100%) create mode 100644 FOSSDB_web/apps/fossdb/license/apps.py rename FOSSDB_web/apps/{ => fossdb}/license/forms.py (100%) rename FOSSDB_web/apps/{ => fossdb}/license/migrations/__init__.py (100%) rename FOSSDB_web/apps/{ => fossdb}/license/models.py (100%) rename FOSSDB_web/apps/{ => fossdb}/license/tests.py (100%) rename FOSSDB_web/apps/{ => fossdb}/license/views.py (100%) delete mode 100644 FOSSDB_web/apps/fossdb/migrations/0001_initial.py delete mode 100644 FOSSDB_web/apps/fossdb/migrations/0002_delete_license_alter_project_licenses.py rename FOSSDB_web/apps/{ => fossdb}/programming_language/__init__.py (100%) rename FOSSDB_web/apps/{ => fossdb}/programming_language/admin.py (100%) create mode 100644 FOSSDB_web/apps/fossdb/programming_language/apps.py create mode 100644 FOSSDB_web/apps/fossdb/programming_language/forms.py rename FOSSDB_web/apps/{ => fossdb}/programming_language/migrations/__init__.py (100%) rename FOSSDB_web/apps/{ => fossdb}/programming_language/models.py (100%) rename FOSSDB_web/apps/{ => fossdb}/programming_language/tests.py (100%) rename FOSSDB_web/apps/{ => fossdb}/programming_language/views.py (100%) rename FOSSDB_web/apps/{tag => fossdb/project}/__init__.py (100%) create mode 100644 FOSSDB_web/apps/fossdb/project/admin.py create mode 100644 FOSSDB_web/apps/fossdb/project/apps.py create mode 100644 FOSSDB_web/apps/fossdb/project/forms.py rename FOSSDB_web/apps/{tag => fossdb/project}/migrations/__init__.py (100%) rename FOSSDB_web/apps/fossdb/{ => project}/models.py (67%) create mode 100644 FOSSDB_web/apps/fossdb/project/tests.py create mode 100644 FOSSDB_web/apps/fossdb/project/views.py create mode 100644 FOSSDB_web/apps/fossdb/tag/__init__.py rename FOSSDB_web/apps/{ => fossdb}/tag/admin.py (100%) create mode 100644 FOSSDB_web/apps/fossdb/tag/apps.py create mode 100644 FOSSDB_web/apps/fossdb/tag/migrations/__init__.py rename FOSSDB_web/apps/{ => fossdb}/tag/models.py (100%) rename FOSSDB_web/apps/{ => fossdb}/tag/tests.py (100%) rename FOSSDB_web/apps/{ => fossdb}/tag/views.py (100%) delete mode 100644 FOSSDB_web/apps/hosting_platform/apps.py delete mode 100644 FOSSDB_web/apps/hosting_platform/forms.py delete mode 100644 FOSSDB_web/apps/license/apps.py delete mode 100644 FOSSDB_web/apps/license/migrations/0001_initial.py delete mode 100644 FOSSDB_web/apps/programming_language/apps.py delete mode 100644 FOSSDB_web/apps/programming_language/forms.py delete mode 100644 FOSSDB_web/apps/tag/apps.py diff --git a/FOSSDB_web/apps/fossdb/admin.py b/FOSSDB_web/apps/fossdb/admin.py index 00be6f8..e69de29 100644 --- a/FOSSDB_web/apps/fossdb/admin.py +++ b/FOSSDB_web/apps/fossdb/admin.py @@ -1,19 +0,0 @@ -from django.contrib import admin -from hosting_platform.admin import ProjectHostingPlatformInline -from programming_language.admin import ProjectProgrammingLanguageInline - -from .models import Project - - -class ProjectAdmin(admin.ModelAdmin): - inlines = [ProjectProgrammingLanguageInline, ProjectHostingPlatformInline] - list_display = ("author", "name", "_languages", "_hosting_platform") - - def _languages(self, object): - return " | ".join([i.language.language for i in object.projectprogramminglanguage_set.all()]) - - def _hosting_platform(self, object): - return " | ".join([i.hosting_platform.hosting_platform for i in object.projecthostingplatform_set.all()]) - - -admin.site.register(Project, ProjectAdmin) diff --git a/FOSSDB_web/apps/fossdb/forms.py b/FOSSDB_web/apps/fossdb/forms.py deleted file mode 100644 index b1f60e2..0000000 --- a/FOSSDB_web/apps/fossdb/forms.py +++ /dev/null @@ -1,22 +0,0 @@ -from django import forms - -from .models import Project - - -class ProjectForm(forms.ModelForm): - - class Meta: - model = Project - fields = ["name", "description", "licenses"] - - widgets = { - "name": forms.TextInput(attrs={ - "class": "form-control", - "placeholder": "Project name", - }), - "description": forms.Textarea(attrs={ - "class": "form-control", - "placeholder": "Description", - }), - "licenses": forms.CheckboxSelectMultiple(), - } diff --git a/FOSSDB_web/apps/hosting_platform/__init__.py b/FOSSDB_web/apps/fossdb/hosting_platform/__init__.py similarity index 100% rename from FOSSDB_web/apps/hosting_platform/__init__.py rename to FOSSDB_web/apps/fossdb/hosting_platform/__init__.py diff --git a/FOSSDB_web/apps/hosting_platform/admin.py b/FOSSDB_web/apps/fossdb/hosting_platform/admin.py similarity index 100% rename from FOSSDB_web/apps/hosting_platform/admin.py rename to FOSSDB_web/apps/fossdb/hosting_platform/admin.py diff --git a/FOSSDB_web/apps/fossdb/hosting_platform/apps.py b/FOSSDB_web/apps/fossdb/hosting_platform/apps.py new file mode 100644 index 0000000..e041c8e --- /dev/null +++ b/FOSSDB_web/apps/fossdb/hosting_platform/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class HostingPlatformConfig(AppConfig): + default_auto_field = "django.db.models.BigAutoField" + name = "fossdb.hosting_platform" diff --git a/FOSSDB_web/apps/fossdb/hosting_platform/forms.py b/FOSSDB_web/apps/fossdb/hosting_platform/forms.py new file mode 100644 index 0000000..661213f --- /dev/null +++ b/FOSSDB_web/apps/fossdb/hosting_platform/forms.py @@ -0,0 +1,11 @@ +from django import forms + +from .models import HostingPlatform + + +class HostingPlatformForm(forms.ModelForm): + url = forms.URLField() + + class Meta: + model = HostingPlatform + fields = ["hosting_platform", "url"] diff --git a/FOSSDB_web/apps/hosting_platform/migrations/__init__.py b/FOSSDB_web/apps/fossdb/hosting_platform/migrations/__init__.py similarity index 100% rename from FOSSDB_web/apps/hosting_platform/migrations/__init__.py rename to FOSSDB_web/apps/fossdb/hosting_platform/migrations/__init__.py diff --git a/FOSSDB_web/apps/hosting_platform/models.py b/FOSSDB_web/apps/fossdb/hosting_platform/models.py similarity index 100% rename from FOSSDB_web/apps/hosting_platform/models.py rename to FOSSDB_web/apps/fossdb/hosting_platform/models.py diff --git a/FOSSDB_web/apps/hosting_platform/tests.py b/FOSSDB_web/apps/fossdb/hosting_platform/tests.py similarity index 100% rename from FOSSDB_web/apps/hosting_platform/tests.py rename to FOSSDB_web/apps/fossdb/hosting_platform/tests.py diff --git a/FOSSDB_web/apps/hosting_platform/views.py b/FOSSDB_web/apps/fossdb/hosting_platform/views.py similarity index 100% rename from FOSSDB_web/apps/hosting_platform/views.py rename to FOSSDB_web/apps/fossdb/hosting_platform/views.py diff --git a/FOSSDB_web/apps/license/__init__.py b/FOSSDB_web/apps/fossdb/license/__init__.py similarity index 100% rename from FOSSDB_web/apps/license/__init__.py rename to FOSSDB_web/apps/fossdb/license/__init__.py diff --git a/FOSSDB_web/apps/license/admin.py b/FOSSDB_web/apps/fossdb/license/admin.py similarity index 100% rename from FOSSDB_web/apps/license/admin.py rename to FOSSDB_web/apps/fossdb/license/admin.py diff --git a/FOSSDB_web/apps/fossdb/license/apps.py b/FOSSDB_web/apps/fossdb/license/apps.py new file mode 100644 index 0000000..4e1d259 --- /dev/null +++ b/FOSSDB_web/apps/fossdb/license/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class LicenseConfig(AppConfig): + default_auto_field = "django.db.models.BigAutoField" + name = "fossdb.license" diff --git a/FOSSDB_web/apps/license/forms.py b/FOSSDB_web/apps/fossdb/license/forms.py similarity index 100% rename from FOSSDB_web/apps/license/forms.py rename to FOSSDB_web/apps/fossdb/license/forms.py diff --git a/FOSSDB_web/apps/license/migrations/__init__.py b/FOSSDB_web/apps/fossdb/license/migrations/__init__.py similarity index 100% rename from FOSSDB_web/apps/license/migrations/__init__.py rename to FOSSDB_web/apps/fossdb/license/migrations/__init__.py diff --git a/FOSSDB_web/apps/license/models.py b/FOSSDB_web/apps/fossdb/license/models.py similarity index 100% rename from FOSSDB_web/apps/license/models.py rename to FOSSDB_web/apps/fossdb/license/models.py diff --git a/FOSSDB_web/apps/license/tests.py b/FOSSDB_web/apps/fossdb/license/tests.py similarity index 100% rename from FOSSDB_web/apps/license/tests.py rename to FOSSDB_web/apps/fossdb/license/tests.py diff --git a/FOSSDB_web/apps/license/views.py b/FOSSDB_web/apps/fossdb/license/views.py similarity index 100% rename from FOSSDB_web/apps/license/views.py rename to FOSSDB_web/apps/fossdb/license/views.py diff --git a/FOSSDB_web/apps/fossdb/migrations/0001_initial.py b/FOSSDB_web/apps/fossdb/migrations/0001_initial.py deleted file mode 100644 index d43573f..0000000 --- a/FOSSDB_web/apps/fossdb/migrations/0001_initial.py +++ /dev/null @@ -1,85 +0,0 @@ -# Generated by Django 4.1.7 on 2023-04-07 23:05 - -from django.conf import settings -from django.db import migrations, models -import django.db.models.deletion -import uuid - - -class Migration(migrations.Migration): - - initial = True - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ] - - operations = [ - migrations.CreateModel( - name='HostingPlatform', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('hosting_platform', models.CharField(max_length=100)), - ], - ), - migrations.CreateModel( - name='License', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('short_name', models.CharField(max_length=50)), - ('full_name', models.CharField(blank=True, max_length=100, null=True)), - ('url', models.URLField(blank=True, null=True)), - ('description', models.TextField(blank=True, null=True)), - ], - ), - migrations.CreateModel( - name='ProgrammingLanguage', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('language', models.CharField(max_length=100)), - ], - ), - migrations.CreateModel( - name='Project', - fields=[ - ('uuid', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), - ('name', models.CharField(max_length=255)), - ('description', models.TextField()), - ('date_created', models.DateTimeField(auto_now_add=True)), - ('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), - ], - ), - migrations.CreateModel( - name='ProjectProgrammingLanguage', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('percentage', models.PositiveIntegerField()), - ('language', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='fossdb.programminglanguage')), - ('project', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='fossdb.project')), - ], - ), - migrations.CreateModel( - name='ProjectHostingPlatform', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('url', models.URLField()), - ('hosting_platform', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='fossdb.hostingplatform')), - ('project', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='fossdb.project')), - ], - ), - migrations.AddField( - model_name='project', - name='hosting_platform', - field=models.ManyToManyField(related_name='projects', through='fossdb.ProjectHostingPlatform', to='fossdb.hostingplatform'), - ), - migrations.AddField( - model_name='project', - name='licenses', - field=models.ManyToManyField(to='fossdb.license'), - ), - migrations.AddField( - model_name='project', - name='programming_languages', - field=models.ManyToManyField(related_name='projects', through='fossdb.ProjectProgrammingLanguage', to='fossdb.programminglanguage'), - ), - ] diff --git a/FOSSDB_web/apps/fossdb/migrations/0002_delete_license_alter_project_licenses.py b/FOSSDB_web/apps/fossdb/migrations/0002_delete_license_alter_project_licenses.py deleted file mode 100644 index 0244548..0000000 --- a/FOSSDB_web/apps/fossdb/migrations/0002_delete_license_alter_project_licenses.py +++ /dev/null @@ -1,22 +0,0 @@ -# Generated by Django 4.1.7 on 2023-04-08 10:14 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('license', '0001_initial'), - ('fossdb', '0001_initial'), - ] - - operations = [ - migrations.DeleteModel( - name='License', - ), - migrations.AlterField( - model_name='project', - name='licenses', - field=models.ManyToManyField(to='license.license'), - ), - ] diff --git a/FOSSDB_web/apps/programming_language/__init__.py b/FOSSDB_web/apps/fossdb/programming_language/__init__.py similarity index 100% rename from FOSSDB_web/apps/programming_language/__init__.py rename to FOSSDB_web/apps/fossdb/programming_language/__init__.py diff --git a/FOSSDB_web/apps/programming_language/admin.py b/FOSSDB_web/apps/fossdb/programming_language/admin.py similarity index 100% rename from FOSSDB_web/apps/programming_language/admin.py rename to FOSSDB_web/apps/fossdb/programming_language/admin.py diff --git a/FOSSDB_web/apps/fossdb/programming_language/apps.py b/FOSSDB_web/apps/fossdb/programming_language/apps.py new file mode 100644 index 0000000..a460465 --- /dev/null +++ b/FOSSDB_web/apps/fossdb/programming_language/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class ProgrammingLanguageConfig(AppConfig): + default_auto_field = "django.db.models.BigAutoField" + name = "fossdb.programming_language" diff --git a/FOSSDB_web/apps/fossdb/programming_language/forms.py b/FOSSDB_web/apps/fossdb/programming_language/forms.py new file mode 100644 index 0000000..4478a51 --- /dev/null +++ b/FOSSDB_web/apps/fossdb/programming_language/forms.py @@ -0,0 +1,11 @@ +from django import forms + +from .models import ProgrammingLanguage + + +class ProgrammingLanguageForm(forms.ModelForm): + percentage = forms.IntegerField(min_value=0, max_value=100) + + class Meta: + model = ProgrammingLanguage + fields = ["language", "percentage"] diff --git a/FOSSDB_web/apps/programming_language/migrations/__init__.py b/FOSSDB_web/apps/fossdb/programming_language/migrations/__init__.py similarity index 100% rename from FOSSDB_web/apps/programming_language/migrations/__init__.py rename to FOSSDB_web/apps/fossdb/programming_language/migrations/__init__.py diff --git a/FOSSDB_web/apps/programming_language/models.py b/FOSSDB_web/apps/fossdb/programming_language/models.py similarity index 100% rename from FOSSDB_web/apps/programming_language/models.py rename to FOSSDB_web/apps/fossdb/programming_language/models.py diff --git a/FOSSDB_web/apps/programming_language/tests.py b/FOSSDB_web/apps/fossdb/programming_language/tests.py similarity index 100% rename from FOSSDB_web/apps/programming_language/tests.py rename to FOSSDB_web/apps/fossdb/programming_language/tests.py diff --git a/FOSSDB_web/apps/programming_language/views.py b/FOSSDB_web/apps/fossdb/programming_language/views.py similarity index 100% rename from FOSSDB_web/apps/programming_language/views.py rename to FOSSDB_web/apps/fossdb/programming_language/views.py diff --git a/FOSSDB_web/apps/tag/__init__.py b/FOSSDB_web/apps/fossdb/project/__init__.py similarity index 100% rename from FOSSDB_web/apps/tag/__init__.py rename to FOSSDB_web/apps/fossdb/project/__init__.py diff --git a/FOSSDB_web/apps/fossdb/project/admin.py b/FOSSDB_web/apps/fossdb/project/admin.py new file mode 100644 index 0000000..936ecd6 --- /dev/null +++ b/FOSSDB_web/apps/fossdb/project/admin.py @@ -0,0 +1,20 @@ +from django.contrib import admin + +from fossdb.hosting_platform.admin import ProjectHostingPlatformInline +from fossdb.programming_language.admin import ProjectProgrammingLanguageInline + +from .models import Project + + +class ProjectAdmin(admin.ModelAdmin): + inlines = [ProjectProgrammingLanguageInline, ProjectHostingPlatformInline] + list_display = ("author", "name", "_languages", "_hosting_platform") + + def _languages(self, object): + return " | ".join([i.language.language for i in object.projectprogramminglanguage_set.all()]) + + def _hosting_platform(self, object): + return " | ".join([i.hosting_platform.hosting_platform for i in object.projecthostingplatform_set.all()]) + + +admin.site.register(Project, ProjectAdmin) diff --git a/FOSSDB_web/apps/fossdb/project/apps.py b/FOSSDB_web/apps/fossdb/project/apps.py new file mode 100644 index 0000000..a8017ec --- /dev/null +++ b/FOSSDB_web/apps/fossdb/project/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class ProjectConfig(AppConfig): + default_auto_field = "django.db.models.BigAutoField" + name = "fossdb.project" diff --git a/FOSSDB_web/apps/fossdb/project/forms.py b/FOSSDB_web/apps/fossdb/project/forms.py new file mode 100644 index 0000000..26bd551 --- /dev/null +++ b/FOSSDB_web/apps/fossdb/project/forms.py @@ -0,0 +1,45 @@ +from django import forms + +from fossdb.hosting_platform.forms import HostingPlatformForm +from fossdb.hosting_platform.models import ProjectHostingPlatform +from fossdb.programming_language.forms import ProgrammingLanguageForm +from fossdb.programming_language.models import ProjectProgrammingLanguage + +from .models import Project + + +class ProjectForm(forms.ModelForm): + + class Meta: + model = Project + fields = ["name", "description", "licenses"] + + widgets = { + "name": forms.TextInput(attrs={ + "class": "form-control", + "placeholder": "Project name", + }), + "description": forms.Textarea(attrs={ + "class": "form-control", + "placeholder": "Description", + }), + "licenses": forms.CheckboxSelectMultiple(), + } + + +ProjectHostingPlatformFormSet = forms.inlineformset_factory( + Project, + ProjectHostingPlatform, + form=HostingPlatformForm, + extra=1, + can_delete=False +) + + +ProjectProgrammingLanguageFormSet = forms.inlineformset_factory( + Project, + ProjectProgrammingLanguage, + form=ProgrammingLanguageForm, + extra=1, + can_delete=True, +) diff --git a/FOSSDB_web/apps/tag/migrations/__init__.py b/FOSSDB_web/apps/fossdb/project/migrations/__init__.py similarity index 100% rename from FOSSDB_web/apps/tag/migrations/__init__.py rename to FOSSDB_web/apps/fossdb/project/migrations/__init__.py diff --git a/FOSSDB_web/apps/fossdb/models.py b/FOSSDB_web/apps/fossdb/project/models.py similarity index 67% rename from FOSSDB_web/apps/fossdb/models.py rename to FOSSDB_web/apps/fossdb/project/models.py index 37fddeb..37dd50e 100644 --- a/FOSSDB_web/apps/fossdb/models.py +++ b/FOSSDB_web/apps/fossdb/project/models.py @@ -2,10 +2,13 @@ import uuid from django.conf import settings from django.db import models -from hosting_platform.models import HostingPlatform -from license.models import License -from programming_language.models import ProgrammingLanguage -from tag.models import Tag + +from fossdb.hosting_platform.models import (HostingPlatform, + ProjectHostingPlatform) +from fossdb.license.models import License +from fossdb.programming_language.models import (ProgrammingLanguage, + ProjectProgrammingLanguage) +from fossdb.tag.models import Tag User = settings.AUTH_USER_MODEL @@ -16,8 +19,8 @@ class Project(models.Model): name = models.CharField(max_length=255) description = models.TextField(blank=True, default="") licenses = models.ManyToManyField(License) - programming_languages = models.ManyToManyField(ProgrammingLanguage, through="ProjectProgrammingLanguage", related_name="projects") - hosting_platform = models.ManyToManyField(HostingPlatform, through="ProjectHostingPlatform", related_name="projects") + programming_languages = models.ManyToManyField(ProgrammingLanguage, through=ProjectProgrammingLanguage, related_name="projects") + hosting_platform = models.ManyToManyField(HostingPlatform, through=ProjectHostingPlatform, related_name="projects") project_type = models.ForeignKey(Tag, on_delete=models.CASCADE, blank=True, null=True) date_created = models.DateTimeField(auto_now_add=True) diff --git a/FOSSDB_web/apps/fossdb/project/tests.py b/FOSSDB_web/apps/fossdb/project/tests.py new file mode 100644 index 0000000..e69de29 diff --git a/FOSSDB_web/apps/fossdb/project/views.py b/FOSSDB_web/apps/fossdb/project/views.py new file mode 100644 index 0000000..11b33e6 --- /dev/null +++ b/FOSSDB_web/apps/fossdb/project/views.py @@ -0,0 +1,45 @@ + +from django.contrib.auth.decorators import login_required, permission_required +from django.shortcuts import redirect, render + +from .forms import (ProjectForm, ProjectHostingPlatformFormSet, + ProjectProgrammingLanguageFormSet) +from .models import Project + +# from fossdb.hosting_platform.forms import ProjectHostingPlatformFormSet +# from fossdb.programming_language.forms import ProjectProgrammingLanguageFormSet + + +@login_required(login_url="login/") +@permission_required("fossdb.add_post", login_url="login/", raise_exception=True) +def add_project(request): + if request.method == "POST": + project_form = ProjectForm(request.POST) + language_formset = ProjectProgrammingLanguageFormSet(request.POST, instance=Project()) + host_formset = ProjectHostingPlatformFormSet(request.POST, instance=Project()) + + if project_form.is_valid() and language_formset.is_valid() and host_formset.is_valid(): + project = project_form.save(commit=False) + project.author = request.user + project.save() + + language_formset.instance = project + language_formset.save() + + host_formset.instance = project + host_formset.save() + + project_form.save_m2m() + return redirect("/") + else: + project_form = ProjectForm() + language_formset = ProjectProgrammingLanguageFormSet() + host_formset = ProjectHostingPlatformFormSet() + + context = { + "title": "Add project", + "project_form": project_form, + "language_formset": language_formset, + "host_formset": host_formset, + } + return render(request, "fossdb/add_project.html", context) diff --git a/FOSSDB_web/apps/fossdb/tag/__init__.py b/FOSSDB_web/apps/fossdb/tag/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/FOSSDB_web/apps/tag/admin.py b/FOSSDB_web/apps/fossdb/tag/admin.py similarity index 100% rename from FOSSDB_web/apps/tag/admin.py rename to FOSSDB_web/apps/fossdb/tag/admin.py diff --git a/FOSSDB_web/apps/fossdb/tag/apps.py b/FOSSDB_web/apps/fossdb/tag/apps.py new file mode 100644 index 0000000..5ce961f --- /dev/null +++ b/FOSSDB_web/apps/fossdb/tag/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class TagConfig(AppConfig): + default_auto_field = "django.db.models.BigAutoField" + name = "fossdb.tag" diff --git a/FOSSDB_web/apps/fossdb/tag/migrations/__init__.py b/FOSSDB_web/apps/fossdb/tag/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/FOSSDB_web/apps/tag/models.py b/FOSSDB_web/apps/fossdb/tag/models.py similarity index 100% rename from FOSSDB_web/apps/tag/models.py rename to FOSSDB_web/apps/fossdb/tag/models.py diff --git a/FOSSDB_web/apps/tag/tests.py b/FOSSDB_web/apps/fossdb/tag/tests.py similarity index 100% rename from FOSSDB_web/apps/tag/tests.py rename to FOSSDB_web/apps/fossdb/tag/tests.py diff --git a/FOSSDB_web/apps/tag/views.py b/FOSSDB_web/apps/fossdb/tag/views.py similarity index 100% rename from FOSSDB_web/apps/tag/views.py rename to FOSSDB_web/apps/fossdb/tag/views.py diff --git a/FOSSDB_web/apps/fossdb/views.py b/FOSSDB_web/apps/fossdb/views.py index 34bb139..0759545 100644 --- a/FOSSDB_web/apps/fossdb/views.py +++ b/FOSSDB_web/apps/fossdb/views.py @@ -1,10 +1,6 @@ -from django.contrib.auth.decorators import login_required, permission_required -from django.shortcuts import redirect, render -from hosting_platform.forms import ProjectHostingPlatformFormSet -from programming_language.forms import ProjectProgrammingLanguageFormSet +from django.shortcuts import render -from .forms import ProjectForm -from .models import Project +from fossdb.models import Project def index(request): @@ -13,38 +9,3 @@ def index(request): "projects": Project.objects.all(), } return render(request, "fossdb/index.html", context) - - -@login_required(login_url="login/") -@permission_required("fossdb.add_post", login_url="login/", raise_exception=True) -def add_project(request): - if request.method == "POST": - project_form = ProjectForm(request.POST) - language_formset = ProjectProgrammingLanguageFormSet(request.POST, instance=Project()) - host_formset = ProjectHostingPlatformFormSet(request.POST, instance=Project()) - - if project_form.is_valid() and language_formset.is_valid() and host_formset.is_valid(): - project = project_form.save(commit=False) - project.author = request.user - project.save() - - language_formset.instance = project - language_formset.save() - - host_formset.instance = project - host_formset.save() - - project_form.save_m2m() - return redirect("/") - else: - project_form = ProjectForm() - language_formset = ProjectProgrammingLanguageFormSet() - host_formset = ProjectHostingPlatformFormSet() - - context = { - "title": "Add project", - "project_form": project_form, - "language_formset": language_formset, - "host_formset": host_formset, - } - return render(request, "fossdb/add_project.html", context) diff --git a/FOSSDB_web/apps/hosting_platform/apps.py b/FOSSDB_web/apps/hosting_platform/apps.py deleted file mode 100644 index c11d49f..0000000 --- a/FOSSDB_web/apps/hosting_platform/apps.py +++ /dev/null @@ -1,6 +0,0 @@ -from django.apps import AppConfig - - -class HostingPlatformConfig(AppConfig): - default_auto_field = 'django.db.models.BigAutoField' - name = 'hosting_platform' diff --git a/FOSSDB_web/apps/hosting_platform/forms.py b/FOSSDB_web/apps/hosting_platform/forms.py deleted file mode 100644 index 7d39747..0000000 --- a/FOSSDB_web/apps/hosting_platform/forms.py +++ /dev/null @@ -1,21 +0,0 @@ -from django import forms -from fossdb.models import Project - -from .models import HostingPlatform, ProjectHostingPlatform - - -class HostingPlatformForm(forms.ModelForm): - url = forms.URLField() - - class Meta: - model = HostingPlatform - fields = ["hosting_platform", "url"] - - -ProjectHostingPlatformFormSet = forms.inlineformset_factory( - Project, - ProjectHostingPlatform, - form=HostingPlatformForm, - extra=1, - can_delete=False -) diff --git a/FOSSDB_web/apps/license/apps.py b/FOSSDB_web/apps/license/apps.py deleted file mode 100644 index af50348..0000000 --- a/FOSSDB_web/apps/license/apps.py +++ /dev/null @@ -1,6 +0,0 @@ -from django.apps import AppConfig - - -class LicenseConfig(AppConfig): - default_auto_field = 'django.db.models.BigAutoField' - name = 'license' diff --git a/FOSSDB_web/apps/license/migrations/0001_initial.py b/FOSSDB_web/apps/license/migrations/0001_initial.py deleted file mode 100644 index 26024b3..0000000 --- a/FOSSDB_web/apps/license/migrations/0001_initial.py +++ /dev/null @@ -1,24 +0,0 @@ -# Generated by Django 4.1.7 on 2023-04-08 10:14 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - initial = True - - dependencies = [ - ] - - operations = [ - migrations.CreateModel( - name='License', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('short_name', models.CharField(max_length=50)), - ('full_name', models.CharField(blank=True, max_length=100, null=True)), - ('url', models.URLField(blank=True, null=True)), - ('description', models.TextField(blank=True, null=True)), - ], - ), - ] diff --git a/FOSSDB_web/apps/programming_language/apps.py b/FOSSDB_web/apps/programming_language/apps.py deleted file mode 100644 index 4192b11..0000000 --- a/FOSSDB_web/apps/programming_language/apps.py +++ /dev/null @@ -1,6 +0,0 @@ -from django.apps import AppConfig - - -class ProgrammingLanguageConfig(AppConfig): - default_auto_field = 'django.db.models.BigAutoField' - name = 'programming_language' diff --git a/FOSSDB_web/apps/programming_language/forms.py b/FOSSDB_web/apps/programming_language/forms.py deleted file mode 100644 index 4cc8775..0000000 --- a/FOSSDB_web/apps/programming_language/forms.py +++ /dev/null @@ -1,21 +0,0 @@ -from django import forms -from fossdb.models import Project - -from .models import ProgrammingLanguage, ProjectProgrammingLanguage - - -class ProgrammingLanguageForm(forms.ModelForm): - percentage = forms.IntegerField(min_value=0, max_value=100) - - class Meta: - model = ProgrammingLanguage - fields = ["language", "percentage"] - - -ProjectProgrammingLanguageFormSet = forms.inlineformset_factory( - Project, - ProjectProgrammingLanguage, - form=ProgrammingLanguageForm, - extra=1, - can_delete=True, -) diff --git a/FOSSDB_web/apps/tag/apps.py b/FOSSDB_web/apps/tag/apps.py deleted file mode 100644 index 72862e5..0000000 --- a/FOSSDB_web/apps/tag/apps.py +++ /dev/null @@ -1,6 +0,0 @@ -from django.apps import AppConfig - - -class TagConfig(AppConfig): - default_auto_field = 'django.db.models.BigAutoField' - name = 'tag' diff --git a/FOSSDB_web/settings.py b/FOSSDB_web/settings.py index f52db99..fa5090e 100644 --- a/FOSSDB_web/settings.py +++ b/FOSSDB_web/settings.py @@ -36,12 +36,13 @@ ALLOWED_HOSTS = config["ALLOWED_HOSTS"] # Application definition INSTALLED_APPS = [ - "fossdb", - "license", "account", - "programming_language", - "hosting_platform", - "tag", + "fossdb", + "fossdb.project", + "fossdb.license", + "fossdb.programming_language", + "fossdb.hosting_platform", + "fossdb.tag", "django.contrib.admin", "django.contrib.auth", "django.contrib.contenttypes", From b4cf26465bbed68488d23fb5c93f0c6b2f044bf7 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Sat, 8 Apr 2023 15:48:44 +0300 Subject: [PATCH 063/144] Revert changes --- FOSSDB_web/apps/fossdb/admin.py | 32 ++++++ FOSSDB_web/apps/fossdb/{project => }/forms.py | 44 ++++++--- .../apps/fossdb/hosting_platform/__init__.py | 0 .../apps/fossdb/hosting_platform/admin.py | 11 --- .../apps/fossdb/hosting_platform/apps.py | 6 -- .../apps/fossdb/hosting_platform/forms.py | 11 --- .../hosting_platform/migrations/__init__.py | 0 .../apps/fossdb/hosting_platform/models.py | 17 ---- .../apps/fossdb/hosting_platform/tests.py | 3 - .../apps/fossdb/hosting_platform/views.py | 3 - FOSSDB_web/apps/fossdb/license/__init__.py | 0 FOSSDB_web/apps/fossdb/license/admin.py | 5 - FOSSDB_web/apps/fossdb/license/apps.py | 6 -- FOSSDB_web/apps/fossdb/license/forms.py | 9 -- .../fossdb/license/migrations/__init__.py | 0 FOSSDB_web/apps/fossdb/license/models.py | 11 --- FOSSDB_web/apps/fossdb/license/tests.py | 3 - FOSSDB_web/apps/fossdb/license/views.py | 0 .../apps/fossdb/migrations/0001_initial.py | 99 +++++++++++++++++++ FOSSDB_web/apps/fossdb/models.py | 74 ++++++++++++++ .../fossdb/programming_language/__init__.py | 0 .../apps/fossdb/programming_language/admin.py | 11 --- .../apps/fossdb/programming_language/apps.py | 6 -- .../apps/fossdb/programming_language/forms.py | 11 --- .../migrations/__init__.py | 0 .../fossdb/programming_language/models.py | 17 ---- .../apps/fossdb/programming_language/tests.py | 3 - .../apps/fossdb/programming_language/views.py | 3 - FOSSDB_web/apps/fossdb/project/__init__.py | 0 FOSSDB_web/apps/fossdb/project/admin.py | 20 ---- FOSSDB_web/apps/fossdb/project/apps.py | 6 -- .../fossdb/project/migrations/__init__.py | 0 FOSSDB_web/apps/fossdb/project/models.py | 33 ------- FOSSDB_web/apps/fossdb/project/tests.py | 0 FOSSDB_web/apps/fossdb/project/views.py | 45 --------- FOSSDB_web/apps/fossdb/tag/__init__.py | 0 FOSSDB_web/apps/fossdb/tag/admin.py | 5 - FOSSDB_web/apps/fossdb/tag/apps.py | 6 -- .../apps/fossdb/tag/migrations/__init__.py | 0 FOSSDB_web/apps/fossdb/tag/models.py | 7 -- FOSSDB_web/apps/fossdb/tag/tests.py | 3 - FOSSDB_web/apps/fossdb/tag/views.py | 3 - FOSSDB_web/apps/fossdb/views.py | 42 +++++++- FOSSDB_web/settings.py | 5 - 44 files changed, 276 insertions(+), 284 deletions(-) rename FOSSDB_web/apps/fossdb/{project => }/forms.py (57%) delete mode 100644 FOSSDB_web/apps/fossdb/hosting_platform/__init__.py delete mode 100644 FOSSDB_web/apps/fossdb/hosting_platform/admin.py delete mode 100644 FOSSDB_web/apps/fossdb/hosting_platform/apps.py delete mode 100644 FOSSDB_web/apps/fossdb/hosting_platform/forms.py delete mode 100644 FOSSDB_web/apps/fossdb/hosting_platform/migrations/__init__.py delete mode 100644 FOSSDB_web/apps/fossdb/hosting_platform/models.py delete mode 100644 FOSSDB_web/apps/fossdb/hosting_platform/tests.py delete mode 100644 FOSSDB_web/apps/fossdb/hosting_platform/views.py delete mode 100644 FOSSDB_web/apps/fossdb/license/__init__.py delete mode 100644 FOSSDB_web/apps/fossdb/license/admin.py delete mode 100644 FOSSDB_web/apps/fossdb/license/apps.py delete mode 100644 FOSSDB_web/apps/fossdb/license/forms.py delete mode 100644 FOSSDB_web/apps/fossdb/license/migrations/__init__.py delete mode 100644 FOSSDB_web/apps/fossdb/license/models.py delete mode 100644 FOSSDB_web/apps/fossdb/license/tests.py delete mode 100644 FOSSDB_web/apps/fossdb/license/views.py create mode 100644 FOSSDB_web/apps/fossdb/migrations/0001_initial.py create mode 100644 FOSSDB_web/apps/fossdb/models.py delete mode 100644 FOSSDB_web/apps/fossdb/programming_language/__init__.py delete mode 100644 FOSSDB_web/apps/fossdb/programming_language/admin.py delete mode 100644 FOSSDB_web/apps/fossdb/programming_language/apps.py delete mode 100644 FOSSDB_web/apps/fossdb/programming_language/forms.py delete mode 100644 FOSSDB_web/apps/fossdb/programming_language/migrations/__init__.py delete mode 100644 FOSSDB_web/apps/fossdb/programming_language/models.py delete mode 100644 FOSSDB_web/apps/fossdb/programming_language/tests.py delete mode 100644 FOSSDB_web/apps/fossdb/programming_language/views.py delete mode 100644 FOSSDB_web/apps/fossdb/project/__init__.py delete mode 100644 FOSSDB_web/apps/fossdb/project/admin.py delete mode 100644 FOSSDB_web/apps/fossdb/project/apps.py delete mode 100644 FOSSDB_web/apps/fossdb/project/migrations/__init__.py delete mode 100644 FOSSDB_web/apps/fossdb/project/models.py delete mode 100644 FOSSDB_web/apps/fossdb/project/tests.py delete mode 100644 FOSSDB_web/apps/fossdb/project/views.py delete mode 100644 FOSSDB_web/apps/fossdb/tag/__init__.py delete mode 100644 FOSSDB_web/apps/fossdb/tag/admin.py delete mode 100644 FOSSDB_web/apps/fossdb/tag/apps.py delete mode 100644 FOSSDB_web/apps/fossdb/tag/migrations/__init__.py delete mode 100644 FOSSDB_web/apps/fossdb/tag/models.py delete mode 100644 FOSSDB_web/apps/fossdb/tag/tests.py delete mode 100644 FOSSDB_web/apps/fossdb/tag/views.py diff --git a/FOSSDB_web/apps/fossdb/admin.py b/FOSSDB_web/apps/fossdb/admin.py index e69de29..21327ac 100644 --- a/FOSSDB_web/apps/fossdb/admin.py +++ b/FOSSDB_web/apps/fossdb/admin.py @@ -0,0 +1,32 @@ +from django.contrib import admin + +from .models import (HostingPlatform, License, ProgrammingLanguage, Project, + ProjectHostingPlatform, ProjectProgrammingLanguage, Tag) + + +class ProjectProgrammingLanguageInline(admin.TabularInline): + model = ProjectProgrammingLanguage + extra = 1 + + +class ProjectHostingPlatformInline(admin.TabularInline): + model = ProjectHostingPlatform + extra = 1 + + +class ProjectAdmin(admin.ModelAdmin): + inlines = [ProjectProgrammingLanguageInline, ProjectHostingPlatformInline] + list_display = ("author", "name", "_languages", "_hosting_platform") + + def _languages(self, object): + return " | ".join([i.language.language for i in object.projectprogramminglanguage_set.all()]) + + def _hosting_platform(self, object): + return " | ".join([i.hosting_platform.hosting_platform for i in object.projecthostingplatform_set.all()]) + + +admin.site.register(HostingPlatform) +admin.site.register(Project, ProjectAdmin) +admin.site.register(License) +admin.site.register(ProgrammingLanguage) +admin.site.register(Tag) diff --git a/FOSSDB_web/apps/fossdb/project/forms.py b/FOSSDB_web/apps/fossdb/forms.py similarity index 57% rename from FOSSDB_web/apps/fossdb/project/forms.py rename to FOSSDB_web/apps/fossdb/forms.py index 26bd551..9da02f4 100644 --- a/FOSSDB_web/apps/fossdb/project/forms.py +++ b/FOSSDB_web/apps/fossdb/forms.py @@ -1,11 +1,7 @@ from django import forms -from fossdb.hosting_platform.forms import HostingPlatformForm -from fossdb.hosting_platform.models import ProjectHostingPlatform -from fossdb.programming_language.forms import ProgrammingLanguageForm -from fossdb.programming_language.models import ProjectProgrammingLanguage - -from .models import Project +from .models import (HostingPlatform, License, ProgrammingLanguage, Project, + ProjectHostingPlatform, ProjectProgrammingLanguage) class ProjectForm(forms.ModelForm): @@ -27,13 +23,18 @@ class ProjectForm(forms.ModelForm): } -ProjectHostingPlatformFormSet = forms.inlineformset_factory( - Project, - ProjectHostingPlatform, - form=HostingPlatformForm, - extra=1, - can_delete=False -) +class LicenseForm(forms.ModelForm): + class Meta: + model = License + fields = ["short_name", "full_name", "url", "description"] + + +class ProgrammingLanguageForm(forms.ModelForm): + percentage = forms.IntegerField(min_value=0, max_value=100) + + class Meta: + model = ProgrammingLanguage + fields = ["language", "percentage"] ProjectProgrammingLanguageFormSet = forms.inlineformset_factory( @@ -43,3 +44,20 @@ ProjectProgrammingLanguageFormSet = forms.inlineformset_factory( extra=1, can_delete=True, ) + + +class HostingPlatformForm(forms.ModelForm): + url = forms.URLField() + + class Meta: + model = HostingPlatform + fields = ["hosting_platform", "url"] + + +ProjectHostingPlatformFormSet = forms.inlineformset_factory( + Project, + ProjectHostingPlatform, + form=HostingPlatformForm, + extra=1, + can_delete=False +) diff --git a/FOSSDB_web/apps/fossdb/hosting_platform/__init__.py b/FOSSDB_web/apps/fossdb/hosting_platform/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/FOSSDB_web/apps/fossdb/hosting_platform/admin.py b/FOSSDB_web/apps/fossdb/hosting_platform/admin.py deleted file mode 100644 index 22ac739..0000000 --- a/FOSSDB_web/apps/fossdb/hosting_platform/admin.py +++ /dev/null @@ -1,11 +0,0 @@ -from django.contrib import admin - -from .models import HostingPlatform, ProjectHostingPlatform - - -class ProjectHostingPlatformInline(admin.TabularInline): - model = ProjectHostingPlatform - extra = 1 - - -admin.site.register(HostingPlatform) diff --git a/FOSSDB_web/apps/fossdb/hosting_platform/apps.py b/FOSSDB_web/apps/fossdb/hosting_platform/apps.py deleted file mode 100644 index e041c8e..0000000 --- a/FOSSDB_web/apps/fossdb/hosting_platform/apps.py +++ /dev/null @@ -1,6 +0,0 @@ -from django.apps import AppConfig - - -class HostingPlatformConfig(AppConfig): - default_auto_field = "django.db.models.BigAutoField" - name = "fossdb.hosting_platform" diff --git a/FOSSDB_web/apps/fossdb/hosting_platform/forms.py b/FOSSDB_web/apps/fossdb/hosting_platform/forms.py deleted file mode 100644 index 661213f..0000000 --- a/FOSSDB_web/apps/fossdb/hosting_platform/forms.py +++ /dev/null @@ -1,11 +0,0 @@ -from django import forms - -from .models import HostingPlatform - - -class HostingPlatformForm(forms.ModelForm): - url = forms.URLField() - - class Meta: - model = HostingPlatform - fields = ["hosting_platform", "url"] diff --git a/FOSSDB_web/apps/fossdb/hosting_platform/migrations/__init__.py b/FOSSDB_web/apps/fossdb/hosting_platform/migrations/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/FOSSDB_web/apps/fossdb/hosting_platform/models.py b/FOSSDB_web/apps/fossdb/hosting_platform/models.py deleted file mode 100644 index c401aa0..0000000 --- a/FOSSDB_web/apps/fossdb/hosting_platform/models.py +++ /dev/null @@ -1,17 +0,0 @@ -from django.db import models - - -class HostingPlatform(models.Model): - hosting_platform = models.CharField(max_length=100) - - def __str__(self): - return self.hosting_platform - - -class ProjectHostingPlatform(models.Model): - project = models.ForeignKey("Project", on_delete=models.CASCADE) - hosting_platform = models.ForeignKey(HostingPlatform, on_delete=models.CASCADE) - url = models.URLField() - - def __str__(self): - return f"{self.project} | {self.hosting_platform}" diff --git a/FOSSDB_web/apps/fossdb/hosting_platform/tests.py b/FOSSDB_web/apps/fossdb/hosting_platform/tests.py deleted file mode 100644 index 7ce503c..0000000 --- a/FOSSDB_web/apps/fossdb/hosting_platform/tests.py +++ /dev/null @@ -1,3 +0,0 @@ -from django.test import TestCase - -# Create your tests here. diff --git a/FOSSDB_web/apps/fossdb/hosting_platform/views.py b/FOSSDB_web/apps/fossdb/hosting_platform/views.py deleted file mode 100644 index 91ea44a..0000000 --- a/FOSSDB_web/apps/fossdb/hosting_platform/views.py +++ /dev/null @@ -1,3 +0,0 @@ -from django.shortcuts import render - -# Create your views here. diff --git a/FOSSDB_web/apps/fossdb/license/__init__.py b/FOSSDB_web/apps/fossdb/license/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/FOSSDB_web/apps/fossdb/license/admin.py b/FOSSDB_web/apps/fossdb/license/admin.py deleted file mode 100644 index 9908df0..0000000 --- a/FOSSDB_web/apps/fossdb/license/admin.py +++ /dev/null @@ -1,5 +0,0 @@ -from django.contrib import admin - -from .models import License - -admin.site.register(License) diff --git a/FOSSDB_web/apps/fossdb/license/apps.py b/FOSSDB_web/apps/fossdb/license/apps.py deleted file mode 100644 index 4e1d259..0000000 --- a/FOSSDB_web/apps/fossdb/license/apps.py +++ /dev/null @@ -1,6 +0,0 @@ -from django.apps import AppConfig - - -class LicenseConfig(AppConfig): - default_auto_field = "django.db.models.BigAutoField" - name = "fossdb.license" diff --git a/FOSSDB_web/apps/fossdb/license/forms.py b/FOSSDB_web/apps/fossdb/license/forms.py deleted file mode 100644 index 0c180da..0000000 --- a/FOSSDB_web/apps/fossdb/license/forms.py +++ /dev/null @@ -1,9 +0,0 @@ -from django import forms - -from .models import License - - -class LicenseForm(forms.ModelForm): - class Meta: - model = License - fields = ["short_name", "full_name", "url", "description"] diff --git a/FOSSDB_web/apps/fossdb/license/migrations/__init__.py b/FOSSDB_web/apps/fossdb/license/migrations/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/FOSSDB_web/apps/fossdb/license/models.py b/FOSSDB_web/apps/fossdb/license/models.py deleted file mode 100644 index 572a0b4..0000000 --- a/FOSSDB_web/apps/fossdb/license/models.py +++ /dev/null @@ -1,11 +0,0 @@ -from django.db import models - - -class License(models.Model): - short_name = models.CharField(max_length=50) - full_name = models.CharField(max_length=100, blank=True, default="") - url = models.URLField(blank=True, default="") - description = models.TextField(blank=True, default="") - - def __str__(self): - return self.short_name diff --git a/FOSSDB_web/apps/fossdb/license/tests.py b/FOSSDB_web/apps/fossdb/license/tests.py deleted file mode 100644 index 7ce503c..0000000 --- a/FOSSDB_web/apps/fossdb/license/tests.py +++ /dev/null @@ -1,3 +0,0 @@ -from django.test import TestCase - -# Create your tests here. diff --git a/FOSSDB_web/apps/fossdb/license/views.py b/FOSSDB_web/apps/fossdb/license/views.py deleted file mode 100644 index e69de29..0000000 diff --git a/FOSSDB_web/apps/fossdb/migrations/0001_initial.py b/FOSSDB_web/apps/fossdb/migrations/0001_initial.py new file mode 100644 index 0000000..33d8a96 --- /dev/null +++ b/FOSSDB_web/apps/fossdb/migrations/0001_initial.py @@ -0,0 +1,99 @@ +# Generated by Django 4.1.7 on 2023-04-08 12:47 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='HostingPlatform', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('hosting_platform', models.CharField(max_length=100)), + ], + ), + migrations.CreateModel( + name='License', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('short_name', models.CharField(max_length=50)), + ('full_name', models.CharField(blank=True, default='', max_length=100)), + ('url', models.URLField(blank=True, default='')), + ('description', models.TextField(blank=True, default='')), + ], + ), + migrations.CreateModel( + name='ProgrammingLanguage', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('language', models.CharField(max_length=100)), + ], + ), + migrations.CreateModel( + name='Project', + fields=[ + ('uuid', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), + ('name', models.CharField(max_length=255)), + ('description', models.TextField(blank=True, default='')), + ('date_created', models.DateTimeField(auto_now_add=True)), + ('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ], + ), + migrations.CreateModel( + name='Tag', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=100)), + ('description', models.TextField(blank=True, default='')), + ('icon', models.ImageField(blank=True, null=True, upload_to='types/icons/')), + ], + ), + migrations.CreateModel( + name='ProjectProgrammingLanguage', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('percentage', models.PositiveIntegerField()), + ('language', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='fossdb.programminglanguage')), + ('project', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='fossdb.project')), + ], + ), + migrations.CreateModel( + name='ProjectHostingPlatform', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('url', models.URLField()), + ('hosting_platform', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='fossdb.hostingplatform')), + ('project', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='fossdb.project')), + ], + ), + migrations.AddField( + model_name='project', + name='hosting_platform', + field=models.ManyToManyField(related_name='projects', through='fossdb.ProjectHostingPlatform', to='fossdb.hostingplatform'), + ), + migrations.AddField( + model_name='project', + name='licenses', + field=models.ManyToManyField(to='fossdb.license'), + ), + migrations.AddField( + model_name='project', + name='programming_languages', + field=models.ManyToManyField(related_name='projects', through='fossdb.ProjectProgrammingLanguage', to='fossdb.programminglanguage'), + ), + migrations.AddField( + model_name='project', + name='project_type', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='fossdb.tag'), + ), + ] diff --git a/FOSSDB_web/apps/fossdb/models.py b/FOSSDB_web/apps/fossdb/models.py new file mode 100644 index 0000000..e1ae5ea --- /dev/null +++ b/FOSSDB_web/apps/fossdb/models.py @@ -0,0 +1,74 @@ +import uuid + +from django.conf import settings +from django.db import models + +User = settings.AUTH_USER_MODEL + + +class License(models.Model): + short_name = models.CharField(max_length=50) + full_name = models.CharField(max_length=100, blank=True, default="") + url = models.URLField(blank=True, default="") + description = models.TextField(blank=True, default="") + + def __str__(self): + return self.short_name + + +class HostingPlatform(models.Model): + hosting_platform = models.CharField(max_length=100) + + def __str__(self): + return self.hosting_platform + + +class ProgrammingLanguage(models.Model): + language = models.CharField(max_length=100) + + def __str__(self): + return self.language + + +class Tag(models.Model): + name = models.CharField(max_length=100) + description = models.TextField(blank=True, default="") + icon = models.ImageField(upload_to="types/icons/", null=True, blank=True) + + +class ProjectProgrammingLanguage(models.Model): + project = models.ForeignKey("Project", on_delete=models.CASCADE) + language = models.ForeignKey(ProgrammingLanguage, on_delete=models.CASCADE) + percentage = models.PositiveIntegerField() + + def __str__(self): + return f"{self.project} | {self.language} | {self.percentage}%" + + +class ProjectHostingPlatform(models.Model): + project = models.ForeignKey("Project", on_delete=models.CASCADE) + hosting_platform = models.ForeignKey(HostingPlatform, on_delete=models.CASCADE) + url = models.URLField() + + def __str__(self): + return f"{self.project} | {self.hosting_platform}" + + +class Project(models.Model): + uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) + author = models.ForeignKey(User, on_delete=models.CASCADE) + name = models.CharField(max_length=255) + description = models.TextField(blank=True, default="") + licenses = models.ManyToManyField(License) + programming_languages = models.ManyToManyField(ProgrammingLanguage, through="ProjectProgrammingLanguage", related_name="projects") + hosting_platform = models.ManyToManyField(HostingPlatform, through="ProjectHostingPlatform", related_name="projects") + project_type = models.ForeignKey(Tag, on_delete=models.CASCADE, blank=True, null=True) + date_created = models.DateTimeField(auto_now_add=True) + + def save(self, *args, **kwargs): + if not self.uuid: + self.uuid = uuid.uuid5(uuid.NAMESPACE_URL, f"{self.author.username}-{self.name}") + super().save(*args, **kwargs) + + def __str__(self): + return f"{self.author} | {self.name}" diff --git a/FOSSDB_web/apps/fossdb/programming_language/__init__.py b/FOSSDB_web/apps/fossdb/programming_language/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/FOSSDB_web/apps/fossdb/programming_language/admin.py b/FOSSDB_web/apps/fossdb/programming_language/admin.py deleted file mode 100644 index 74324bf..0000000 --- a/FOSSDB_web/apps/fossdb/programming_language/admin.py +++ /dev/null @@ -1,11 +0,0 @@ -from django.contrib import admin - -from .models import ProgrammingLanguage, ProjectProgrammingLanguage - - -class ProjectProgrammingLanguageInline(admin.TabularInline): - model = ProjectProgrammingLanguage - extra = 1 - - -admin.site.register(ProgrammingLanguage) diff --git a/FOSSDB_web/apps/fossdb/programming_language/apps.py b/FOSSDB_web/apps/fossdb/programming_language/apps.py deleted file mode 100644 index a460465..0000000 --- a/FOSSDB_web/apps/fossdb/programming_language/apps.py +++ /dev/null @@ -1,6 +0,0 @@ -from django.apps import AppConfig - - -class ProgrammingLanguageConfig(AppConfig): - default_auto_field = "django.db.models.BigAutoField" - name = "fossdb.programming_language" diff --git a/FOSSDB_web/apps/fossdb/programming_language/forms.py b/FOSSDB_web/apps/fossdb/programming_language/forms.py deleted file mode 100644 index 4478a51..0000000 --- a/FOSSDB_web/apps/fossdb/programming_language/forms.py +++ /dev/null @@ -1,11 +0,0 @@ -from django import forms - -from .models import ProgrammingLanguage - - -class ProgrammingLanguageForm(forms.ModelForm): - percentage = forms.IntegerField(min_value=0, max_value=100) - - class Meta: - model = ProgrammingLanguage - fields = ["language", "percentage"] diff --git a/FOSSDB_web/apps/fossdb/programming_language/migrations/__init__.py b/FOSSDB_web/apps/fossdb/programming_language/migrations/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/FOSSDB_web/apps/fossdb/programming_language/models.py b/FOSSDB_web/apps/fossdb/programming_language/models.py deleted file mode 100644 index 9a624f1..0000000 --- a/FOSSDB_web/apps/fossdb/programming_language/models.py +++ /dev/null @@ -1,17 +0,0 @@ -from django.db import models - - -class ProgrammingLanguage(models.Model): - language = models.CharField(max_length=100) - - def __str__(self): - return self.language - - -class ProjectProgrammingLanguage(models.Model): - project = models.ForeignKey("Project", on_delete=models.CASCADE) - language = models.ForeignKey(ProgrammingLanguage, on_delete=models.CASCADE) - percentage = models.PositiveIntegerField() - - def __str__(self): - return f"{self.project} | {self.language} | {self.percentage}%" diff --git a/FOSSDB_web/apps/fossdb/programming_language/tests.py b/FOSSDB_web/apps/fossdb/programming_language/tests.py deleted file mode 100644 index 7ce503c..0000000 --- a/FOSSDB_web/apps/fossdb/programming_language/tests.py +++ /dev/null @@ -1,3 +0,0 @@ -from django.test import TestCase - -# Create your tests here. diff --git a/FOSSDB_web/apps/fossdb/programming_language/views.py b/FOSSDB_web/apps/fossdb/programming_language/views.py deleted file mode 100644 index 91ea44a..0000000 --- a/FOSSDB_web/apps/fossdb/programming_language/views.py +++ /dev/null @@ -1,3 +0,0 @@ -from django.shortcuts import render - -# Create your views here. diff --git a/FOSSDB_web/apps/fossdb/project/__init__.py b/FOSSDB_web/apps/fossdb/project/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/FOSSDB_web/apps/fossdb/project/admin.py b/FOSSDB_web/apps/fossdb/project/admin.py deleted file mode 100644 index 936ecd6..0000000 --- a/FOSSDB_web/apps/fossdb/project/admin.py +++ /dev/null @@ -1,20 +0,0 @@ -from django.contrib import admin - -from fossdb.hosting_platform.admin import ProjectHostingPlatformInline -from fossdb.programming_language.admin import ProjectProgrammingLanguageInline - -from .models import Project - - -class ProjectAdmin(admin.ModelAdmin): - inlines = [ProjectProgrammingLanguageInline, ProjectHostingPlatformInline] - list_display = ("author", "name", "_languages", "_hosting_platform") - - def _languages(self, object): - return " | ".join([i.language.language for i in object.projectprogramminglanguage_set.all()]) - - def _hosting_platform(self, object): - return " | ".join([i.hosting_platform.hosting_platform for i in object.projecthostingplatform_set.all()]) - - -admin.site.register(Project, ProjectAdmin) diff --git a/FOSSDB_web/apps/fossdb/project/apps.py b/FOSSDB_web/apps/fossdb/project/apps.py deleted file mode 100644 index a8017ec..0000000 --- a/FOSSDB_web/apps/fossdb/project/apps.py +++ /dev/null @@ -1,6 +0,0 @@ -from django.apps import AppConfig - - -class ProjectConfig(AppConfig): - default_auto_field = "django.db.models.BigAutoField" - name = "fossdb.project" diff --git a/FOSSDB_web/apps/fossdb/project/migrations/__init__.py b/FOSSDB_web/apps/fossdb/project/migrations/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/FOSSDB_web/apps/fossdb/project/models.py b/FOSSDB_web/apps/fossdb/project/models.py deleted file mode 100644 index 37dd50e..0000000 --- a/FOSSDB_web/apps/fossdb/project/models.py +++ /dev/null @@ -1,33 +0,0 @@ -import uuid - -from django.conf import settings -from django.db import models - -from fossdb.hosting_platform.models import (HostingPlatform, - ProjectHostingPlatform) -from fossdb.license.models import License -from fossdb.programming_language.models import (ProgrammingLanguage, - ProjectProgrammingLanguage) -from fossdb.tag.models import Tag - -User = settings.AUTH_USER_MODEL - - -class Project(models.Model): - uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) - author = models.ForeignKey(User, on_delete=models.CASCADE) - name = models.CharField(max_length=255) - description = models.TextField(blank=True, default="") - licenses = models.ManyToManyField(License) - programming_languages = models.ManyToManyField(ProgrammingLanguage, through=ProjectProgrammingLanguage, related_name="projects") - hosting_platform = models.ManyToManyField(HostingPlatform, through=ProjectHostingPlatform, related_name="projects") - project_type = models.ForeignKey(Tag, on_delete=models.CASCADE, blank=True, null=True) - date_created = models.DateTimeField(auto_now_add=True) - - def save(self, *args, **kwargs): - if not self.uuid: - self.uuid = uuid.uuid5(uuid.NAMESPACE_URL, f"{self.author.username}-{self.name}") - super().save(*args, **kwargs) - - def __str__(self): - return f"{self.author} | {self.name}" diff --git a/FOSSDB_web/apps/fossdb/project/tests.py b/FOSSDB_web/apps/fossdb/project/tests.py deleted file mode 100644 index e69de29..0000000 diff --git a/FOSSDB_web/apps/fossdb/project/views.py b/FOSSDB_web/apps/fossdb/project/views.py deleted file mode 100644 index 11b33e6..0000000 --- a/FOSSDB_web/apps/fossdb/project/views.py +++ /dev/null @@ -1,45 +0,0 @@ - -from django.contrib.auth.decorators import login_required, permission_required -from django.shortcuts import redirect, render - -from .forms import (ProjectForm, ProjectHostingPlatformFormSet, - ProjectProgrammingLanguageFormSet) -from .models import Project - -# from fossdb.hosting_platform.forms import ProjectHostingPlatformFormSet -# from fossdb.programming_language.forms import ProjectProgrammingLanguageFormSet - - -@login_required(login_url="login/") -@permission_required("fossdb.add_post", login_url="login/", raise_exception=True) -def add_project(request): - if request.method == "POST": - project_form = ProjectForm(request.POST) - language_formset = ProjectProgrammingLanguageFormSet(request.POST, instance=Project()) - host_formset = ProjectHostingPlatformFormSet(request.POST, instance=Project()) - - if project_form.is_valid() and language_formset.is_valid() and host_formset.is_valid(): - project = project_form.save(commit=False) - project.author = request.user - project.save() - - language_formset.instance = project - language_formset.save() - - host_formset.instance = project - host_formset.save() - - project_form.save_m2m() - return redirect("/") - else: - project_form = ProjectForm() - language_formset = ProjectProgrammingLanguageFormSet() - host_formset = ProjectHostingPlatformFormSet() - - context = { - "title": "Add project", - "project_form": project_form, - "language_formset": language_formset, - "host_formset": host_formset, - } - return render(request, "fossdb/add_project.html", context) diff --git a/FOSSDB_web/apps/fossdb/tag/__init__.py b/FOSSDB_web/apps/fossdb/tag/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/FOSSDB_web/apps/fossdb/tag/admin.py b/FOSSDB_web/apps/fossdb/tag/admin.py deleted file mode 100644 index 1fdb041..0000000 --- a/FOSSDB_web/apps/fossdb/tag/admin.py +++ /dev/null @@ -1,5 +0,0 @@ -from django.contrib import admin - -from .models import Tag - -admin.site.register(Tag) diff --git a/FOSSDB_web/apps/fossdb/tag/apps.py b/FOSSDB_web/apps/fossdb/tag/apps.py deleted file mode 100644 index 5ce961f..0000000 --- a/FOSSDB_web/apps/fossdb/tag/apps.py +++ /dev/null @@ -1,6 +0,0 @@ -from django.apps import AppConfig - - -class TagConfig(AppConfig): - default_auto_field = "django.db.models.BigAutoField" - name = "fossdb.tag" diff --git a/FOSSDB_web/apps/fossdb/tag/migrations/__init__.py b/FOSSDB_web/apps/fossdb/tag/migrations/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/FOSSDB_web/apps/fossdb/tag/models.py b/FOSSDB_web/apps/fossdb/tag/models.py deleted file mode 100644 index 99ab5f3..0000000 --- a/FOSSDB_web/apps/fossdb/tag/models.py +++ /dev/null @@ -1,7 +0,0 @@ -from django.db import models - - -class Tag(models.Model): - name = models.CharField(max_length=100) - description = models.TextField(blank=True, default="") - icon = models.ImageField(upload_to="types/icons/", null=True, blank=True) diff --git a/FOSSDB_web/apps/fossdb/tag/tests.py b/FOSSDB_web/apps/fossdb/tag/tests.py deleted file mode 100644 index 7ce503c..0000000 --- a/FOSSDB_web/apps/fossdb/tag/tests.py +++ /dev/null @@ -1,3 +0,0 @@ -from django.test import TestCase - -# Create your tests here. diff --git a/FOSSDB_web/apps/fossdb/tag/views.py b/FOSSDB_web/apps/fossdb/tag/views.py deleted file mode 100644 index 91ea44a..0000000 --- a/FOSSDB_web/apps/fossdb/tag/views.py +++ /dev/null @@ -1,3 +0,0 @@ -from django.shortcuts import render - -# Create your views here. diff --git a/FOSSDB_web/apps/fossdb/views.py b/FOSSDB_web/apps/fossdb/views.py index 0759545..19b6d09 100644 --- a/FOSSDB_web/apps/fossdb/views.py +++ b/FOSSDB_web/apps/fossdb/views.py @@ -1,6 +1,9 @@ -from django.shortcuts import render +from django.contrib.auth.decorators import login_required, permission_required +from django.shortcuts import redirect, render -from fossdb.models import Project +from .forms import (ProjectForm, ProjectHostingPlatformFormSet, + ProjectProgrammingLanguageFormSet) +from .models import Project def index(request): @@ -9,3 +12,38 @@ def index(request): "projects": Project.objects.all(), } return render(request, "fossdb/index.html", context) + + +@login_required(login_url="login/") +@permission_required("fossdb.add_post", login_url="login/", raise_exception=True) +def add_project(request): + if request.method == "POST": + project_form = ProjectForm(request.POST) + language_formset = ProjectProgrammingLanguageFormSet(request.POST, instance=Project()) + host_formset = ProjectHostingPlatformFormSet(request.POST, instance=Project()) + + if project_form.is_valid() and language_formset.is_valid() and host_formset.is_valid(): + project = project_form.save(commit=False) + project.author = request.user + project.save() + + language_formset.instance = project + language_formset.save() + + host_formset.instance = project + host_formset.save() + + project_form.save_m2m() + return redirect("/") + else: + project_form = ProjectForm() + language_formset = ProjectProgrammingLanguageFormSet() + host_formset = ProjectHostingPlatformFormSet() + + context = { + "title": "Add project", + "project_form": project_form, + "language_formset": language_formset, + "host_formset": host_formset, + } + return render(request, "fossdb/add_project.html", context) diff --git a/FOSSDB_web/settings.py b/FOSSDB_web/settings.py index fa5090e..0c10737 100644 --- a/FOSSDB_web/settings.py +++ b/FOSSDB_web/settings.py @@ -38,11 +38,6 @@ ALLOWED_HOSTS = config["ALLOWED_HOSTS"] INSTALLED_APPS = [ "account", "fossdb", - "fossdb.project", - "fossdb.license", - "fossdb.programming_language", - "fossdb.hosting_platform", - "fossdb.tag", "django.contrib.admin", "django.contrib.auth", "django.contrib.contenttypes", From 743035a9b565d924e1dbdb79f2eb99d0c2eedd62 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Sun, 9 Apr 2023 12:48:20 +0300 Subject: [PATCH 064/144] Fix typos --- FOSSDB_web/apps/fossdb/models.py | 5 ++++- FOSSDB_web/apps/fossdb/views.py | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/FOSSDB_web/apps/fossdb/models.py b/FOSSDB_web/apps/fossdb/models.py index e1ae5ea..0d88e65 100644 --- a/FOSSDB_web/apps/fossdb/models.py +++ b/FOSSDB_web/apps/fossdb/models.py @@ -35,6 +35,9 @@ class Tag(models.Model): description = models.TextField(blank=True, default="") icon = models.ImageField(upload_to="types/icons/", null=True, blank=True) + def __str__(self): + return self.name + class ProjectProgrammingLanguage(models.Model): project = models.ForeignKey("Project", on_delete=models.CASCADE) @@ -62,7 +65,7 @@ class Project(models.Model): licenses = models.ManyToManyField(License) programming_languages = models.ManyToManyField(ProgrammingLanguage, through="ProjectProgrammingLanguage", related_name="projects") hosting_platform = models.ManyToManyField(HostingPlatform, through="ProjectHostingPlatform", related_name="projects") - project_type = models.ForeignKey(Tag, on_delete=models.CASCADE, blank=True, null=True) + tag = models.ManyToManyField(Tag) date_created = models.DateTimeField(auto_now_add=True) def save(self, *args, **kwargs): diff --git a/FOSSDB_web/apps/fossdb/views.py b/FOSSDB_web/apps/fossdb/views.py index 19b6d09..710ee59 100644 --- a/FOSSDB_web/apps/fossdb/views.py +++ b/FOSSDB_web/apps/fossdb/views.py @@ -15,7 +15,7 @@ def index(request): @login_required(login_url="login/") -@permission_required("fossdb.add_post", login_url="login/", raise_exception=True) +@permission_required("fossdb.add_project", login_url="login/", raise_exception=True) def add_project(request): if request.method == "POST": project_form = ProjectForm(request.POST) From fdf883352371543ed3f21e920d9f6fe606756653 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Sun, 9 Apr 2023 13:20:45 +0300 Subject: [PATCH 065/144] Moved License model to separate folder --- FOSSDB_web/apps/fossdb/admin.py | 3 ++- FOSSDB_web/apps/fossdb/forms.py | 6 ------ FOSSDB_web/apps/fossdb/license/forms.py | 9 +++++++++ FOSSDB_web/apps/fossdb/license/models.py | 11 +++++++++++ FOSSDB_web/apps/fossdb/migrations/0001_initial.py | 6 +++--- FOSSDB_web/apps/fossdb/models.py | 12 ++---------- 6 files changed, 27 insertions(+), 20 deletions(-) create mode 100644 FOSSDB_web/apps/fossdb/license/forms.py create mode 100644 FOSSDB_web/apps/fossdb/license/models.py diff --git a/FOSSDB_web/apps/fossdb/admin.py b/FOSSDB_web/apps/fossdb/admin.py index 21327ac..893dce9 100644 --- a/FOSSDB_web/apps/fossdb/admin.py +++ b/FOSSDB_web/apps/fossdb/admin.py @@ -1,6 +1,7 @@ from django.contrib import admin -from .models import (HostingPlatform, License, ProgrammingLanguage, Project, +from .license.models import License +from .models import (HostingPlatform, ProgrammingLanguage, Project, ProjectHostingPlatform, ProjectProgrammingLanguage, Tag) diff --git a/FOSSDB_web/apps/fossdb/forms.py b/FOSSDB_web/apps/fossdb/forms.py index 9da02f4..1eafc30 100644 --- a/FOSSDB_web/apps/fossdb/forms.py +++ b/FOSSDB_web/apps/fossdb/forms.py @@ -23,12 +23,6 @@ class ProjectForm(forms.ModelForm): } -class LicenseForm(forms.ModelForm): - class Meta: - model = License - fields = ["short_name", "full_name", "url", "description"] - - class ProgrammingLanguageForm(forms.ModelForm): percentage = forms.IntegerField(min_value=0, max_value=100) diff --git a/FOSSDB_web/apps/fossdb/license/forms.py b/FOSSDB_web/apps/fossdb/license/forms.py new file mode 100644 index 0000000..0c180da --- /dev/null +++ b/FOSSDB_web/apps/fossdb/license/forms.py @@ -0,0 +1,9 @@ +from django import forms + +from .models import License + + +class LicenseForm(forms.ModelForm): + class Meta: + model = License + fields = ["short_name", "full_name", "url", "description"] diff --git a/FOSSDB_web/apps/fossdb/license/models.py b/FOSSDB_web/apps/fossdb/license/models.py new file mode 100644 index 0000000..572a0b4 --- /dev/null +++ b/FOSSDB_web/apps/fossdb/license/models.py @@ -0,0 +1,11 @@ +from django.db import models + + +class License(models.Model): + short_name = models.CharField(max_length=50) + full_name = models.CharField(max_length=100, blank=True, default="") + url = models.URLField(blank=True, default="") + description = models.TextField(blank=True, default="") + + def __str__(self): + return self.short_name diff --git a/FOSSDB_web/apps/fossdb/migrations/0001_initial.py b/FOSSDB_web/apps/fossdb/migrations/0001_initial.py index 33d8a96..a142884 100644 --- a/FOSSDB_web/apps/fossdb/migrations/0001_initial.py +++ b/FOSSDB_web/apps/fossdb/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 4.1.7 on 2023-04-08 12:47 +# Generated by Django 4.1.7 on 2023-04-09 10:17 from django.conf import settings from django.db import migrations, models @@ -93,7 +93,7 @@ class Migration(migrations.Migration): ), migrations.AddField( model_name='project', - name='project_type', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='fossdb.tag'), + name='tag', + field=models.ManyToManyField(to='fossdb.tag'), ), ] diff --git a/FOSSDB_web/apps/fossdb/models.py b/FOSSDB_web/apps/fossdb/models.py index 0d88e65..3061570 100644 --- a/FOSSDB_web/apps/fossdb/models.py +++ b/FOSSDB_web/apps/fossdb/models.py @@ -3,19 +3,11 @@ import uuid from django.conf import settings from django.db import models +from .license.models import License + User = settings.AUTH_USER_MODEL -class License(models.Model): - short_name = models.CharField(max_length=50) - full_name = models.CharField(max_length=100, blank=True, default="") - url = models.URLField(blank=True, default="") - description = models.TextField(blank=True, default="") - - def __str__(self): - return self.short_name - - class HostingPlatform(models.Model): hosting_platform = models.CharField(max_length=100) From e0f2e615f3aa4537cad0d597960d0a654d7bd9c7 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Sun, 9 Apr 2023 13:24:51 +0300 Subject: [PATCH 066/144] Moved ProgrammingLanguage to separate folder --- FOSSDB_web/apps/fossdb/admin.py | 4 ++-- FOSSDB_web/apps/fossdb/forms.py | 20 +------------------- FOSSDB_web/apps/fossdb/language/forms.py | 22 ++++++++++++++++++++++ FOSSDB_web/apps/fossdb/language/models.py | 17 +++++++++++++++++ FOSSDB_web/apps/fossdb/models.py | 17 +---------------- FOSSDB_web/apps/fossdb/views.py | 4 ++-- 6 files changed, 45 insertions(+), 39 deletions(-) create mode 100644 FOSSDB_web/apps/fossdb/language/forms.py create mode 100644 FOSSDB_web/apps/fossdb/language/models.py diff --git a/FOSSDB_web/apps/fossdb/admin.py b/FOSSDB_web/apps/fossdb/admin.py index 893dce9..18dbec5 100644 --- a/FOSSDB_web/apps/fossdb/admin.py +++ b/FOSSDB_web/apps/fossdb/admin.py @@ -1,8 +1,8 @@ from django.contrib import admin +from .language.models import ProgrammingLanguage, ProjectProgrammingLanguage from .license.models import License -from .models import (HostingPlatform, ProgrammingLanguage, Project, - ProjectHostingPlatform, ProjectProgrammingLanguage, Tag) +from .models import HostingPlatform, Project, ProjectHostingPlatform, Tag class ProjectProgrammingLanguageInline(admin.TabularInline): diff --git a/FOSSDB_web/apps/fossdb/forms.py b/FOSSDB_web/apps/fossdb/forms.py index 1eafc30..1dde296 100644 --- a/FOSSDB_web/apps/fossdb/forms.py +++ b/FOSSDB_web/apps/fossdb/forms.py @@ -1,7 +1,6 @@ from django import forms -from .models import (HostingPlatform, License, ProgrammingLanguage, Project, - ProjectHostingPlatform, ProjectProgrammingLanguage) +from .models import HostingPlatform, Project, ProjectHostingPlatform class ProjectForm(forms.ModelForm): @@ -23,23 +22,6 @@ class ProjectForm(forms.ModelForm): } -class ProgrammingLanguageForm(forms.ModelForm): - percentage = forms.IntegerField(min_value=0, max_value=100) - - class Meta: - model = ProgrammingLanguage - fields = ["language", "percentage"] - - -ProjectProgrammingLanguageFormSet = forms.inlineformset_factory( - Project, - ProjectProgrammingLanguage, - form=ProgrammingLanguageForm, - extra=1, - can_delete=True, -) - - class HostingPlatformForm(forms.ModelForm): url = forms.URLField() diff --git a/FOSSDB_web/apps/fossdb/language/forms.py b/FOSSDB_web/apps/fossdb/language/forms.py new file mode 100644 index 0000000..a7cadf3 --- /dev/null +++ b/FOSSDB_web/apps/fossdb/language/forms.py @@ -0,0 +1,22 @@ +from django import forms + +from fossdb.models import Project + +from .models import ProgrammingLanguage, ProjectProgrammingLanguage + + +class ProgrammingLanguageForm(forms.ModelForm): + percentage = forms.IntegerField(min_value=0, max_value=100) + + class Meta: + model = ProgrammingLanguage + fields = ["language", "percentage"] + + +ProjectProgrammingLanguageFormSet = forms.inlineformset_factory( + Project, + ProjectProgrammingLanguage, + form=ProgrammingLanguageForm, + extra=1, + can_delete=True, +) diff --git a/FOSSDB_web/apps/fossdb/language/models.py b/FOSSDB_web/apps/fossdb/language/models.py new file mode 100644 index 0000000..9a624f1 --- /dev/null +++ b/FOSSDB_web/apps/fossdb/language/models.py @@ -0,0 +1,17 @@ +from django.db import models + + +class ProgrammingLanguage(models.Model): + language = models.CharField(max_length=100) + + def __str__(self): + return self.language + + +class ProjectProgrammingLanguage(models.Model): + project = models.ForeignKey("Project", on_delete=models.CASCADE) + language = models.ForeignKey(ProgrammingLanguage, on_delete=models.CASCADE) + percentage = models.PositiveIntegerField() + + def __str__(self): + return f"{self.project} | {self.language} | {self.percentage}%" diff --git a/FOSSDB_web/apps/fossdb/models.py b/FOSSDB_web/apps/fossdb/models.py index 3061570..ff3703a 100644 --- a/FOSSDB_web/apps/fossdb/models.py +++ b/FOSSDB_web/apps/fossdb/models.py @@ -3,6 +3,7 @@ import uuid from django.conf import settings from django.db import models +from .language.models import ProgrammingLanguage from .license.models import License User = settings.AUTH_USER_MODEL @@ -15,13 +16,6 @@ class HostingPlatform(models.Model): return self.hosting_platform -class ProgrammingLanguage(models.Model): - language = models.CharField(max_length=100) - - def __str__(self): - return self.language - - class Tag(models.Model): name = models.CharField(max_length=100) description = models.TextField(blank=True, default="") @@ -31,15 +25,6 @@ class Tag(models.Model): return self.name -class ProjectProgrammingLanguage(models.Model): - project = models.ForeignKey("Project", on_delete=models.CASCADE) - language = models.ForeignKey(ProgrammingLanguage, on_delete=models.CASCADE) - percentage = models.PositiveIntegerField() - - def __str__(self): - return f"{self.project} | {self.language} | {self.percentage}%" - - class ProjectHostingPlatform(models.Model): project = models.ForeignKey("Project", on_delete=models.CASCADE) hosting_platform = models.ForeignKey(HostingPlatform, on_delete=models.CASCADE) diff --git a/FOSSDB_web/apps/fossdb/views.py b/FOSSDB_web/apps/fossdb/views.py index 710ee59..3249af3 100644 --- a/FOSSDB_web/apps/fossdb/views.py +++ b/FOSSDB_web/apps/fossdb/views.py @@ -1,8 +1,8 @@ from django.contrib.auth.decorators import login_required, permission_required from django.shortcuts import redirect, render -from .forms import (ProjectForm, ProjectHostingPlatformFormSet, - ProjectProgrammingLanguageFormSet) +from .forms import ProjectForm, ProjectHostingPlatformFormSet +from .language.forms import ProjectProgrammingLanguageFormSet from .models import Project From 0b0d6539dc7a6c07b9643d4d25b81bc3bed0e859 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Sun, 9 Apr 2023 13:30:01 +0300 Subject: [PATCH 067/144] Moved HostingPlatform to separate folder --- FOSSDB_web/apps/fossdb/admin.py | 3 ++- FOSSDB_web/apps/fossdb/forms.py | 19 +------------------ FOSSDB_web/apps/fossdb/host/forms.py | 22 ++++++++++++++++++++++ FOSSDB_web/apps/fossdb/host/models.py | 17 +++++++++++++++++ FOSSDB_web/apps/fossdb/models.py | 25 +++---------------------- FOSSDB_web/apps/fossdb/views.py | 3 ++- 6 files changed, 47 insertions(+), 42 deletions(-) create mode 100644 FOSSDB_web/apps/fossdb/host/forms.py create mode 100644 FOSSDB_web/apps/fossdb/host/models.py diff --git a/FOSSDB_web/apps/fossdb/admin.py b/FOSSDB_web/apps/fossdb/admin.py index 18dbec5..6a9f524 100644 --- a/FOSSDB_web/apps/fossdb/admin.py +++ b/FOSSDB_web/apps/fossdb/admin.py @@ -1,8 +1,9 @@ from django.contrib import admin +from .host.models import HostingPlatform, ProjectHostingPlatform from .language.models import ProgrammingLanguage, ProjectProgrammingLanguage from .license.models import License -from .models import HostingPlatform, Project, ProjectHostingPlatform, Tag +from .models import Project, Tag class ProjectProgrammingLanguageInline(admin.TabularInline): diff --git a/FOSSDB_web/apps/fossdb/forms.py b/FOSSDB_web/apps/fossdb/forms.py index 1dde296..b1f60e2 100644 --- a/FOSSDB_web/apps/fossdb/forms.py +++ b/FOSSDB_web/apps/fossdb/forms.py @@ -1,6 +1,6 @@ from django import forms -from .models import HostingPlatform, Project, ProjectHostingPlatform +from .models import Project class ProjectForm(forms.ModelForm): @@ -20,20 +20,3 @@ class ProjectForm(forms.ModelForm): }), "licenses": forms.CheckboxSelectMultiple(), } - - -class HostingPlatformForm(forms.ModelForm): - url = forms.URLField() - - class Meta: - model = HostingPlatform - fields = ["hosting_platform", "url"] - - -ProjectHostingPlatformFormSet = forms.inlineformset_factory( - Project, - ProjectHostingPlatform, - form=HostingPlatformForm, - extra=1, - can_delete=False -) diff --git a/FOSSDB_web/apps/fossdb/host/forms.py b/FOSSDB_web/apps/fossdb/host/forms.py new file mode 100644 index 0000000..5c04a50 --- /dev/null +++ b/FOSSDB_web/apps/fossdb/host/forms.py @@ -0,0 +1,22 @@ +from django import forms + +from fossdb.models import Project + +from .models import HostingPlatform, ProjectHostingPlatform + + +class HostingPlatformForm(forms.ModelForm): + url = forms.URLField() + + class Meta: + model = HostingPlatform + fields = ["hosting_platform", "url"] + + +ProjectHostingPlatformFormSet = forms.inlineformset_factory( + Project, + ProjectHostingPlatform, + form=HostingPlatformForm, + extra=1, + can_delete=False +) diff --git a/FOSSDB_web/apps/fossdb/host/models.py b/FOSSDB_web/apps/fossdb/host/models.py new file mode 100644 index 0000000..c401aa0 --- /dev/null +++ b/FOSSDB_web/apps/fossdb/host/models.py @@ -0,0 +1,17 @@ +from django.db import models + + +class HostingPlatform(models.Model): + hosting_platform = models.CharField(max_length=100) + + def __str__(self): + return self.hosting_platform + + +class ProjectHostingPlatform(models.Model): + project = models.ForeignKey("Project", on_delete=models.CASCADE) + hosting_platform = models.ForeignKey(HostingPlatform, on_delete=models.CASCADE) + url = models.URLField() + + def __str__(self): + return f"{self.project} | {self.hosting_platform}" diff --git a/FOSSDB_web/apps/fossdb/models.py b/FOSSDB_web/apps/fossdb/models.py index ff3703a..3ce4c4d 100644 --- a/FOSSDB_web/apps/fossdb/models.py +++ b/FOSSDB_web/apps/fossdb/models.py @@ -3,19 +3,9 @@ import uuid from django.conf import settings from django.db import models -from .language.models import ProgrammingLanguage -from .license.models import License - User = settings.AUTH_USER_MODEL -class HostingPlatform(models.Model): - hosting_platform = models.CharField(max_length=100) - - def __str__(self): - return self.hosting_platform - - class Tag(models.Model): name = models.CharField(max_length=100) description = models.TextField(blank=True, default="") @@ -25,23 +15,14 @@ class Tag(models.Model): return self.name -class ProjectHostingPlatform(models.Model): - project = models.ForeignKey("Project", on_delete=models.CASCADE) - hosting_platform = models.ForeignKey(HostingPlatform, on_delete=models.CASCADE) - url = models.URLField() - - def __str__(self): - return f"{self.project} | {self.hosting_platform}" - - class Project(models.Model): uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) author = models.ForeignKey(User, on_delete=models.CASCADE) name = models.CharField(max_length=255) description = models.TextField(blank=True, default="") - licenses = models.ManyToManyField(License) - programming_languages = models.ManyToManyField(ProgrammingLanguage, through="ProjectProgrammingLanguage", related_name="projects") - hosting_platform = models.ManyToManyField(HostingPlatform, through="ProjectHostingPlatform", related_name="projects") + licenses = models.ManyToManyField("License") + programming_languages = models.ManyToManyField("ProgrammingLanguage", through="ProjectProgrammingLanguage", related_name="projects") + hosting_platform = models.ManyToManyField("HostingPlatform", through="ProjectHostingPlatform", related_name="projects") tag = models.ManyToManyField(Tag) date_created = models.DateTimeField(auto_now_add=True) diff --git a/FOSSDB_web/apps/fossdb/views.py b/FOSSDB_web/apps/fossdb/views.py index 3249af3..4d76938 100644 --- a/FOSSDB_web/apps/fossdb/views.py +++ b/FOSSDB_web/apps/fossdb/views.py @@ -1,7 +1,8 @@ from django.contrib.auth.decorators import login_required, permission_required from django.shortcuts import redirect, render -from .forms import ProjectForm, ProjectHostingPlatformFormSet +from .forms import ProjectForm +from .host.forms import ProjectHostingPlatformFormSet from .language.forms import ProjectProgrammingLanguageFormSet from .models import Project From a4359a4dc1fb65cce0422fb14ff8ab38db2726a4 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Sun, 9 Apr 2023 13:31:43 +0300 Subject: [PATCH 068/144] Moved Tag to separate folder --- FOSSDB_web/apps/fossdb/admin.py | 3 ++- FOSSDB_web/apps/fossdb/models.py | 11 +---------- FOSSDB_web/apps/fossdb/tag/models.py | 11 +++++++++++ 3 files changed, 14 insertions(+), 11 deletions(-) create mode 100644 FOSSDB_web/apps/fossdb/tag/models.py diff --git a/FOSSDB_web/apps/fossdb/admin.py b/FOSSDB_web/apps/fossdb/admin.py index 6a9f524..ea74c31 100644 --- a/FOSSDB_web/apps/fossdb/admin.py +++ b/FOSSDB_web/apps/fossdb/admin.py @@ -3,7 +3,8 @@ from django.contrib import admin from .host.models import HostingPlatform, ProjectHostingPlatform from .language.models import ProgrammingLanguage, ProjectProgrammingLanguage from .license.models import License -from .models import Project, Tag +from .models import Project +from .tag.models import Tag class ProjectProgrammingLanguageInline(admin.TabularInline): diff --git a/FOSSDB_web/apps/fossdb/models.py b/FOSSDB_web/apps/fossdb/models.py index 3ce4c4d..5fa0cf2 100644 --- a/FOSSDB_web/apps/fossdb/models.py +++ b/FOSSDB_web/apps/fossdb/models.py @@ -6,15 +6,6 @@ from django.db import models User = settings.AUTH_USER_MODEL -class Tag(models.Model): - name = models.CharField(max_length=100) - description = models.TextField(blank=True, default="") - icon = models.ImageField(upload_to="types/icons/", null=True, blank=True) - - def __str__(self): - return self.name - - class Project(models.Model): uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) author = models.ForeignKey(User, on_delete=models.CASCADE) @@ -23,7 +14,7 @@ class Project(models.Model): licenses = models.ManyToManyField("License") programming_languages = models.ManyToManyField("ProgrammingLanguage", through="ProjectProgrammingLanguage", related_name="projects") hosting_platform = models.ManyToManyField("HostingPlatform", through="ProjectHostingPlatform", related_name="projects") - tag = models.ManyToManyField(Tag) + tag = models.ManyToManyField("Tag") date_created = models.DateTimeField(auto_now_add=True) def save(self, *args, **kwargs): diff --git a/FOSSDB_web/apps/fossdb/tag/models.py b/FOSSDB_web/apps/fossdb/tag/models.py new file mode 100644 index 0000000..10bb71e --- /dev/null +++ b/FOSSDB_web/apps/fossdb/tag/models.py @@ -0,0 +1,11 @@ + +from django.db import models + + +class Tag(models.Model): + name = models.CharField(max_length=100) + description = models.TextField(blank=True, default="") + icon = models.ImageField(upload_to="types/icons/", null=True, blank=True) + + def __str__(self): + return self.name From e74853d89f4900a6b7f2f4fd1c62694e5ba6c3c8 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Sun, 9 Apr 2023 13:36:41 +0300 Subject: [PATCH 069/144] Created OS model --- .../0002_operatingsystem_project_os.py | 27 +++++++++++++++++++ FOSSDB_web/apps/fossdb/models.py | 15 ++++++++--- .../apps/fossdb/operating_system/models.py | 7 +++++ 3 files changed, 45 insertions(+), 4 deletions(-) create mode 100644 FOSSDB_web/apps/fossdb/migrations/0002_operatingsystem_project_os.py create mode 100644 FOSSDB_web/apps/fossdb/operating_system/models.py diff --git a/FOSSDB_web/apps/fossdb/migrations/0002_operatingsystem_project_os.py b/FOSSDB_web/apps/fossdb/migrations/0002_operatingsystem_project_os.py new file mode 100644 index 0000000..9741c32 --- /dev/null +++ b/FOSSDB_web/apps/fossdb/migrations/0002_operatingsystem_project_os.py @@ -0,0 +1,27 @@ +# Generated by Django 4.1.7 on 2023-04-09 10:35 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('fossdb', '0001_initial'), + ] + + operations = [ + migrations.CreateModel( + name='OperatingSystem', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=100)), + ('description', models.TextField(blank=True, default='')), + ('version', models.CharField(blank=True, max_length=50)), + ], + ), + migrations.AddField( + model_name='project', + name='os', + field=models.ManyToManyField(to='fossdb.operatingsystem'), + ), + ] diff --git a/FOSSDB_web/apps/fossdb/models.py b/FOSSDB_web/apps/fossdb/models.py index 5fa0cf2..59297ad 100644 --- a/FOSSDB_web/apps/fossdb/models.py +++ b/FOSSDB_web/apps/fossdb/models.py @@ -3,6 +3,12 @@ import uuid from django.conf import settings from django.db import models +from .host.models import HostingPlatform +from .language.models import ProgrammingLanguage +from .license.models import License +from .operating_system.models import OperatingSystem +from .tag.models import Tag + User = settings.AUTH_USER_MODEL @@ -11,10 +17,11 @@ class Project(models.Model): author = models.ForeignKey(User, on_delete=models.CASCADE) name = models.CharField(max_length=255) description = models.TextField(blank=True, default="") - licenses = models.ManyToManyField("License") - programming_languages = models.ManyToManyField("ProgrammingLanguage", through="ProjectProgrammingLanguage", related_name="projects") - hosting_platform = models.ManyToManyField("HostingPlatform", through="ProjectHostingPlatform", related_name="projects") - tag = models.ManyToManyField("Tag") + licenses = models.ManyToManyField(License) + programming_languages = models.ManyToManyField(ProgrammingLanguage, through="ProjectProgrammingLanguage", related_name="projects") + hosting_platform = models.ManyToManyField(HostingPlatform, through="ProjectHostingPlatform", related_name="projects") + tag = models.ManyToManyField(Tag) + os = models.ManyToManyField(OperatingSystem) date_created = models.DateTimeField(auto_now_add=True) def save(self, *args, **kwargs): diff --git a/FOSSDB_web/apps/fossdb/operating_system/models.py b/FOSSDB_web/apps/fossdb/operating_system/models.py new file mode 100644 index 0000000..d638ec8 --- /dev/null +++ b/FOSSDB_web/apps/fossdb/operating_system/models.py @@ -0,0 +1,7 @@ +from django.db import models + + +class OperatingSystem(models.Model): + name = models.CharField(max_length=100) + description = models.TextField(blank=True, default="") + version = models.CharField(max_length=50, blank=True) From 60f252321bad3ee729cbfdf30caa6449f4b0d2f5 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Sun, 9 Apr 2023 14:06:15 +0300 Subject: [PATCH 070/144] Created Star model --- .../migrations/0003_star_project_star.py | 29 +++++++++++++++++++ FOSSDB_web/apps/fossdb/models.py | 19 ++++++++---- FOSSDB_web/apps/fossdb/star/models.py | 9 ++++++ 3 files changed, 52 insertions(+), 5 deletions(-) create mode 100644 FOSSDB_web/apps/fossdb/migrations/0003_star_project_star.py create mode 100644 FOSSDB_web/apps/fossdb/star/models.py diff --git a/FOSSDB_web/apps/fossdb/migrations/0003_star_project_star.py b/FOSSDB_web/apps/fossdb/migrations/0003_star_project_star.py new file mode 100644 index 0000000..2baf97f --- /dev/null +++ b/FOSSDB_web/apps/fossdb/migrations/0003_star_project_star.py @@ -0,0 +1,29 @@ +# Generated by Django 4.1.7 on 2023-04-09 10:51 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('fossdb', '0002_operatingsystem_project_os'), + ] + + operations = [ + migrations.CreateModel( + name='Star', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('project', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='stars', to='fossdb.project')), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ], + ), + migrations.AddField( + model_name='project', + name='star', + field=models.ManyToManyField(related_name='projects_star', to='fossdb.star'), + ), + ] diff --git a/FOSSDB_web/apps/fossdb/models.py b/FOSSDB_web/apps/fossdb/models.py index 59297ad..53d1bd0 100644 --- a/FOSSDB_web/apps/fossdb/models.py +++ b/FOSSDB_web/apps/fossdb/models.py @@ -7,6 +7,7 @@ from .host.models import HostingPlatform from .language.models import ProgrammingLanguage from .license.models import License from .operating_system.models import OperatingSystem +from .star.models import Star from .tag.models import Tag User = settings.AUTH_USER_MODEL @@ -14,7 +15,7 @@ User = settings.AUTH_USER_MODEL class Project(models.Model): uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) - author = models.ForeignKey(User, on_delete=models.CASCADE) + author = models.ForeignKey(User, on_delete=models.CASCADE, db_index=True) name = models.CharField(max_length=255) description = models.TextField(blank=True, default="") licenses = models.ManyToManyField(License) @@ -22,12 +23,20 @@ class Project(models.Model): hosting_platform = models.ManyToManyField(HostingPlatform, through="ProjectHostingPlatform", related_name="projects") tag = models.ManyToManyField(Tag) os = models.ManyToManyField(OperatingSystem) + star = models.ManyToManyField(Star, related_name="projects_star") date_created = models.DateTimeField(auto_now_add=True) - def save(self, *args, **kwargs): - if not self.uuid: - self.uuid = uuid.uuid5(uuid.NAMESPACE_URL, f"{self.author.username}-{self.name}") - super().save(*args, **kwargs) + @property + def star_amount(self): + return self.star.count() + + def get_absolute_url(self): + return f"/{self.author.name}/{self.name}" def __str__(self): return f"{self.author} | {self.name}" + + def save(self, *args, **kwargs): + if not self.uuid: + self.uuid = uuid.uuid3(uuid.uuid4(), f"{self.author.username}-{self.name}") + super().save(*args, **kwargs) diff --git a/FOSSDB_web/apps/fossdb/star/models.py b/FOSSDB_web/apps/fossdb/star/models.py new file mode 100644 index 0000000..74f0452 --- /dev/null +++ b/FOSSDB_web/apps/fossdb/star/models.py @@ -0,0 +1,9 @@ +from django.conf import settings +from django.db import models + +User = settings.AUTH_USER_MODEL + + +class Star(models.Model): + user = models.ForeignKey(User, on_delete=models.CASCADE) + project = models.ForeignKey("Project", on_delete=models.CASCADE, related_name="stars") From c54089238bdc0b76c91f530fc974e3307f22239f Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Sun, 9 Apr 2023 19:34:19 +0300 Subject: [PATCH 071/144] Added Pillow dependency --- requirements.txt | 1 + setup.cfg | 1 + 2 files changed, 2 insertions(+) diff --git a/requirements.txt b/requirements.txt index 4e4add1..c689f93 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ Django==4.1.7 +Pillow==9.4.0 fontawesomefree==6.2.1 mysqlclient==2.1.1 diff --git a/setup.cfg b/setup.cfg index 069d76d..3ef6ae0 100644 --- a/setup.cfg +++ b/setup.cfg @@ -12,6 +12,7 @@ classifiers = packages = FOSSDB_web install_requires = Django>=4.1 + Pillow>=9.4.0 fontawesomefree>=6.2.1 mysqlclient>=2.1.1 From 64d9b9c8470f5d8b83464b12bb4d4cfa21d63c7d Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Sun, 9 Apr 2023 19:40:09 +0300 Subject: [PATCH 072/144] Fix typo --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 25fa3fb..8290f4e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -19,5 +19,5 @@ jobs: run: | python -m pip install --upgrade pip pip install tox tox-gh-actions - - name: Lint with tox + - name: Test with tox run: tox From cf6286d4dd97f0c4071c66d9fe75b5b6e5821f51 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Sun, 9 Apr 2023 19:45:56 +0300 Subject: [PATCH 073/144] Update `config.json` --- config.json | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/config.json b/config.json index dcaea64..2871971 100644 --- a/config.json +++ b/config.json @@ -1,10 +1,8 @@ { "SECRET_KEY": "", - "ALLOWED_HOSTS": [ - "", - "localhost" - ], + "ALLOWED_HOSTS": [""], "DATABASE": { + "ENGINE": "", "NAME": "", "USER": "", "PASSWORD": "", From 19d13a042745efa9207dd1d66b880fa90210a9b2 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Sun, 9 Apr 2023 19:49:26 +0300 Subject: [PATCH 074/144] Changed test os --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 8290f4e..549aa1a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -7,7 +7,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - os: [ubuntu-latest, windows-latest] + os: [debian-latest] python-version: ["3.10"] steps: - uses: actions/checkout@v2 From 3593aab01bc946985de9db21f64c9c551bec036a Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Sun, 9 Apr 2023 19:54:17 +0300 Subject: [PATCH 075/144] Removes windows from automatic testing --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 549aa1a..b1a1554 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -7,7 +7,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - os: [debian-latest] + os: [ubuntu-latest] python-version: ["3.10"] steps: - uses: actions/checkout@v2 From 4635bffc9f96285b074072a83b0cb86522e53456 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Mon, 10 Apr 2023 14:02:42 +0300 Subject: [PATCH 076/144] Fix tests --- FOSSDB_web/apps/fossdb/admin.py | 2 +- setup.cfg | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/FOSSDB_web/apps/fossdb/admin.py b/FOSSDB_web/apps/fossdb/admin.py index ea74c31..4730425 100644 --- a/FOSSDB_web/apps/fossdb/admin.py +++ b/FOSSDB_web/apps/fossdb/admin.py @@ -1,4 +1,4 @@ -from django.contrib import admin +# from django.contrib import admin from .host.models import HostingPlatform, ProjectHostingPlatform from .language.models import ProgrammingLanguage, ProjectProgrammingLanguage diff --git a/setup.cfg b/setup.cfg index 3ef6ae0..11cce81 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = FOSSDB-Web -description = Open-Source Software Database Website +description = Free and Open-Source Software Database Website author = Kristofers Solo license = GPL3 license_files = LICENSE From f9246064efc7ea75629b09ed9c060a65386c1aa4 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Mon, 10 Apr 2023 13:50:52 +0300 Subject: [PATCH 077/144] Created `README.md` file --- README.md | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..208f8d4 --- /dev/null +++ b/README.md @@ -0,0 +1,51 @@ +# FOSSDB + +[![License](https://img.shields.io/badge/license-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0.en.html) +![Tests](https://github.com/kristoferssolo/FOSSDB-Web/actions/workflows/test.yml/badge.svg) + + +FOSSDB is an open-source web application that helps users find, contribute, and collaborate on free and open-source software (FOSS) projects. + +## Table of Contents +- [Installation](#installation) +- [Usage](#usage) +- [Contributing](#contributing) +- [License](#license) + +## Installation +1. Clone the repository and `cd` into it. +2. Install dependencies: +```sh +pip install -r requirements.txt +``` +3. Enter your `SECRET_KEY` and database information into `config.json` file. +4. Run database migrations: +```sh +python manage.py migrate +``` +5. Create a superuser: +```sh +python manage.py createsuperuser +``` +6. Run the development server: +```sh +python manage.py runserver +``` + +## Usage +After following the installation steps, you can access the application at [https://localhost:8000](https://localhost:8000). +Here are some of the features: +- Browse projects by programming language, license, or search term +- View project details, including programming languages, licenses, and descriptions +- Create a new project and add programming languages and licenses +- Edit and delete existing projects + +## Contributing +Contributions are always welcome! Here are some ways to get started: +1. Fork the repository and make your changes. +2. Submit a pull request. +3. Respond to open issues or submit new ones. +4. Improve documentation. + +## License +This project is licensed under the [GPL3 License](https://www.gnu.org/licenses/gpl-3.0.en.html). See the [LICENSE](./LICENSE) file for details. From f10fe979cecf8c779e73cc05397a75bea086babd Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Wed, 12 Apr 2023 10:35:48 +0300 Subject: [PATCH 078/144] Separated lint and test to 2 files --- .github/workflows/lint.yml | 25 +++++++++++++++++++++++++ .github/workflows/test.yml | 4 ++-- 2 files changed, 27 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/lint.yml diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 0000000..41df0de --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,25 @@ +name: Lint +on: + - push + - pull_request +jobs: + lint: + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-latest] + python-version: ["3.10"] + steps: + - uses: actions/checkout@v2 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install -r requirements_dev.txt + - name: Lint with mypy + run: mypy FOSSDB_web + - name: Lint with flake8 + run: flake8 FOSSDB_web diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b1a1554..365ee12 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -18,6 +18,6 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install tox tox-gh-actions + pip install -r requirements.txt - name: Test with tox - run: tox + run: python manage.py test From 623c5e22aed5c1c552b08d52345f234539479c03 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Wed, 12 Apr 2023 10:45:21 +0300 Subject: [PATCH 079/144] Fix tests --- .github/workflows/lint.yml | 4 ++-- .github/workflows/test.yml | 4 ++-- FOSSDB_web/apps/fossdb/admin.py | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 41df0de..521effb 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -3,7 +3,7 @@ on: - push - pull_request jobs: - lint: + test: runs-on: ${{ matrix.os }} strategy: matrix: @@ -18,7 +18,7 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install -r requirements_dev.txt + pip install mypy flake8 - name: Lint with mypy run: mypy FOSSDB_web - name: Lint with flake8 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 365ee12..a410855 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -18,6 +18,6 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install -r requirements.txt - - name: Test with tox + pip install django + - name: Test with django test run: python manage.py test diff --git a/FOSSDB_web/apps/fossdb/admin.py b/FOSSDB_web/apps/fossdb/admin.py index 4730425..ea74c31 100644 --- a/FOSSDB_web/apps/fossdb/admin.py +++ b/FOSSDB_web/apps/fossdb/admin.py @@ -1,4 +1,4 @@ -# from django.contrib import admin +from django.contrib import admin from .host.models import HostingPlatform, ProjectHostingPlatform from .language.models import ProgrammingLanguage, ProjectProgrammingLanguage From 4509ee531328e3fc13156cd9c7e4278b53b696ab Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Wed, 12 Apr 2023 10:46:57 +0300 Subject: [PATCH 080/144] Install requirements for tests --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a410855..88ecea3 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -18,6 +18,6 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install django + pip install -r requirements.txt - name: Test with django test run: python manage.py test From 8439fa56bc14aecf23a6e8ee09859b1a1e79af86 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Wed, 12 Apr 2023 10:47:54 +0300 Subject: [PATCH 081/144] Added lint to README --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 208f8d4..3772914 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,8 @@ # FOSSDB -[![License](https://img.shields.io/badge/license-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0.en.html) -![Tests](https://github.com/kristoferssolo/FOSSDB-Web/actions/workflows/test.yml/badge.svg) +[![License](https://img.shields.io/badge/license-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0.en.html) +![Tests](https://github.com/kristoferssolo/FOSSDB-Web/actions/workflows/test.yml/badge.svg) +![Lint](https://github.com/kristoferssolo/FOSSDB-Web/actions/workflows/lint.yml/badge.svg) FOSSDB is an open-source web application that helps users find, contribute, and collaborate on free and open-source software (FOSS) projects. From 4dcf8709a2480c782541a19dff3c53889772cec6 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Sat, 22 Apr 2023 13:47:59 +0300 Subject: [PATCH 082/144] Renamed project to `FOSSDB` --- {FOSSDB_web => FOSSDB}/__init__.py | 0 {FOSSDB_web => FOSSDB}/apps/account/__init__.py | 0 {FOSSDB_web => FOSSDB}/apps/account/admin.py | 0 {FOSSDB_web => FOSSDB}/apps/account/apps.py | 0 {FOSSDB_web => FOSSDB}/apps/account/forms.py | 0 {FOSSDB_web => FOSSDB}/apps/account/tests.py | 0 {FOSSDB_web => FOSSDB}/apps/account/urls.py | 0 {FOSSDB_web => FOSSDB}/apps/account/views.py | 0 {FOSSDB_web => FOSSDB}/apps/fossdb/__init__.py | 0 {FOSSDB_web => FOSSDB}/apps/fossdb/admin.py | 0 {FOSSDB_web => FOSSDB}/apps/fossdb/apps.py | 0 {FOSSDB_web => FOSSDB}/apps/fossdb/forms.py | 0 {FOSSDB_web => FOSSDB}/apps/fossdb/host/forms.py | 0 {FOSSDB_web => FOSSDB}/apps/fossdb/host/models.py | 0 {FOSSDB_web => FOSSDB}/apps/fossdb/language/forms.py | 0 {FOSSDB_web => FOSSDB}/apps/fossdb/language/models.py | 0 {FOSSDB_web => FOSSDB}/apps/fossdb/license/forms.py | 0 {FOSSDB_web => FOSSDB}/apps/fossdb/license/models.py | 0 .../apps/fossdb/migrations/0001_initial.py | 0 .../fossdb/migrations/0002_operatingsystem_project_os.py | 0 .../apps/fossdb/migrations/0003_star_project_star.py | 0 {FOSSDB_web => FOSSDB}/apps/fossdb/migrations/__init__.py | 0 {FOSSDB_web => FOSSDB}/apps/fossdb/models.py | 0 .../apps/fossdb/operating_system/models.py | 0 {FOSSDB_web => FOSSDB}/apps/fossdb/star/models.py | 0 {FOSSDB_web => FOSSDB}/apps/fossdb/tag/models.py | 0 {FOSSDB_web => FOSSDB}/apps/fossdb/tests.py | 0 {FOSSDB_web => FOSSDB}/apps/fossdb/urls.py | 0 {FOSSDB_web => FOSSDB}/apps/fossdb/views.py | 0 {FOSSDB_web => FOSSDB}/asgi.py | 4 ++-- {FOSSDB_web => FOSSDB}/settings.py | 8 ++++---- {FOSSDB_web => FOSSDB}/urls.py | 2 +- {FOSSDB_web => FOSSDB}/wsgi.py | 4 ++-- README.md | 4 ++-- manage.py | 2 +- pyproject.toml | 2 +- setup.cfg | 4 ++-- tox.ini | 4 ++-- 38 files changed, 17 insertions(+), 17 deletions(-) rename {FOSSDB_web => FOSSDB}/__init__.py (100%) rename {FOSSDB_web => FOSSDB}/apps/account/__init__.py (100%) rename {FOSSDB_web => FOSSDB}/apps/account/admin.py (100%) rename {FOSSDB_web => FOSSDB}/apps/account/apps.py (100%) rename {FOSSDB_web => FOSSDB}/apps/account/forms.py (100%) rename {FOSSDB_web => FOSSDB}/apps/account/tests.py (100%) rename {FOSSDB_web => FOSSDB}/apps/account/urls.py (100%) rename {FOSSDB_web => FOSSDB}/apps/account/views.py (100%) rename {FOSSDB_web => FOSSDB}/apps/fossdb/__init__.py (100%) rename {FOSSDB_web => FOSSDB}/apps/fossdb/admin.py (100%) rename {FOSSDB_web => FOSSDB}/apps/fossdb/apps.py (100%) rename {FOSSDB_web => FOSSDB}/apps/fossdb/forms.py (100%) rename {FOSSDB_web => FOSSDB}/apps/fossdb/host/forms.py (100%) rename {FOSSDB_web => FOSSDB}/apps/fossdb/host/models.py (100%) rename {FOSSDB_web => FOSSDB}/apps/fossdb/language/forms.py (100%) rename {FOSSDB_web => FOSSDB}/apps/fossdb/language/models.py (100%) rename {FOSSDB_web => FOSSDB}/apps/fossdb/license/forms.py (100%) rename {FOSSDB_web => FOSSDB}/apps/fossdb/license/models.py (100%) rename {FOSSDB_web => FOSSDB}/apps/fossdb/migrations/0001_initial.py (100%) rename {FOSSDB_web => FOSSDB}/apps/fossdb/migrations/0002_operatingsystem_project_os.py (100%) rename {FOSSDB_web => FOSSDB}/apps/fossdb/migrations/0003_star_project_star.py (100%) rename {FOSSDB_web => FOSSDB}/apps/fossdb/migrations/__init__.py (100%) rename {FOSSDB_web => FOSSDB}/apps/fossdb/models.py (100%) rename {FOSSDB_web => FOSSDB}/apps/fossdb/operating_system/models.py (100%) rename {FOSSDB_web => FOSSDB}/apps/fossdb/star/models.py (100%) rename {FOSSDB_web => FOSSDB}/apps/fossdb/tag/models.py (100%) rename {FOSSDB_web => FOSSDB}/apps/fossdb/tests.py (100%) rename {FOSSDB_web => FOSSDB}/apps/fossdb/urls.py (100%) rename {FOSSDB_web => FOSSDB}/apps/fossdb/views.py (100%) rename {FOSSDB_web => FOSSDB}/asgi.py (73%) rename {FOSSDB_web => FOSSDB}/settings.py (95%) rename {FOSSDB_web => FOSSDB}/urls.py (96%) rename {FOSSDB_web => FOSSDB}/wsgi.py (73%) diff --git a/FOSSDB_web/__init__.py b/FOSSDB/__init__.py similarity index 100% rename from FOSSDB_web/__init__.py rename to FOSSDB/__init__.py diff --git a/FOSSDB_web/apps/account/__init__.py b/FOSSDB/apps/account/__init__.py similarity index 100% rename from FOSSDB_web/apps/account/__init__.py rename to FOSSDB/apps/account/__init__.py diff --git a/FOSSDB_web/apps/account/admin.py b/FOSSDB/apps/account/admin.py similarity index 100% rename from FOSSDB_web/apps/account/admin.py rename to FOSSDB/apps/account/admin.py diff --git a/FOSSDB_web/apps/account/apps.py b/FOSSDB/apps/account/apps.py similarity index 100% rename from FOSSDB_web/apps/account/apps.py rename to FOSSDB/apps/account/apps.py diff --git a/FOSSDB_web/apps/account/forms.py b/FOSSDB/apps/account/forms.py similarity index 100% rename from FOSSDB_web/apps/account/forms.py rename to FOSSDB/apps/account/forms.py diff --git a/FOSSDB_web/apps/account/tests.py b/FOSSDB/apps/account/tests.py similarity index 100% rename from FOSSDB_web/apps/account/tests.py rename to FOSSDB/apps/account/tests.py diff --git a/FOSSDB_web/apps/account/urls.py b/FOSSDB/apps/account/urls.py similarity index 100% rename from FOSSDB_web/apps/account/urls.py rename to FOSSDB/apps/account/urls.py diff --git a/FOSSDB_web/apps/account/views.py b/FOSSDB/apps/account/views.py similarity index 100% rename from FOSSDB_web/apps/account/views.py rename to FOSSDB/apps/account/views.py diff --git a/FOSSDB_web/apps/fossdb/__init__.py b/FOSSDB/apps/fossdb/__init__.py similarity index 100% rename from FOSSDB_web/apps/fossdb/__init__.py rename to FOSSDB/apps/fossdb/__init__.py diff --git a/FOSSDB_web/apps/fossdb/admin.py b/FOSSDB/apps/fossdb/admin.py similarity index 100% rename from FOSSDB_web/apps/fossdb/admin.py rename to FOSSDB/apps/fossdb/admin.py diff --git a/FOSSDB_web/apps/fossdb/apps.py b/FOSSDB/apps/fossdb/apps.py similarity index 100% rename from FOSSDB_web/apps/fossdb/apps.py rename to FOSSDB/apps/fossdb/apps.py diff --git a/FOSSDB_web/apps/fossdb/forms.py b/FOSSDB/apps/fossdb/forms.py similarity index 100% rename from FOSSDB_web/apps/fossdb/forms.py rename to FOSSDB/apps/fossdb/forms.py diff --git a/FOSSDB_web/apps/fossdb/host/forms.py b/FOSSDB/apps/fossdb/host/forms.py similarity index 100% rename from FOSSDB_web/apps/fossdb/host/forms.py rename to FOSSDB/apps/fossdb/host/forms.py diff --git a/FOSSDB_web/apps/fossdb/host/models.py b/FOSSDB/apps/fossdb/host/models.py similarity index 100% rename from FOSSDB_web/apps/fossdb/host/models.py rename to FOSSDB/apps/fossdb/host/models.py diff --git a/FOSSDB_web/apps/fossdb/language/forms.py b/FOSSDB/apps/fossdb/language/forms.py similarity index 100% rename from FOSSDB_web/apps/fossdb/language/forms.py rename to FOSSDB/apps/fossdb/language/forms.py diff --git a/FOSSDB_web/apps/fossdb/language/models.py b/FOSSDB/apps/fossdb/language/models.py similarity index 100% rename from FOSSDB_web/apps/fossdb/language/models.py rename to FOSSDB/apps/fossdb/language/models.py diff --git a/FOSSDB_web/apps/fossdb/license/forms.py b/FOSSDB/apps/fossdb/license/forms.py similarity index 100% rename from FOSSDB_web/apps/fossdb/license/forms.py rename to FOSSDB/apps/fossdb/license/forms.py diff --git a/FOSSDB_web/apps/fossdb/license/models.py b/FOSSDB/apps/fossdb/license/models.py similarity index 100% rename from FOSSDB_web/apps/fossdb/license/models.py rename to FOSSDB/apps/fossdb/license/models.py diff --git a/FOSSDB_web/apps/fossdb/migrations/0001_initial.py b/FOSSDB/apps/fossdb/migrations/0001_initial.py similarity index 100% rename from FOSSDB_web/apps/fossdb/migrations/0001_initial.py rename to FOSSDB/apps/fossdb/migrations/0001_initial.py diff --git a/FOSSDB_web/apps/fossdb/migrations/0002_operatingsystem_project_os.py b/FOSSDB/apps/fossdb/migrations/0002_operatingsystem_project_os.py similarity index 100% rename from FOSSDB_web/apps/fossdb/migrations/0002_operatingsystem_project_os.py rename to FOSSDB/apps/fossdb/migrations/0002_operatingsystem_project_os.py diff --git a/FOSSDB_web/apps/fossdb/migrations/0003_star_project_star.py b/FOSSDB/apps/fossdb/migrations/0003_star_project_star.py similarity index 100% rename from FOSSDB_web/apps/fossdb/migrations/0003_star_project_star.py rename to FOSSDB/apps/fossdb/migrations/0003_star_project_star.py diff --git a/FOSSDB_web/apps/fossdb/migrations/__init__.py b/FOSSDB/apps/fossdb/migrations/__init__.py similarity index 100% rename from FOSSDB_web/apps/fossdb/migrations/__init__.py rename to FOSSDB/apps/fossdb/migrations/__init__.py diff --git a/FOSSDB_web/apps/fossdb/models.py b/FOSSDB/apps/fossdb/models.py similarity index 100% rename from FOSSDB_web/apps/fossdb/models.py rename to FOSSDB/apps/fossdb/models.py diff --git a/FOSSDB_web/apps/fossdb/operating_system/models.py b/FOSSDB/apps/fossdb/operating_system/models.py similarity index 100% rename from FOSSDB_web/apps/fossdb/operating_system/models.py rename to FOSSDB/apps/fossdb/operating_system/models.py diff --git a/FOSSDB_web/apps/fossdb/star/models.py b/FOSSDB/apps/fossdb/star/models.py similarity index 100% rename from FOSSDB_web/apps/fossdb/star/models.py rename to FOSSDB/apps/fossdb/star/models.py diff --git a/FOSSDB_web/apps/fossdb/tag/models.py b/FOSSDB/apps/fossdb/tag/models.py similarity index 100% rename from FOSSDB_web/apps/fossdb/tag/models.py rename to FOSSDB/apps/fossdb/tag/models.py diff --git a/FOSSDB_web/apps/fossdb/tests.py b/FOSSDB/apps/fossdb/tests.py similarity index 100% rename from FOSSDB_web/apps/fossdb/tests.py rename to FOSSDB/apps/fossdb/tests.py diff --git a/FOSSDB_web/apps/fossdb/urls.py b/FOSSDB/apps/fossdb/urls.py similarity index 100% rename from FOSSDB_web/apps/fossdb/urls.py rename to FOSSDB/apps/fossdb/urls.py diff --git a/FOSSDB_web/apps/fossdb/views.py b/FOSSDB/apps/fossdb/views.py similarity index 100% rename from FOSSDB_web/apps/fossdb/views.py rename to FOSSDB/apps/fossdb/views.py diff --git a/FOSSDB_web/asgi.py b/FOSSDB/asgi.py similarity index 73% rename from FOSSDB_web/asgi.py rename to FOSSDB/asgi.py index e090765..11a6b23 100644 --- a/FOSSDB_web/asgi.py +++ b/FOSSDB/asgi.py @@ -1,5 +1,5 @@ """ -ASGI config for FOSSDB_web project. +ASGI config for FOSSDB project. It exposes the ASGI callable as a module-level variable named ``application``. @@ -11,6 +11,6 @@ import os from django.core.asgi import get_asgi_application -os.environ.setdefault("DJANGO_SETTINGS_MODULE", "FOSSDB_web.settings") +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "FOSSDB.settings") application = get_asgi_application() diff --git a/FOSSDB_web/settings.py b/FOSSDB/settings.py similarity index 95% rename from FOSSDB_web/settings.py rename to FOSSDB/settings.py index 0c10737..39ae324 100644 --- a/FOSSDB_web/settings.py +++ b/FOSSDB/settings.py @@ -1,5 +1,5 @@ """ -Django settings for FOSSDB_web project. +Django settings for FOSSDB project. Generated by "django-admin startproject" using Django 4.0.5. @@ -16,7 +16,7 @@ from pathlib import Path # Build paths inside the project like this: BASE_DIR / "subdir". BASE_PATH = Path(__file__).resolve().parent.parent -sys.path.insert(0, str(BASE_PATH.joinpath("FOSSDB_web", "apps"))) +sys.path.insert(0, str(BASE_PATH.joinpath("FOSSDB", "apps"))) # SECURITY WARNING: don't run with debug turned on in production! @@ -56,7 +56,7 @@ MIDDLEWARE = [ "django.middleware.clickjacking.XFrameOptionsMiddleware", ] -ROOT_URLCONF = "FOSSDB_web.urls" +ROOT_URLCONF = "FOSSDB.urls" TEMPLATES = [ { @@ -74,7 +74,7 @@ TEMPLATES = [ }, ] -WSGI_APPLICATION = "FOSSDB_web.wsgi.application" +WSGI_APPLICATION = "FOSSDB.wsgi.application" # Database diff --git a/FOSSDB_web/urls.py b/FOSSDB/urls.py similarity index 96% rename from FOSSDB_web/urls.py rename to FOSSDB/urls.py index a68021a..6618184 100644 --- a/FOSSDB_web/urls.py +++ b/FOSSDB/urls.py @@ -1,4 +1,4 @@ -"""FOSSDB_web URL Configuration +"""FOSSDB URL Configuration The `urlpatterns` list routes URLs to views. For more information please see: https://docs.djangoproject.com/en/4.0/topics/http/urls/ diff --git a/FOSSDB_web/wsgi.py b/FOSSDB/wsgi.py similarity index 73% rename from FOSSDB_web/wsgi.py rename to FOSSDB/wsgi.py index 3d462f8..db8157c 100644 --- a/FOSSDB_web/wsgi.py +++ b/FOSSDB/wsgi.py @@ -1,5 +1,5 @@ """ -WSGI config for FOSSDB_web project. +WSGI config for FOSSDB project. It exposes the WSGI callable as a module-level variable named ``application``. @@ -11,6 +11,6 @@ import os from django.core.wsgi import get_wsgi_application -os.environ.setdefault("DJANGO_SETTINGS_MODULE", "FOSSDB_web.settings") +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "FOSSDB.settings") application = get_wsgi_application() diff --git a/README.md b/README.md index 3772914..6d6ce19 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ # FOSSDB [![License](https://img.shields.io/badge/license-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0.en.html) -![Tests](https://github.com/kristoferssolo/FOSSDB-Web/actions/workflows/test.yml/badge.svg) -![Lint](https://github.com/kristoferssolo/FOSSDB-Web/actions/workflows/lint.yml/badge.svg) +![Tests](https://github.com/kristoferssolo/FOSSDB/actions/workflows/test.yml/badge.svg) +![Lint](https://github.com/kristoferssolo/FOSSDB/actions/workflows/lint.yml/badge.svg) FOSSDB is an open-source web application that helps users find, contribute, and collaborate on free and open-source software (FOSS) projects. diff --git a/manage.py b/manage.py index 94b8cd0..00cee50 100755 --- a/manage.py +++ b/manage.py @@ -6,7 +6,7 @@ import sys def main(): """Run administrative tasks.""" - os.environ.setdefault("DJANGO_SETTINGS_MODULE", "FOSSDB_web.settings") + os.environ.setdefault("DJANGO_SETTINGS_MODULE", "FOSSDB.settings") try: from django.core.management import execute_from_command_line except ImportError as exc: diff --git a/pyproject.toml b/pyproject.toml index 53ca1a8..b770667 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,7 +6,7 @@ build-backend = "setuptools.build_meta" check_untyped_defs = true disallow_any_generics = true ignore_missing_imports = true -mypy_path = "FOSSDB_web" +mypy_path = "FOSSDB" no_implicit_optional = true no_implicit_reexport = true show_error_codes = true diff --git a/setup.cfg b/setup.cfg index 11cce81..0d6842f 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,5 +1,5 @@ [metadata] -name = FOSSDB-Web +name = FOSSDB description = Free and Open-Source Software Database Website author = Kristofers Solo license = GPL3 @@ -9,7 +9,7 @@ classifiers = Programming Language :: Python :: 3.10 [options] -packages = FOSSDB_web +packages = FOSSDB install_requires = Django>=4.1 Pillow>=9.4.0 diff --git a/tox.ini b/tox.ini index 0e5c0d3..72d22b6 100644 --- a/tox.ini +++ b/tox.ini @@ -16,10 +16,10 @@ commands = python manage.py test [testenv:flake8] basepython = python3.10 deps = flake8 -commands = flake8 FOSSDB_web +commands = flake8 FOSSDB [testenv:mypy] basepython = python3.10 deps = -r{toxinidir}/requirements_dev.txt -commands = mypy FOSSDB_web +commands = mypy FOSSDB From 5b0c5dd244f61d611ab53628712b748788abaf4c Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Sun, 23 Apr 2023 18:32:46 +0300 Subject: [PATCH 083/144] Changed `flake8` to `ruff` --- .github/workflows/lint.yml | 25 ------------------------- .github/workflows/ruff.yml | 8 ++++++++ .github/workflows/test.yml | 23 +++++++++-------------- FOSSDB/apps/fossdb/models.py | 12 ++++++++---- pyproject.toml | 3 +++ requirements_dev.txt | 5 +---- setup.cfg | 35 ----------------------------------- setup.py | 4 ---- tox.ini | 25 ------------------------- 9 files changed, 29 insertions(+), 111 deletions(-) delete mode 100644 .github/workflows/lint.yml create mode 100644 .github/workflows/ruff.yml delete mode 100644 setup.cfg delete mode 100644 setup.py delete mode 100644 tox.ini diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml deleted file mode 100644 index 521effb..0000000 --- a/.github/workflows/lint.yml +++ /dev/null @@ -1,25 +0,0 @@ -name: Lint -on: - - push - - pull_request -jobs: - test: - runs-on: ${{ matrix.os }} - strategy: - matrix: - os: [ubuntu-latest] - python-version: ["3.10"] - steps: - - uses: actions/checkout@v2 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 - with: - python-version: ${{ matrix.python-version }} - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install mypy flake8 - - name: Lint with mypy - run: mypy FOSSDB_web - - name: Lint with flake8 - run: flake8 FOSSDB_web diff --git a/.github/workflows/ruff.yml b/.github/workflows/ruff.yml new file mode 100644 index 0000000..563b87d --- /dev/null +++ b/.github/workflows/ruff.yml @@ -0,0 +1,8 @@ +name: Ruff +on: [push, pull_request] +jobs: + ruff: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: chartboost/ruff-action@v1 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 88ecea3..264e1d4 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,23 +1,18 @@ -name: Test -on: - - push - - pull_request +name: Django Test +on: [push, pull_request] jobs: test: - runs-on: ${{ matrix.os }} - strategy: - matrix: - os: [ubuntu-latest] - python-version: ["3.10"] + runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 + - name: Checkout code + uses: actions/checkout@v2 + - name: Set up Python + uses: actions/setup_python@v2 with: - python-version: ${{ matrix.python-version }} + python-version: "3.10" - name: Install dependencies run: | python -m pip install --upgrade pip pip install -r requirements.txt - - name: Test with django test + - name: Run tests run: python manage.py test diff --git a/FOSSDB/apps/fossdb/models.py b/FOSSDB/apps/fossdb/models.py index 53d1bd0..5f19875 100644 --- a/FOSSDB/apps/fossdb/models.py +++ b/FOSSDB/apps/fossdb/models.py @@ -14,13 +14,16 @@ User = settings.AUTH_USER_MODEL class Project(models.Model): - uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) + uuid = models.UUIDField( + primary_key=True, default=uuid.uuid4, editable=False) author = models.ForeignKey(User, on_delete=models.CASCADE, db_index=True) name = models.CharField(max_length=255) description = models.TextField(blank=True, default="") licenses = models.ManyToManyField(License) - programming_languages = models.ManyToManyField(ProgrammingLanguage, through="ProjectProgrammingLanguage", related_name="projects") - hosting_platform = models.ManyToManyField(HostingPlatform, through="ProjectHostingPlatform", related_name="projects") + programming_languages = models.ManyToManyField( + ProgrammingLanguage, through="ProjectProgrammingLanguage", related_name="projects") + hosting_platform = models.ManyToManyField( + HostingPlatform, through="ProjectHostingPlatform", related_name="projects") tag = models.ManyToManyField(Tag) os = models.ManyToManyField(OperatingSystem) star = models.ManyToManyField(Star, related_name="projects_star") @@ -38,5 +41,6 @@ class Project(models.Model): def save(self, *args, **kwargs): if not self.uuid: - self.uuid = uuid.uuid3(uuid.uuid4(), f"{self.author.username}-{self.name}") + self.uuid = uuid.uuid3( + uuid.uuid4(), f"{self.author.username}-{self.name}") super().save(*args, **kwargs) diff --git a/pyproject.toml b/pyproject.toml index b770667..ed7c9bd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -15,3 +15,6 @@ warn_redundant_casts = true warn_return_any = true warn_unreachable = true warn_unused_configs = true + +[tool.ruff] +line-length = 160 diff --git a/requirements_dev.txt b/requirements_dev.txt index 14597cb..8373b5e 100644 --- a/requirements_dev.txt +++ b/requirements_dev.txt @@ -1,5 +1,2 @@ -flake8==6.0.0 mypy==0.991 -pytest-cov==4.0.0 -pytest==7.2.0 -tox==3.27.1 +ruff==0.0.262 diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index 0d6842f..0000000 --- a/setup.cfg +++ /dev/null @@ -1,35 +0,0 @@ -[metadata] -name = FOSSDB -description = Free and Open-Source Software Database Website -author = Kristofers Solo -license = GPL3 -license_files = LICENSE -platforms = unix, linux, osx, cygwin, win32 -classifiers = - Programming Language :: Python :: 3.10 - -[options] -packages = FOSSDB -install_requires = - Django>=4.1 - Pillow>=9.4.0 - fontawesomefree>=6.2.1 - mysqlclient>=2.1.1 - -python_requires = >=3.10 -package_dir = =. -zip_safe = no - -[options.extras_require] -testing = - flake8>=6.0.0 - mypy>=0.991 - pytest-cov>=4.0.0 - pytest>=7.2.0 - tox>=3.27.1 - -[options.package_data] -detector = py.typed - -[flake8] -max-line-length = 160 diff --git a/setup.py b/setup.py deleted file mode 100644 index 7f1a176..0000000 --- a/setup.py +++ /dev/null @@ -1,4 +0,0 @@ -from setuptools import setup - -if __name__ == "__main__": - setup() diff --git a/tox.ini b/tox.ini deleted file mode 100644 index 72d22b6..0000000 --- a/tox.ini +++ /dev/null @@ -1,25 +0,0 @@ -[tox] -minversion = 3.8.0 -envlist = django, flake8, mypy -isolated_build = true - -[gh-actions] -python = - 3.10: django, mypy, flake8 - - -[testenv:django] -basepython = python3.10 -deps = django -commands = python manage.py test - -[testenv:flake8] -basepython = python3.10 -deps = flake8 -commands = flake8 FOSSDB - -[testenv:mypy] -basepython = python3.10 -deps = - -r{toxinidir}/requirements_dev.txt -commands = mypy FOSSDB From 88b589a611df953776305c3ec91033811264796d Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Sun, 23 Apr 2023 18:33:22 +0300 Subject: [PATCH 084/144] Fix url --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6d6ce19..3056c88 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![License](https://img.shields.io/badge/license-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0.en.html) ![Tests](https://github.com/kristoferssolo/FOSSDB/actions/workflows/test.yml/badge.svg) -![Lint](https://github.com/kristoferssolo/FOSSDB/actions/workflows/lint.yml/badge.svg) +![Lint](https://github.com/kristoferssolo/FOSSDB/actions/workflows/ruff.yml/badge.svg) FOSSDB is an open-source web application that helps users find, contribute, and collaborate on free and open-source software (FOSS) projects. From 915505a1e817fca567812ed39c6756782f1795fc Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Sun, 23 Apr 2023 18:36:14 +0300 Subject: [PATCH 085/144] Fix setup-python --- .github/workflows/test.yml | 2 +- README.md | 4 ++-- pyproject.toml | 4 ---- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 264e1d4..6b85293 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -7,7 +7,7 @@ jobs: - name: Checkout code uses: actions/checkout@v2 - name: Set up Python - uses: actions/setup_python@v2 + uses: actions/setup-python@v2 with: python-version: "3.10" - name: Install dependencies diff --git a/README.md b/README.md index 3056c88..0524bad 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ # FOSSDB [![License](https://img.shields.io/badge/license-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0.en.html) -![Tests](https://github.com/kristoferssolo/FOSSDB/actions/workflows/test.yml/badge.svg) -![Lint](https://github.com/kristoferssolo/FOSSDB/actions/workflows/ruff.yml/badge.svg) +![Django Test](https://github.com/kristoferssolo/FOSSDB/actions/workflows/test.yml/badge.svg) +![Ruff](https://github.com/kristoferssolo/FOSSDB/actions/workflows/ruff.yml/badge.svg) FOSSDB is an open-source web application that helps users find, contribute, and collaborate on free and open-source software (FOSS) projects. diff --git a/pyproject.toml b/pyproject.toml index ed7c9bd..636869d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,3 @@ -[build-system] -requires = ["setuptools>=42.0", "wheel"] -build-backend = "setuptools.build_meta" - [tool.mypy] check_untyped_defs = true disallow_any_generics = true From fc43ec6a9ae84b1e5123dc1810858e9e19e1968d Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Sun, 23 Apr 2023 18:38:57 +0300 Subject: [PATCH 086/144] Test errors --- .github/workflows/test.yml | 4 ++-- FOSSDB/apps/fossdb/models.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 6b85293..f575616 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -5,9 +5,9 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout code - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Set up Python - uses: actions/setup-python@v2 + uses: actions/setup-python@v3 with: python-version: "3.10" - name: Install dependencies diff --git a/FOSSDB/apps/fossdb/models.py b/FOSSDB/apps/fossdb/models.py index 5f19875..7f189d7 100644 --- a/FOSSDB/apps/fossdb/models.py +++ b/FOSSDB/apps/fossdb/models.py @@ -10,7 +10,7 @@ from .operating_system.models import OperatingSystem from .star.models import Star from .tag.models import Tag -User = settings.AUTH_USER_MODEL +ser = settings.AUTH_USER_MODEL class Project(models.Model): From 3c6b8f3436440f6db235a7bb6cf5ea883d38b758 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Sun, 23 Apr 2023 18:41:12 +0300 Subject: [PATCH 087/144] Fix errors --- FOSSDB/apps/fossdb/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FOSSDB/apps/fossdb/models.py b/FOSSDB/apps/fossdb/models.py index 7f189d7..5f19875 100644 --- a/FOSSDB/apps/fossdb/models.py +++ b/FOSSDB/apps/fossdb/models.py @@ -10,7 +10,7 @@ from .operating_system.models import OperatingSystem from .star.models import Star from .tag.models import Tag -ser = settings.AUTH_USER_MODEL +User = settings.AUTH_USER_MODEL class Project(models.Model): From 134fe828c74a640b87ed58324b744baa036c6fac Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Fri, 16 Jun 2023 19:22:01 +0300 Subject: [PATCH 088/144] Updated packages --- requirements.txt | 6 +++--- requirements_dev.txt | 7 ++----- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/requirements.txt b/requirements.txt index c689f93..77ced76 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -Django==4.1.7 -Pillow==9.4.0 -fontawesomefree==6.2.1 +Django==4.2.2 +Pillow==9.5.0 +fontawesomefree==6.4.0 mysqlclient==2.1.1 diff --git a/requirements_dev.txt b/requirements_dev.txt index 14597cb..64c40bd 100644 --- a/requirements_dev.txt +++ b/requirements_dev.txt @@ -1,5 +1,2 @@ -flake8==6.0.0 -mypy==0.991 -pytest-cov==4.0.0 -pytest==7.2.0 -tox==3.27.1 +mypy==1.3.0 +ruff==0.0.272 From c1097eadec94870cce966acbc10e3836eeafa62d Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Fri, 16 Jun 2023 19:24:01 +0300 Subject: [PATCH 089/144] Swapped flake8 to ruff --- pyproject.toml | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 53ca1a8..14cbde0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,12 +1,8 @@ -[build-system] -requires = ["setuptools>=42.0", "wheel"] -build-backend = "setuptools.build_meta" - [tool.mypy] check_untyped_defs = true disallow_any_generics = true ignore_missing_imports = true -mypy_path = "FOSSDB_web" +mypy_path = "FOSSDB" no_implicit_optional = true no_implicit_reexport = true show_error_codes = true @@ -15,3 +11,10 @@ warn_redundant_casts = true warn_return_any = true warn_unreachable = true warn_unused_configs = true + +[tool.ruff] +line-length = 160 + + +[tool.ruff.flake8-quotes] +docstring-quotes = "double" From 860b6ed3e9a6b56b6c24069d66fc2afbdadbb9df Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Fri, 16 Jun 2023 19:27:24 +0300 Subject: [PATCH 090/144] Moved debug option to config file --- config.json | 1 + 1 file changed, 1 insertion(+) diff --git a/config.json b/config.json index 2871971..d834f37 100644 --- a/config.json +++ b/config.json @@ -1,4 +1,5 @@ { + "DEBUG": false, "SECRET_KEY": "", "ALLOWED_HOSTS": [""], "DATABASE": { From 012f6fe9c916d51bcbe5e68da24fd42cc6df184f Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Fri, 16 Jun 2023 19:27:32 +0300 Subject: [PATCH 091/144] Create example config file --- config.json.example | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 config.json.example diff --git a/config.json.example b/config.json.example new file mode 100644 index 0000000..d834f37 --- /dev/null +++ b/config.json.example @@ -0,0 +1,13 @@ +{ + "DEBUG": false, + "SECRET_KEY": "", + "ALLOWED_HOSTS": [""], + "DATABASE": { + "ENGINE": "", + "NAME": "", + "USER": "", + "PASSWORD": "", + "HOST": "", + "PORT": "" + } +} From b876b0857d4371839362f1055ffe944c1bd0cada Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Fri, 16 Jun 2023 19:43:40 +0300 Subject: [PATCH 092/144] Fix debug mode --- FOSSDB/apps/fossdb/migrations/0001_initial.py | 29 ++++++++++++++++++- .../0002_operatingsystem_project_os.py | 27 ----------------- .../migrations/0003_star_project_star.py | 29 ------------------- FOSSDB/settings.py | 5 ++-- 4 files changed, 30 insertions(+), 60 deletions(-) delete mode 100644 FOSSDB/apps/fossdb/migrations/0002_operatingsystem_project_os.py delete mode 100644 FOSSDB/apps/fossdb/migrations/0003_star_project_star.py diff --git a/FOSSDB/apps/fossdb/migrations/0001_initial.py b/FOSSDB/apps/fossdb/migrations/0001_initial.py index a142884..7dd555f 100644 --- a/FOSSDB/apps/fossdb/migrations/0001_initial.py +++ b/FOSSDB/apps/fossdb/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 4.1.7 on 2023-04-09 10:17 +# Generated by Django 4.2.2 on 2023-06-16 16:30 from django.conf import settings from django.db import migrations, models @@ -32,6 +32,15 @@ class Migration(migrations.Migration): ('description', models.TextField(blank=True, default='')), ], ), + migrations.CreateModel( + name='OperatingSystem', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=100)), + ('description', models.TextField(blank=True, default='')), + ('version', models.CharField(blank=True, max_length=50)), + ], + ), migrations.CreateModel( name='ProgrammingLanguage', fields=[ @@ -58,6 +67,14 @@ class Migration(migrations.Migration): ('icon', models.ImageField(blank=True, null=True, upload_to='types/icons/')), ], ), + migrations.CreateModel( + name='Star', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('project', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='stars', to='fossdb.project')), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ], + ), migrations.CreateModel( name='ProjectProgrammingLanguage', fields=[ @@ -86,11 +103,21 @@ class Migration(migrations.Migration): name='licenses', field=models.ManyToManyField(to='fossdb.license'), ), + migrations.AddField( + model_name='project', + name='os', + field=models.ManyToManyField(to='fossdb.operatingsystem'), + ), migrations.AddField( model_name='project', name='programming_languages', field=models.ManyToManyField(related_name='projects', through='fossdb.ProjectProgrammingLanguage', to='fossdb.programminglanguage'), ), + migrations.AddField( + model_name='project', + name='star', + field=models.ManyToManyField(related_name='projects_star', to='fossdb.star'), + ), migrations.AddField( model_name='project', name='tag', diff --git a/FOSSDB/apps/fossdb/migrations/0002_operatingsystem_project_os.py b/FOSSDB/apps/fossdb/migrations/0002_operatingsystem_project_os.py deleted file mode 100644 index 9741c32..0000000 --- a/FOSSDB/apps/fossdb/migrations/0002_operatingsystem_project_os.py +++ /dev/null @@ -1,27 +0,0 @@ -# Generated by Django 4.1.7 on 2023-04-09 10:35 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('fossdb', '0001_initial'), - ] - - operations = [ - migrations.CreateModel( - name='OperatingSystem', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=100)), - ('description', models.TextField(blank=True, default='')), - ('version', models.CharField(blank=True, max_length=50)), - ], - ), - migrations.AddField( - model_name='project', - name='os', - field=models.ManyToManyField(to='fossdb.operatingsystem'), - ), - ] diff --git a/FOSSDB/apps/fossdb/migrations/0003_star_project_star.py b/FOSSDB/apps/fossdb/migrations/0003_star_project_star.py deleted file mode 100644 index 2baf97f..0000000 --- a/FOSSDB/apps/fossdb/migrations/0003_star_project_star.py +++ /dev/null @@ -1,29 +0,0 @@ -# Generated by Django 4.1.7 on 2023-04-09 10:51 - -from django.conf import settings -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('fossdb', '0002_operatingsystem_project_os'), - ] - - operations = [ - migrations.CreateModel( - name='Star', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('project', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='stars', to='fossdb.project')), - ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), - ], - ), - migrations.AddField( - model_name='project', - name='star', - field=models.ManyToManyField(related_name='projects_star', to='fossdb.star'), - ), - ] diff --git a/FOSSDB/settings.py b/FOSSDB/settings.py index 39ae324..8d9989d 100644 --- a/FOSSDB/settings.py +++ b/FOSSDB/settings.py @@ -19,9 +19,6 @@ BASE_PATH = Path(__file__).resolve().parent.parent sys.path.insert(0, str(BASE_PATH.joinpath("FOSSDB", "apps"))) -# SECURITY WARNING: don't run with debug turned on in production! -DEBUG = BASE_PATH.joinpath("debug").is_file() - # Quick-start development settings - unsuitable for production # See https://docs.djangoproject.com/en/4.0/howto/deployment/checklist/ with open(BASE_PATH.joinpath("config.json"), "r", encoding="UTF-8") as config_file: @@ -32,6 +29,8 @@ SECRET_KEY = config["SECRET_KEY"] ALLOWED_HOSTS = config["ALLOWED_HOSTS"] +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = config["DEBUG"] # Application definition From 12b93544f92ad09ec167306b6d1b6d53aa967209 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Thu, 22 Jun 2023 09:24:18 +0000 Subject: [PATCH 093/144] Remove `config.json` --- .gitignore | 1 + config.json | 13 ------------- 2 files changed, 1 insertion(+), 13 deletions(-) delete mode 100644 config.json diff --git a/.gitignore b/.gitignore index 1c223fa..370e58e 100644 --- a/.gitignore +++ b/.gitignore @@ -134,3 +134,4 @@ debug /static/admin/ /static/fontawesomefree/ +config.json diff --git a/config.json b/config.json deleted file mode 100644 index d834f37..0000000 --- a/config.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "DEBUG": false, - "SECRET_KEY": "", - "ALLOWED_HOSTS": [""], - "DATABASE": { - "ENGINE": "", - "NAME": "", - "USER": "", - "PASSWORD": "", - "HOST": "", - "PORT": "" - } -} From bfc25c582f28d6674116e9aebef9abd7d77f9493 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Sun, 25 Jun 2023 13:46:46 +0000 Subject: [PATCH 094/144] Fix `HostingPlatform` Users can add projects and associated hosting platforms and respective URLs at the same time. --- FOSSDB/apps/fossdb/admin.py | 37 ++++++------ FOSSDB/apps/fossdb/forms.py | 38 ++++++++---- FOSSDB/apps/fossdb/host/forms.py | 22 ------- FOSSDB/apps/fossdb/host/models.py | 17 ------ FOSSDB/apps/fossdb/hosting_platform/models.py | 16 +++++ FOSSDB/apps/fossdb/models.py | 36 ++++++------ FOSSDB/apps/fossdb/views.py | 58 +++++++++---------- templates/fossdb/add_project.html | 13 +---- templates/fossdb/index.html | 22 ++----- 9 files changed, 116 insertions(+), 143 deletions(-) delete mode 100644 FOSSDB/apps/fossdb/host/forms.py delete mode 100644 FOSSDB/apps/fossdb/host/models.py create mode 100644 FOSSDB/apps/fossdb/hosting_platform/models.py diff --git a/FOSSDB/apps/fossdb/admin.py b/FOSSDB/apps/fossdb/admin.py index ea74c31..951a1ee 100644 --- a/FOSSDB/apps/fossdb/admin.py +++ b/FOSSDB/apps/fossdb/admin.py @@ -1,9 +1,10 @@ from django.contrib import admin -from .host.models import HostingPlatform, ProjectHostingPlatform -from .language.models import ProgrammingLanguage, ProjectProgrammingLanguage +from .hosting_platform.models import HostingPlatform, ProjectHostingPlatform from .license.models import License from .models import Project +from .operating_system.models import OperatingSystem, OperatingSystemVersion +from .programming_language.models import ProgrammingLanguage, ProjectProgrammingLanguage from .tag.models import Tag @@ -12,24 +13,26 @@ class ProjectProgrammingLanguageInline(admin.TabularInline): extra = 1 -class ProjectHostingPlatformInline(admin.TabularInline): - model = ProjectHostingPlatform - extra = 1 - - class ProjectAdmin(admin.ModelAdmin): - inlines = [ProjectProgrammingLanguageInline, ProjectHostingPlatformInline] - list_display = ("author", "name", "_languages", "_hosting_platform") + inlines = [ProjectProgrammingLanguageInline] + list_display = ("name", "author", "_languages", "hosting_platform") def _languages(self, object): - return " | ".join([i.language.language for i in object.projectprogramminglanguage_set.all()]) - - def _hosting_platform(self, object): - return " | ".join([i.hosting_platform.hosting_platform for i in object.projecthostingplatform_set.all()]) + return " | ".join( + [i.language.name for i in object.projectprogramminglanguage_set.all()] + ) -admin.site.register(HostingPlatform) +models = ( + HostingPlatform, + # ProjectHostingPlatform, # WARNING: remove this + License, + ProgrammingLanguage, + Tag, + OperatingSystem, + OperatingSystemVersion, +) +for model in models: + admin.site.register(model) + admin.site.register(Project, ProjectAdmin) -admin.site.register(License) -admin.site.register(ProgrammingLanguage) -admin.site.register(Tag) diff --git a/FOSSDB/apps/fossdb/forms.py b/FOSSDB/apps/fossdb/forms.py index b1f60e2..d51ae69 100644 --- a/FOSSDB/apps/fossdb/forms.py +++ b/FOSSDB/apps/fossdb/forms.py @@ -1,22 +1,40 @@ from django import forms +from .hosting_platform.models import HostingPlatform, ProjectHostingPlatform + from .models import Project class ProjectForm(forms.ModelForm): + hosting_platform = forms.ModelChoiceField(queryset=HostingPlatform.objects.all()) + url = forms.CharField(max_length=100) class Meta: model = Project - fields = ["name", "description", "licenses"] + fields = ( + "name", + "description", + "license", + "tag", + "operating_system", + ) + + exclude = ("hosting_platform",) widgets = { - "name": forms.TextInput(attrs={ - "class": "form-control", - "placeholder": "Project name", - }), - "description": forms.Textarea(attrs={ - "class": "form-control", - "placeholder": "Description", - }), - "licenses": forms.CheckboxSelectMultiple(), + "name": forms.TextInput( + attrs={ + "class": "form-control", + "placeholder": "Project name", + } + ), + "description": forms.Textarea( + attrs={ + "class": "form-control", + "placeholder": "Description", + } + ), + "license": forms.CheckboxSelectMultiple(), + "tag": forms.CheckboxSelectMultiple(), + "operating_system": forms.CheckboxSelectMultiple(), } diff --git a/FOSSDB/apps/fossdb/host/forms.py b/FOSSDB/apps/fossdb/host/forms.py deleted file mode 100644 index 5c04a50..0000000 --- a/FOSSDB/apps/fossdb/host/forms.py +++ /dev/null @@ -1,22 +0,0 @@ -from django import forms - -from fossdb.models import Project - -from .models import HostingPlatform, ProjectHostingPlatform - - -class HostingPlatformForm(forms.ModelForm): - url = forms.URLField() - - class Meta: - model = HostingPlatform - fields = ["hosting_platform", "url"] - - -ProjectHostingPlatformFormSet = forms.inlineformset_factory( - Project, - ProjectHostingPlatform, - form=HostingPlatformForm, - extra=1, - can_delete=False -) diff --git a/FOSSDB/apps/fossdb/host/models.py b/FOSSDB/apps/fossdb/host/models.py deleted file mode 100644 index c401aa0..0000000 --- a/FOSSDB/apps/fossdb/host/models.py +++ /dev/null @@ -1,17 +0,0 @@ -from django.db import models - - -class HostingPlatform(models.Model): - hosting_platform = models.CharField(max_length=100) - - def __str__(self): - return self.hosting_platform - - -class ProjectHostingPlatform(models.Model): - project = models.ForeignKey("Project", on_delete=models.CASCADE) - hosting_platform = models.ForeignKey(HostingPlatform, on_delete=models.CASCADE) - url = models.URLField() - - def __str__(self): - return f"{self.project} | {self.hosting_platform}" diff --git a/FOSSDB/apps/fossdb/hosting_platform/models.py b/FOSSDB/apps/fossdb/hosting_platform/models.py new file mode 100644 index 0000000..49e3020 --- /dev/null +++ b/FOSSDB/apps/fossdb/hosting_platform/models.py @@ -0,0 +1,16 @@ +from django.db import models + + +class HostingPlatform(models.Model): + name = models.CharField(max_length=100, unique=True) + + def __str__(self): + return self.name + + +class ProjectHostingPlatform(models.Model): + hosting_platform = models.ForeignKey(HostingPlatform, on_delete=models.CASCADE) + url = models.URLField(unique=True) + + def __str__(self): + return self.url diff --git a/FOSSDB/apps/fossdb/models.py b/FOSSDB/apps/fossdb/models.py index 5f19875..d8ee372 100644 --- a/FOSSDB/apps/fossdb/models.py +++ b/FOSSDB/apps/fossdb/models.py @@ -3,37 +3,40 @@ import uuid from django.conf import settings from django.db import models -from .host.models import HostingPlatform -from .language.models import ProgrammingLanguage +from .hosting_platform.models import ProjectHostingPlatform from .license.models import License -from .operating_system.models import OperatingSystem -from .star.models import Star +from .operating_system.models import OperatingSystemVersion +from .programming_language.models import ProgrammingLanguage from .tag.models import Tag User = settings.AUTH_USER_MODEL class Project(models.Model): - uuid = models.UUIDField( - primary_key=True, default=uuid.uuid4, editable=False) + uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) author = models.ForeignKey(User, on_delete=models.CASCADE, db_index=True) name = models.CharField(max_length=255) description = models.TextField(blank=True, default="") - licenses = models.ManyToManyField(License) - programming_languages = models.ManyToManyField( - ProgrammingLanguage, through="ProjectProgrammingLanguage", related_name="projects") - hosting_platform = models.ManyToManyField( - HostingPlatform, through="ProjectHostingPlatform", related_name="projects") - tag = models.ManyToManyField(Tag) - os = models.ManyToManyField(OperatingSystem) - star = models.ManyToManyField(Star, related_name="projects_star") + license = models.ManyToManyField(License, blank=True) + programming_language = models.ManyToManyField( + ProgrammingLanguage, + through="ProjectProgrammingLanguage", + related_name="projects", + blank=True, + ) + hosting_platform = models.ForeignKey( + ProjectHostingPlatform, on_delete=models.CASCADE + ) + tag = models.ManyToManyField(Tag, blank=True) + operating_system = models.ManyToManyField(OperatingSystemVersion, blank=True) date_created = models.DateTimeField(auto_now_add=True) @property def star_amount(self): return self.star.count() - def get_absolute_url(self): + @property + def absolute_url(self): return f"/{self.author.name}/{self.name}" def __str__(self): @@ -41,6 +44,5 @@ class Project(models.Model): def save(self, *args, **kwargs): if not self.uuid: - self.uuid = uuid.uuid3( - uuid.uuid4(), f"{self.author.username}-{self.name}") + self.uuid = uuid.uuid3(uuid.uuid4(), f"{self.author.username}-{self.name}") super().save(*args, **kwargs) diff --git a/FOSSDB/apps/fossdb/views.py b/FOSSDB/apps/fossdb/views.py index 4d76938..3d06ac4 100644 --- a/FOSSDB/apps/fossdb/views.py +++ b/FOSSDB/apps/fossdb/views.py @@ -1,12 +1,38 @@ from django.contrib.auth.decorators import login_required, permission_required from django.shortcuts import redirect, render +from django.views.generic import CreateView, DeleteView, DetailView, UpdateView from .forms import ProjectForm -from .host.forms import ProjectHostingPlatformFormSet -from .language.forms import ProjectProgrammingLanguageFormSet +from .hosting_platform.models import ProjectHostingPlatform from .models import Project +@login_required(login_url="login/") +@permission_required("fossdb.add_project", login_url="login/", raise_exception=True) +def add_project(request): + form = ProjectForm(request.POST or None) + + if request.method == "POST": + if form.is_valid(): + project = form.save(commit=False) + project.author = request.user + project_hosting_platform = ProjectHostingPlatform.objects.create( + hosting_platform=form.cleaned_data["hosting_platform"], + url=form.cleaned_data["url"], + ) + project.hosting_platform = project_hosting_platform + project.save() + + form.save_m2m() + return redirect("index") + + context = { + "title": "Add project", + "form": form, + } + return render(request, "fossdb/add_project.html", context) + + def index(request): context = { "title": "FOSSDB", @@ -15,36 +41,8 @@ def index(request): return render(request, "fossdb/index.html", context) -@login_required(login_url="login/") -@permission_required("fossdb.add_project", login_url="login/", raise_exception=True) -def add_project(request): - if request.method == "POST": - project_form = ProjectForm(request.POST) - language_formset = ProjectProgrammingLanguageFormSet(request.POST, instance=Project()) - host_formset = ProjectHostingPlatformFormSet(request.POST, instance=Project()) - if project_form.is_valid() and language_formset.is_valid() and host_formset.is_valid(): - project = project_form.save(commit=False) - project.author = request.user - project.save() - language_formset.instance = project - language_formset.save() - host_formset.instance = project - host_formset.save() - project_form.save_m2m() - return redirect("/") - else: - project_form = ProjectForm() - language_formset = ProjectProgrammingLanguageFormSet() - host_formset = ProjectHostingPlatformFormSet() - context = { - "title": "Add project", - "project_form": project_form, - "language_formset": language_formset, - "host_formset": host_formset, - } - return render(request, "fossdb/add_project.html", context) diff --git a/templates/fossdb/add_project.html b/templates/fossdb/add_project.html index d414e16..962a08e 100644 --- a/templates/fossdb/add_project.html +++ b/templates/fossdb/add_project.html @@ -5,18 +5,7 @@ {% block content %}
    {% csrf_token %} - {{ project_form.as_p }} - - {{ language_formset.management_form }} - {% for form in language_formset %} - - - - - - {% endfor %} -
    {{ form.language.label_tag }}{{ form.language }}{{ form.percentage }}
    - {{ host_formset.as_p }} + {{ form.as_p }}
    {% endblock %} diff --git a/templates/fossdb/index.html b/templates/fossdb/index.html index 3b062bb..2236b47 100644 --- a/templates/fossdb/index.html +++ b/templates/fossdb/index.html @@ -11,26 +11,12 @@
    {% for project in projects %} - @{{ project.author.username }} + @{{ project.owner }}

    {{ project.name }}

    -

    {{ project.description }}

    -
      - {% for license in project.licenses.all %} -
    • - {{ license.short_name }} -
    • - {% empty %} -

      No license

      - {% endfor %} -
    -
      - {% for language in project.projectprogramminglanguage_set.all %} -
    • {{ language.language }} | {{ language.percentage }}%
    • - {% empty %} -

      No language

      - {% endfor %} -

    + + +

    {{ project.date_created }}

    {% empty %}

    No projects yet (

    From 0c388c78cfc7c980ec02e198d38f1904ad784b38 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Sun, 25 Jun 2023 13:47:18 +0000 Subject: [PATCH 095/144] Rename `ProgrammingLanguage` directory --- FOSSDB/apps/fossdb/language/forms.py | 22 ----------------- .../apps/fossdb/programming_language/forms.py | 24 +++++++++++++++++++ .../models.py | 4 ++-- 3 files changed, 26 insertions(+), 24 deletions(-) delete mode 100644 FOSSDB/apps/fossdb/language/forms.py create mode 100644 FOSSDB/apps/fossdb/programming_language/forms.py rename FOSSDB/apps/fossdb/{language => programming_language}/models.py (84%) diff --git a/FOSSDB/apps/fossdb/language/forms.py b/FOSSDB/apps/fossdb/language/forms.py deleted file mode 100644 index a7cadf3..0000000 --- a/FOSSDB/apps/fossdb/language/forms.py +++ /dev/null @@ -1,22 +0,0 @@ -from django import forms - -from fossdb.models import Project - -from .models import ProgrammingLanguage, ProjectProgrammingLanguage - - -class ProgrammingLanguageForm(forms.ModelForm): - percentage = forms.IntegerField(min_value=0, max_value=100) - - class Meta: - model = ProgrammingLanguage - fields = ["language", "percentage"] - - -ProjectProgrammingLanguageFormSet = forms.inlineformset_factory( - Project, - ProjectProgrammingLanguage, - form=ProgrammingLanguageForm, - extra=1, - can_delete=True, -) diff --git a/FOSSDB/apps/fossdb/programming_language/forms.py b/FOSSDB/apps/fossdb/programming_language/forms.py new file mode 100644 index 0000000..eee0c01 --- /dev/null +++ b/FOSSDB/apps/fossdb/programming_language/forms.py @@ -0,0 +1,24 @@ +from django import forms +from django.forms import inlineformset_factory +from fossdb.models import Project + +from .models import ProgrammingLanguage, ProjectProgrammingLanguage + + +class ProgrammingLanguageForm(forms.ModelForm): + programming_language = forms.ModelChoiceField( + queryset=ProgrammingLanguage.objects.all() + ) + + class Meta: + model = ProjectProgrammingLanguage + fields = ("programming_language", "percentage") + + +ProjectProgrammingLanguageFormSet = inlineformset_factory( + Project, + ProjectProgrammingLanguage, + form=ProgrammingLanguageForm, + extra=1, + can_delete=True, +) diff --git a/FOSSDB/apps/fossdb/language/models.py b/FOSSDB/apps/fossdb/programming_language/models.py similarity index 84% rename from FOSSDB/apps/fossdb/language/models.py rename to FOSSDB/apps/fossdb/programming_language/models.py index 9a624f1..ef787db 100644 --- a/FOSSDB/apps/fossdb/language/models.py +++ b/FOSSDB/apps/fossdb/programming_language/models.py @@ -2,10 +2,10 @@ from django.db import models class ProgrammingLanguage(models.Model): - language = models.CharField(max_length=100) + name = models.CharField(max_length=100, unique=True) def __str__(self): - return self.language + return self.name class ProjectProgrammingLanguage(models.Model): From 8a729b9c8c01ebe12cc9726f522be03575386798 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Sun, 25 Jun 2023 13:47:45 +0000 Subject: [PATCH 096/144] Delete `License` form --- FOSSDB/apps/fossdb/license/forms.py | 9 --------- 1 file changed, 9 deletions(-) delete mode 100644 FOSSDB/apps/fossdb/license/forms.py diff --git a/FOSSDB/apps/fossdb/license/forms.py b/FOSSDB/apps/fossdb/license/forms.py deleted file mode 100644 index 0c180da..0000000 --- a/FOSSDB/apps/fossdb/license/forms.py +++ /dev/null @@ -1,9 +0,0 @@ -from django import forms - -from .models import License - - -class LicenseForm(forms.ModelForm): - class Meta: - model = License - fields = ["short_name", "full_name", "url", "description"] From 37aa41985512e08eb221fad95a54d837998674d4 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Sun, 25 Jun 2023 13:48:04 +0000 Subject: [PATCH 097/144] Make `License.short_name` and `License.full_name` unique --- FOSSDB/apps/fossdb/license/models.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/FOSSDB/apps/fossdb/license/models.py b/FOSSDB/apps/fossdb/license/models.py index 572a0b4..c66a21b 100644 --- a/FOSSDB/apps/fossdb/license/models.py +++ b/FOSSDB/apps/fossdb/license/models.py @@ -2,10 +2,10 @@ from django.db import models class License(models.Model): - short_name = models.CharField(max_length=50) - full_name = models.CharField(max_length=100, blank=True, default="") + short_name = models.CharField(max_length=50, unique=True) + full_name = models.CharField(max_length=100, unique=True) url = models.URLField(blank=True, default="") - description = models.TextField(blank=True, default="") + text = models.TextField(blank=True, default="") def __str__(self): return self.short_name From 5061d25c80475898add7d56c18ec77c04cb08374 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Sun, 25 Jun 2023 13:48:56 +0000 Subject: [PATCH 098/144] Make `OS.name` field unique --- FOSSDB/apps/fossdb/operating_system/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FOSSDB/apps/fossdb/operating_system/models.py b/FOSSDB/apps/fossdb/operating_system/models.py index d638ec8..92c2516 100644 --- a/FOSSDB/apps/fossdb/operating_system/models.py +++ b/FOSSDB/apps/fossdb/operating_system/models.py @@ -2,6 +2,6 @@ from django.db import models class OperatingSystem(models.Model): - name = models.CharField(max_length=100) + name = models.CharField(max_length=100, unique=True) description = models.TextField(blank=True, default="") version = models.CharField(max_length=50, blank=True) From 236d169c2cadeb464b562a1c6bc5cbcb400c0510 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Sun, 25 Jun 2023 13:49:25 +0000 Subject: [PATCH 099/144] Move `OS.version` to separate model --- FOSSDB/apps/fossdb/operating_system/models.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/FOSSDB/apps/fossdb/operating_system/models.py b/FOSSDB/apps/fossdb/operating_system/models.py index 92c2516..f876785 100644 --- a/FOSSDB/apps/fossdb/operating_system/models.py +++ b/FOSSDB/apps/fossdb/operating_system/models.py @@ -4,4 +4,14 @@ from django.db import models class OperatingSystem(models.Model): name = models.CharField(max_length=100, unique=True) description = models.TextField(blank=True, default="") - version = models.CharField(max_length=50, blank=True) + + + +class OperatingSystemVersion(models.Model): + operating_system = models.ForeignKey(OperatingSystem, on_delete=models.CASCADE) + version = models.CharField(max_length=50, blank=True, default="") + codename = models.CharField(max_length=100, blank=True, default="") + is_lts = models.BooleanField(blank=True, default=False) + + def __str__(self): + return f"{self.operating_system.name} {self.version} {'LTS' if self.is_lts else ''}" From c6f1092361d2c303cb3433bfe5b227d9c3c2c774 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Sun, 25 Jun 2023 13:49:39 +0000 Subject: [PATCH 100/144] Add `OS` default return option --- FOSSDB/apps/fossdb/operating_system/models.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/FOSSDB/apps/fossdb/operating_system/models.py b/FOSSDB/apps/fossdb/operating_system/models.py index f876785..24cc7ca 100644 --- a/FOSSDB/apps/fossdb/operating_system/models.py +++ b/FOSSDB/apps/fossdb/operating_system/models.py @@ -5,6 +5,8 @@ class OperatingSystem(models.Model): name = models.CharField(max_length=100, unique=True) description = models.TextField(blank=True, default="") + def __str__(self): + return self.name class OperatingSystemVersion(models.Model): From 90debba2488983ec79af74eeac698db0f8cb5809 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Sun, 25 Jun 2023 13:50:01 +0000 Subject: [PATCH 101/144] Make `Tag.name` unique --- FOSSDB/apps/fossdb/tag/models.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/FOSSDB/apps/fossdb/tag/models.py b/FOSSDB/apps/fossdb/tag/models.py index 10bb71e..21908a6 100644 --- a/FOSSDB/apps/fossdb/tag/models.py +++ b/FOSSDB/apps/fossdb/tag/models.py @@ -1,9 +1,8 @@ - from django.db import models class Tag(models.Model): - name = models.CharField(max_length=100) + name = models.CharField(max_length=100, unique=True, db_index=True) description = models.TextField(blank=True, default="") icon = models.ImageField(upload_to="types/icons/", null=True, blank=True) From f995959286036a2503601799ec595e27d8fec825 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Sun, 25 Jun 2023 14:04:18 +0000 Subject: [PATCH 102/144] Change `CharFiled` to `URLField` --- FOSSDB/apps/fossdb/forms.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/FOSSDB/apps/fossdb/forms.py b/FOSSDB/apps/fossdb/forms.py index d51ae69..04faa5a 100644 --- a/FOSSDB/apps/fossdb/forms.py +++ b/FOSSDB/apps/fossdb/forms.py @@ -1,26 +1,26 @@ from django import forms -from .hosting_platform.models import HostingPlatform, ProjectHostingPlatform +from .hosting_platform.models import HostingPlatform from .models import Project class ProjectForm(forms.ModelForm): hosting_platform = forms.ModelChoiceField(queryset=HostingPlatform.objects.all()) - url = forms.CharField(max_length=100) + url = forms.URLField(max_length=100) class Meta: model = Project fields = ( "name", "description", + "url", + "hosting_platform", "license", "tag", "operating_system", ) - exclude = ("hosting_platform",) - widgets = { "name": forms.TextInput( attrs={ From 9dbc32656a13363a1b418c3dbf0e055a857f80d4 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Sun, 25 Jun 2023 16:37:28 +0000 Subject: [PATCH 103/144] Fix `HostingPlatform` form Now on `Project` deletion associated `ProjectHostingPlatform` object also will be deleted --- FOSSDB/apps/fossdb/admin.py | 10 ++- FOSSDB/apps/fossdb/forms.py | 6 +- FOSSDB/apps/fossdb/hosting_platform/forms.py | 11 +++ FOSSDB/apps/fossdb/hosting_platform/models.py | 3 + FOSSDB/apps/fossdb/migrations/0001_initial.py | 67 +++++++------------ FOSSDB/apps/fossdb/models.py | 5 -- FOSSDB/apps/fossdb/views.py | 25 ++++--- templates/fossdb/add_project.html | 3 +- 8 files changed, 65 insertions(+), 65 deletions(-) create mode 100644 FOSSDB/apps/fossdb/hosting_platform/forms.py diff --git a/FOSSDB/apps/fossdb/admin.py b/FOSSDB/apps/fossdb/admin.py index 951a1ee..18d3918 100644 --- a/FOSSDB/apps/fossdb/admin.py +++ b/FOSSDB/apps/fossdb/admin.py @@ -13,9 +13,14 @@ class ProjectProgrammingLanguageInline(admin.TabularInline): extra = 1 +class ProjectHostingPlatformInline(admin.TabularInline): + model = ProjectHostingPlatform + extra = 1 + + class ProjectAdmin(admin.ModelAdmin): - inlines = [ProjectProgrammingLanguageInline] - list_display = ("name", "author", "_languages", "hosting_platform") + inlines = [ProjectHostingPlatformInline, ProjectProgrammingLanguageInline] + list_display = ("name", "author", "_languages") def _languages(self, object): return " | ".join( @@ -25,7 +30,6 @@ class ProjectAdmin(admin.ModelAdmin): models = ( HostingPlatform, - # ProjectHostingPlatform, # WARNING: remove this License, ProgrammingLanguage, Tag, diff --git a/FOSSDB/apps/fossdb/forms.py b/FOSSDB/apps/fossdb/forms.py index 04faa5a..9642f38 100644 --- a/FOSSDB/apps/fossdb/forms.py +++ b/FOSSDB/apps/fossdb/forms.py @@ -6,21 +6,19 @@ from .models import Project class ProjectForm(forms.ModelForm): - hosting_platform = forms.ModelChoiceField(queryset=HostingPlatform.objects.all()) - url = forms.URLField(max_length=100) class Meta: model = Project fields = ( "name", "description", - "url", - "hosting_platform", "license", "tag", "operating_system", ) + exclude = ("programming_language",) + widgets = { "name": forms.TextInput( attrs={ diff --git a/FOSSDB/apps/fossdb/hosting_platform/forms.py b/FOSSDB/apps/fossdb/hosting_platform/forms.py new file mode 100644 index 0000000..86aeb42 --- /dev/null +++ b/FOSSDB/apps/fossdb/hosting_platform/forms.py @@ -0,0 +1,11 @@ +from django import forms + +from .models import HostingPlatform, ProjectHostingPlatform + + +class ProjectHostingPlatformForm(forms.ModelForm): + hosting_platform = forms.ModelChoiceField(queryset=HostingPlatform.objects.all()) + + class Meta: + model = ProjectHostingPlatform + fields = ("hosting_platform", "url") diff --git a/FOSSDB/apps/fossdb/hosting_platform/models.py b/FOSSDB/apps/fossdb/hosting_platform/models.py index 49e3020..842f31f 100644 --- a/FOSSDB/apps/fossdb/hosting_platform/models.py +++ b/FOSSDB/apps/fossdb/hosting_platform/models.py @@ -1,5 +1,7 @@ from django.db import models +from fossdb.models import Project + class HostingPlatform(models.Model): name = models.CharField(max_length=100, unique=True) @@ -10,6 +12,7 @@ class HostingPlatform(models.Model): class ProjectHostingPlatform(models.Model): hosting_platform = models.ForeignKey(HostingPlatform, on_delete=models.CASCADE) + project = models.OneToOneField(Project, on_delete=models.CASCADE) url = models.URLField(unique=True) def __str__(self): diff --git a/FOSSDB/apps/fossdb/migrations/0001_initial.py b/FOSSDB/apps/fossdb/migrations/0001_initial.py index 7dd555f..51f11d8 100644 --- a/FOSSDB/apps/fossdb/migrations/0001_initial.py +++ b/FOSSDB/apps/fossdb/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 4.2.2 on 2023-06-16 16:30 +# Generated by Django 4.2.2 on 2023-06-25 16:15 from django.conf import settings from django.db import migrations, models @@ -19,33 +19,42 @@ class Migration(migrations.Migration): name='HostingPlatform', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('hosting_platform', models.CharField(max_length=100)), + ('name', models.CharField(max_length=100, unique=True)), ], ), migrations.CreateModel( name='License', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('short_name', models.CharField(max_length=50)), - ('full_name', models.CharField(blank=True, default='', max_length=100)), + ('short_name', models.CharField(max_length=50, unique=True)), + ('full_name', models.CharField(max_length=100, unique=True)), ('url', models.URLField(blank=True, default='')), - ('description', models.TextField(blank=True, default='')), + ('text', models.TextField(blank=True, default='')), ], ), migrations.CreateModel( name='OperatingSystem', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=100)), + ('name', models.CharField(max_length=100, unique=True)), ('description', models.TextField(blank=True, default='')), - ('version', models.CharField(blank=True, max_length=50)), + ], + ), + migrations.CreateModel( + name='OperatingSystemVersion', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('version', models.CharField(blank=True, default='', max_length=50)), + ('codename', models.CharField(blank=True, default='', max_length=100)), + ('is_lts', models.BooleanField(blank=True, default=False)), + ('operating_system', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='fossdb.operatingsystem')), ], ), migrations.CreateModel( name='ProgrammingLanguage', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('language', models.CharField(max_length=100)), + ('name', models.CharField(max_length=100, unique=True)), ], ), migrations.CreateModel( @@ -56,25 +65,19 @@ class Migration(migrations.Migration): ('description', models.TextField(blank=True, default='')), ('date_created', models.DateTimeField(auto_now_add=True)), ('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ('license', models.ManyToManyField(blank=True, to='fossdb.license')), + ('operating_system', models.ManyToManyField(blank=True, to='fossdb.operatingsystemversion')), ], ), migrations.CreateModel( name='Tag', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=100)), + ('name', models.CharField(db_index=True, max_length=100, unique=True)), ('description', models.TextField(blank=True, default='')), ('icon', models.ImageField(blank=True, null=True, upload_to='types/icons/')), ], ), - migrations.CreateModel( - name='Star', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('project', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='stars', to='fossdb.project')), - ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), - ], - ), migrations.CreateModel( name='ProjectProgrammingLanguage', fields=[ @@ -88,39 +91,19 @@ class Migration(migrations.Migration): name='ProjectHostingPlatform', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('url', models.URLField()), + ('url', models.URLField(unique=True)), ('hosting_platform', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='fossdb.hostingplatform')), - ('project', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='fossdb.project')), + ('project', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='fossdb.project')), ], ), migrations.AddField( model_name='project', - name='hosting_platform', - field=models.ManyToManyField(related_name='projects', through='fossdb.ProjectHostingPlatform', to='fossdb.hostingplatform'), - ), - migrations.AddField( - model_name='project', - name='licenses', - field=models.ManyToManyField(to='fossdb.license'), - ), - migrations.AddField( - model_name='project', - name='os', - field=models.ManyToManyField(to='fossdb.operatingsystem'), - ), - migrations.AddField( - model_name='project', - name='programming_languages', - field=models.ManyToManyField(related_name='projects', through='fossdb.ProjectProgrammingLanguage', to='fossdb.programminglanguage'), - ), - migrations.AddField( - model_name='project', - name='star', - field=models.ManyToManyField(related_name='projects_star', to='fossdb.star'), + name='programming_language', + field=models.ManyToManyField(blank=True, through='fossdb.ProjectProgrammingLanguage', to='fossdb.programminglanguage'), ), migrations.AddField( model_name='project', name='tag', - field=models.ManyToManyField(to='fossdb.tag'), + field=models.ManyToManyField(blank=True, to='fossdb.tag'), ), ] diff --git a/FOSSDB/apps/fossdb/models.py b/FOSSDB/apps/fossdb/models.py index d8ee372..7b46207 100644 --- a/FOSSDB/apps/fossdb/models.py +++ b/FOSSDB/apps/fossdb/models.py @@ -3,7 +3,6 @@ import uuid from django.conf import settings from django.db import models -from .hosting_platform.models import ProjectHostingPlatform from .license.models import License from .operating_system.models import OperatingSystemVersion from .programming_language.models import ProgrammingLanguage @@ -21,12 +20,8 @@ class Project(models.Model): programming_language = models.ManyToManyField( ProgrammingLanguage, through="ProjectProgrammingLanguage", - related_name="projects", blank=True, ) - hosting_platform = models.ForeignKey( - ProjectHostingPlatform, on_delete=models.CASCADE - ) tag = models.ManyToManyField(Tag, blank=True) operating_system = models.ManyToManyField(OperatingSystemVersion, blank=True) date_created = models.DateTimeField(auto_now_add=True) diff --git a/FOSSDB/apps/fossdb/views.py b/FOSSDB/apps/fossdb/views.py index 3d06ac4..9e85081 100644 --- a/FOSSDB/apps/fossdb/views.py +++ b/FOSSDB/apps/fossdb/views.py @@ -3,6 +3,7 @@ from django.shortcuts import redirect, render from django.views.generic import CreateView, DeleteView, DetailView, UpdateView from .forms import ProjectForm +from .hosting_platform.forms import ProjectHostingPlatformForm from .hosting_platform.models import ProjectHostingPlatform from .models import Project @@ -10,25 +11,29 @@ from .models import Project @login_required(login_url="login/") @permission_required("fossdb.add_project", login_url="login/", raise_exception=True) def add_project(request): - form = ProjectForm(request.POST or None) + project_form = ProjectForm(request.POST or None) + hosting_platform_form = ProjectHostingPlatformForm(request.POST or None) if request.method == "POST": - if form.is_valid(): - project = form.save(commit=False) + if project_form.is_valid() and hosting_platform_form.is_valid(): + project = project_form.save(commit=False) project.author = request.user - project_hosting_platform = ProjectHostingPlatform.objects.create( - hosting_platform=form.cleaned_data["hosting_platform"], - url=form.cleaned_data["url"], - ) - project.hosting_platform = project_hosting_platform project.save() - form.save_m2m() + project_hosting_platform = ProjectHostingPlatform( + hosting_platform=hosting_platform_form.cleaned_data["hosting_platform"], + project=project, + url=hosting_platform_form.cleaned_data["url"], + ) + project_hosting_platform.save() + + project_form.save_m2m() return redirect("index") context = { "title": "Add project", - "form": form, + "form": project_form, + "host_form": hosting_platform_form, } return render(request, "fossdb/add_project.html", context) diff --git a/templates/fossdb/add_project.html b/templates/fossdb/add_project.html index 962a08e..12b6134 100644 --- a/templates/fossdb/add_project.html +++ b/templates/fossdb/add_project.html @@ -6,6 +6,7 @@
    {% csrf_token %} {{ form.as_p }} - + {{ host_form.as_p }} +
    {% endblock %} From fd5dd8bf557468e1c0c9fda94f0575b24cc5daba Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Mon, 26 Jun 2023 13:11:21 +0000 Subject: [PATCH 104/144] Fix `HostingPlatform` --- FOSSDB/apps/fossdb/forms.py | 2 -- FOSSDB/apps/fossdb/hosting_platform/forms.py | 14 +++++++---- FOSSDB/apps/fossdb/views.py | 25 ++++++++++---------- templates/fossdb/add_project.html | 4 ++-- 4 files changed, 24 insertions(+), 21 deletions(-) diff --git a/FOSSDB/apps/fossdb/forms.py b/FOSSDB/apps/fossdb/forms.py index 9642f38..6bd50be 100644 --- a/FOSSDB/apps/fossdb/forms.py +++ b/FOSSDB/apps/fossdb/forms.py @@ -1,7 +1,5 @@ from django import forms -from .hosting_platform.models import HostingPlatform - from .models import Project diff --git a/FOSSDB/apps/fossdb/hosting_platform/forms.py b/FOSSDB/apps/fossdb/hosting_platform/forms.py index 86aeb42..2f69d24 100644 --- a/FOSSDB/apps/fossdb/hosting_platform/forms.py +++ b/FOSSDB/apps/fossdb/hosting_platform/forms.py @@ -3,9 +3,15 @@ from django import forms from .models import HostingPlatform, ProjectHostingPlatform -class ProjectHostingPlatformForm(forms.ModelForm): - hosting_platform = forms.ModelChoiceField(queryset=HostingPlatform.objects.all()) - +class HostingPlatformForm(forms.ModelForm): class Meta: model = ProjectHostingPlatform - fields = ("hosting_platform", "url") + fields = ( + "url", + "hosting_platform", + ) + widgets = { + "hosting_platform": forms.Select( + choices=HostingPlatform.objects.all(), + ) + } diff --git a/FOSSDB/apps/fossdb/views.py b/FOSSDB/apps/fossdb/views.py index 9e85081..a7fdb7f 100644 --- a/FOSSDB/apps/fossdb/views.py +++ b/FOSSDB/apps/fossdb/views.py @@ -12,29 +12,28 @@ from .models import Project @permission_required("fossdb.add_project", login_url="login/", raise_exception=True) def add_project(request): project_form = ProjectForm(request.POST or None) - hosting_platform_form = ProjectHostingPlatformForm(request.POST or None) + hosting_platform_form = HostingPlatformForm(request.POST or None) + + _forms: dict[str, forms.ModelForm] = { + "project_form": project_form, + "hosting_platform_form": hosting_platform_form, + } if request.method == "POST": - if project_form.is_valid() and hosting_platform_form.is_valid(): + if all([form.is_valid() for form in _forms.values()]): project = project_form.save(commit=False) project.author = request.user project.save() - project_hosting_platform = ProjectHostingPlatform( - hosting_platform=hosting_platform_form.cleaned_data["hosting_platform"], - project=project, - url=hosting_platform_form.cleaned_data["url"], - ) - project_hosting_platform.save() + hosting_platform = hosting_platform_form.save(commit=False) + hosting_platform.project = project + hosting_platform.save() + project_form.save_m2m() return redirect("index") - context = { - "title": "Add project", - "form": project_form, - "host_form": hosting_platform_form, - } + context = {"title": "Add project", **_forms} return render(request, "fossdb/add_project.html", context) diff --git a/templates/fossdb/add_project.html b/templates/fossdb/add_project.html index 12b6134..d8db375 100644 --- a/templates/fossdb/add_project.html +++ b/templates/fossdb/add_project.html @@ -5,8 +5,8 @@ {% block content %}
    {% csrf_token %} - {{ form.as_p }} - {{ host_form.as_p }} + {{ project_form.as_p }} + {{ hosting_platform_form.as_table }}
    {% endblock %} From d3931e52aa9e2041faa3d795a79730c6898277fc Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Mon, 26 Jun 2023 14:01:17 +0000 Subject: [PATCH 105/144] Added `ProgrammingLanguage` input field Users can now add programming language and percentage to the project. ### TODO - [ ] Allow users to add multiple languages --- FOSSDB/apps/fossdb/admin.py | 4 +-- FOSSDB/apps/fossdb/forms.py | 3 -- FOSSDB/apps/fossdb/migrations/0001_initial.py | 11 ++----- FOSSDB/apps/fossdb/models.py | 8 +---- .../apps/fossdb/programming_language/forms.py | 31 +++++++++---------- .../fossdb/programming_language/models.py | 7 +++-- FOSSDB/apps/fossdb/views.py | 12 +++++-- templates/fossdb/add_project.html | 2 ++ 8 files changed, 35 insertions(+), 43 deletions(-) diff --git a/FOSSDB/apps/fossdb/admin.py b/FOSSDB/apps/fossdb/admin.py index 18d3918..161c5fd 100644 --- a/FOSSDB/apps/fossdb/admin.py +++ b/FOSSDB/apps/fossdb/admin.py @@ -23,9 +23,7 @@ class ProjectAdmin(admin.ModelAdmin): list_display = ("name", "author", "_languages") def _languages(self, object): - return " | ".join( - [i.language.name for i in object.projectprogramminglanguage_set.all()] - ) + return " | ".join([i.programming_language.name for i in object.projectprogramminglanguage_set.all()]) models = ( diff --git a/FOSSDB/apps/fossdb/forms.py b/FOSSDB/apps/fossdb/forms.py index 6bd50be..8416109 100644 --- a/FOSSDB/apps/fossdb/forms.py +++ b/FOSSDB/apps/fossdb/forms.py @@ -4,7 +4,6 @@ from .models import Project class ProjectForm(forms.ModelForm): - class Meta: model = Project fields = ( @@ -15,8 +14,6 @@ class ProjectForm(forms.ModelForm): "operating_system", ) - exclude = ("programming_language",) - widgets = { "name": forms.TextInput( attrs={ diff --git a/FOSSDB/apps/fossdb/migrations/0001_initial.py b/FOSSDB/apps/fossdb/migrations/0001_initial.py index 51f11d8..ba092d8 100644 --- a/FOSSDB/apps/fossdb/migrations/0001_initial.py +++ b/FOSSDB/apps/fossdb/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 4.2.2 on 2023-06-25 16:15 +# Generated by Django 4.2.2 on 2023-06-26 13:46 from django.conf import settings from django.db import migrations, models @@ -60,7 +60,7 @@ class Migration(migrations.Migration): migrations.CreateModel( name='Project', fields=[ - ('uuid', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), + ('uuid', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False, verbose_name='ID')), ('name', models.CharField(max_length=255)), ('description', models.TextField(blank=True, default='')), ('date_created', models.DateTimeField(auto_now_add=True)), @@ -83,7 +83,7 @@ class Migration(migrations.Migration): fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('percentage', models.PositiveIntegerField()), - ('language', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='fossdb.programminglanguage')), + ('programming_language', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='fossdb.programminglanguage')), ('project', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='fossdb.project')), ], ), @@ -96,11 +96,6 @@ class Migration(migrations.Migration): ('project', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='fossdb.project')), ], ), - migrations.AddField( - model_name='project', - name='programming_language', - field=models.ManyToManyField(blank=True, through='fossdb.ProjectProgrammingLanguage', to='fossdb.programminglanguage'), - ), migrations.AddField( model_name='project', name='tag', diff --git a/FOSSDB/apps/fossdb/models.py b/FOSSDB/apps/fossdb/models.py index 7b46207..5fb8572 100644 --- a/FOSSDB/apps/fossdb/models.py +++ b/FOSSDB/apps/fossdb/models.py @@ -5,23 +5,17 @@ from django.db import models from .license.models import License from .operating_system.models import OperatingSystemVersion -from .programming_language.models import ProgrammingLanguage from .tag.models import Tag User = settings.AUTH_USER_MODEL class Project(models.Model): - uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) + uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False, verbose_name="ID") author = models.ForeignKey(User, on_delete=models.CASCADE, db_index=True) name = models.CharField(max_length=255) description = models.TextField(blank=True, default="") license = models.ManyToManyField(License, blank=True) - programming_language = models.ManyToManyField( - ProgrammingLanguage, - through="ProjectProgrammingLanguage", - blank=True, - ) tag = models.ManyToManyField(Tag, blank=True) operating_system = models.ManyToManyField(OperatingSystemVersion, blank=True) date_created = models.DateTimeField(auto_now_add=True) diff --git a/FOSSDB/apps/fossdb/programming_language/forms.py b/FOSSDB/apps/fossdb/programming_language/forms.py index eee0c01..4d29eb5 100644 --- a/FOSSDB/apps/fossdb/programming_language/forms.py +++ b/FOSSDB/apps/fossdb/programming_language/forms.py @@ -1,24 +1,23 @@ from django import forms -from django.forms import inlineformset_factory -from fossdb.models import Project from .models import ProgrammingLanguage, ProjectProgrammingLanguage class ProgrammingLanguageForm(forms.ModelForm): - programming_language = forms.ModelChoiceField( - queryset=ProgrammingLanguage.objects.all() - ) - class Meta: model = ProjectProgrammingLanguage - fields = ("programming_language", "percentage") - - -ProjectProgrammingLanguageFormSet = inlineformset_factory( - Project, - ProjectProgrammingLanguage, - form=ProgrammingLanguageForm, - extra=1, - can_delete=True, -) + fields = ( + "programming_language", + "percentage", + ) + widgets = { + "programming_language": forms.Select( + choices=ProgrammingLanguage.objects.all(), + ), + "percentage": forms.NumberInput( + attrs={ + "min": "0", + "max": "100", + } + ), + } diff --git a/FOSSDB/apps/fossdb/programming_language/models.py b/FOSSDB/apps/fossdb/programming_language/models.py index ef787db..7c62a0d 100644 --- a/FOSSDB/apps/fossdb/programming_language/models.py +++ b/FOSSDB/apps/fossdb/programming_language/models.py @@ -1,4 +1,5 @@ from django.db import models +from fossdb.models import Project class ProgrammingLanguage(models.Model): @@ -9,9 +10,9 @@ class ProgrammingLanguage(models.Model): class ProjectProgrammingLanguage(models.Model): - project = models.ForeignKey("Project", on_delete=models.CASCADE) - language = models.ForeignKey(ProgrammingLanguage, on_delete=models.CASCADE) + project = models.ForeignKey(Project, on_delete=models.CASCADE) + programming_language = models.ForeignKey(ProgrammingLanguage, on_delete=models.CASCADE) percentage = models.PositiveIntegerField() def __str__(self): - return f"{self.project} | {self.language} | {self.percentage}%" + return f"{self.project} | {self.programming_language} | {self.percentage}%" diff --git a/FOSSDB/apps/fossdb/views.py b/FOSSDB/apps/fossdb/views.py index a7fdb7f..9cc57aa 100644 --- a/FOSSDB/apps/fossdb/views.py +++ b/FOSSDB/apps/fossdb/views.py @@ -1,11 +1,12 @@ +from django import forms from django.contrib.auth.decorators import login_required, permission_required from django.shortcuts import redirect, render from django.views.generic import CreateView, DeleteView, DetailView, UpdateView from .forms import ProjectForm -from .hosting_platform.forms import ProjectHostingPlatformForm -from .hosting_platform.models import ProjectHostingPlatform +from .hosting_platform.forms import HostingPlatformForm from .models import Project +from .programming_language.forms import ProgrammingLanguageForm @login_required(login_url="login/") @@ -13,10 +14,12 @@ from .models import Project def add_project(request): project_form = ProjectForm(request.POST or None) hosting_platform_form = HostingPlatformForm(request.POST or None) + programming_language_form = ProgrammingLanguageForm(request.POST or None) _forms: dict[str, forms.ModelForm] = { "project_form": project_form, "hosting_platform_form": hosting_platform_form, + "programming_language_form": programming_language_form, } if request.method == "POST": @@ -29,8 +32,11 @@ def add_project(request): hosting_platform.project = project hosting_platform.save() + # TODO: allow adding multiple languages + programming_language = programming_language_form.save(commit=False) + programming_language.project = project + programming_language.save() - project_form.save_m2m() return redirect("index") context = {"title": "Add project", **_forms} diff --git a/templates/fossdb/add_project.html b/templates/fossdb/add_project.html index d8db375..b25bbd7 100644 --- a/templates/fossdb/add_project.html +++ b/templates/fossdb/add_project.html @@ -7,6 +7,8 @@ {% csrf_token %} {{ project_form.as_p }} {{ hosting_platform_form.as_table }} +
    + {{ programming_language_form.as_table }} {% endblock %} From 7166099b72c4d94b1ca25e5c724d14ea010d633a Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Mon, 26 Jun 2023 14:01:40 +0000 Subject: [PATCH 106/144] Update `pyproject.toml` Added some config options --- pyproject.toml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index 14cbde0..7c136c2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -15,6 +15,21 @@ warn_unused_configs = true [tool.ruff] line-length = 160 +[tool.black] +line-length = 160 [tool.ruff.flake8-quotes] docstring-quotes = "double" + +[tool.djlint] +close_void_tags = true +format_attribute_template_tags = true +format_css = true +format_js = true +max_line_length = 120 + +[tool.djlint.css] +indent_size = 4 + +[tool.djlint.js] +indent_size = 4 From 558a52d319daa9c9db6ff2fab06032ef5559585c Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Mon, 26 Jun 2023 14:07:14 +0000 Subject: [PATCH 107/144] Renamed `Project.author` to `Project.owner` --- FOSSDB/apps/fossdb/admin.py | 2 +- .../0002_rename_author_project_owner.py | 18 ++++++++++++++++++ FOSSDB/apps/fossdb/models.py | 8 ++++---- 3 files changed, 23 insertions(+), 5 deletions(-) create mode 100644 FOSSDB/apps/fossdb/migrations/0002_rename_author_project_owner.py diff --git a/FOSSDB/apps/fossdb/admin.py b/FOSSDB/apps/fossdb/admin.py index 161c5fd..ed62fd0 100644 --- a/FOSSDB/apps/fossdb/admin.py +++ b/FOSSDB/apps/fossdb/admin.py @@ -20,7 +20,7 @@ class ProjectHostingPlatformInline(admin.TabularInline): class ProjectAdmin(admin.ModelAdmin): inlines = [ProjectHostingPlatformInline, ProjectProgrammingLanguageInline] - list_display = ("name", "author", "_languages") + list_display = ("name", "owner", "_languages") def _languages(self, object): return " | ".join([i.programming_language.name for i in object.projectprogramminglanguage_set.all()]) diff --git a/FOSSDB/apps/fossdb/migrations/0002_rename_author_project_owner.py b/FOSSDB/apps/fossdb/migrations/0002_rename_author_project_owner.py new file mode 100644 index 0000000..e9aa5dc --- /dev/null +++ b/FOSSDB/apps/fossdb/migrations/0002_rename_author_project_owner.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2.2 on 2023-06-26 14:06 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('fossdb', '0001_initial'), + ] + + operations = [ + migrations.RenameField( + model_name='project', + old_name='author', + new_name='owner', + ), + ] diff --git a/FOSSDB/apps/fossdb/models.py b/FOSSDB/apps/fossdb/models.py index 5fb8572..a961e79 100644 --- a/FOSSDB/apps/fossdb/models.py +++ b/FOSSDB/apps/fossdb/models.py @@ -12,7 +12,7 @@ User = settings.AUTH_USER_MODEL class Project(models.Model): uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False, verbose_name="ID") - author = models.ForeignKey(User, on_delete=models.CASCADE, db_index=True) + owner = models.ForeignKey(User, on_delete=models.CASCADE, db_index=True) name = models.CharField(max_length=255) description = models.TextField(blank=True, default="") license = models.ManyToManyField(License, blank=True) @@ -26,12 +26,12 @@ class Project(models.Model): @property def absolute_url(self): - return f"/{self.author.name}/{self.name}" + return f"/{self.owner}/{self.name}" def __str__(self): - return f"{self.author} | {self.name}" + return f"{self.owner} | {self.name}" def save(self, *args, **kwargs): if not self.uuid: - self.uuid = uuid.uuid3(uuid.uuid4(), f"{self.author.username}-{self.name}") + self.uuid = uuid.uuid3(uuid.uuid4(), f"{self.owner.username}-{self.name}") super().save(*args, **kwargs) From c7145b096a0a67ea70620e882eb46c5742ed9362 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Mon, 26 Jun 2023 14:08:45 +0000 Subject: [PATCH 108/144] Fix: save M2M tables --- FOSSDB/apps/fossdb/views.py | 1 + 1 file changed, 1 insertion(+) diff --git a/FOSSDB/apps/fossdb/views.py b/FOSSDB/apps/fossdb/views.py index 9cc57aa..35fa898 100644 --- a/FOSSDB/apps/fossdb/views.py +++ b/FOSSDB/apps/fossdb/views.py @@ -37,6 +37,7 @@ def add_project(request): programming_language.project = project programming_language.save() + project.save_m2m() return redirect("index") context = {"title": "Add project", **_forms} From a2868b573d3dc631693e91043048397d6efbc368 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Mon, 26 Jun 2023 14:40:32 +0000 Subject: [PATCH 109/144] Fix `Project` absolute url --- FOSSDB/apps/fossdb/models.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/FOSSDB/apps/fossdb/models.py b/FOSSDB/apps/fossdb/models.py index a961e79..4a2e73a 100644 --- a/FOSSDB/apps/fossdb/models.py +++ b/FOSSDB/apps/fossdb/models.py @@ -24,8 +24,7 @@ class Project(models.Model): def star_amount(self): return self.star.count() - @property - def absolute_url(self): + def get_absolute_url(self): return f"/{self.owner}/{self.name}" def __str__(self): From 31cf63c1edb7a0275fedf0f820ee987f8c6fcc52 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Mon, 26 Jun 2023 14:41:36 +0000 Subject: [PATCH 110/144] Added `Project` detail view --- FOSSDB/apps/fossdb/urls.py | 3 ++- FOSSDB/apps/fossdb/views.py | 20 ++++++++++++--- templates/fossdb/detailed_view.html | 38 +++++++++++++++++++++++++++++ 3 files changed, 56 insertions(+), 5 deletions(-) create mode 100644 templates/fossdb/detailed_view.html diff --git a/FOSSDB/apps/fossdb/urls.py b/FOSSDB/apps/fossdb/urls.py index 11fbdee..4e0ad33 100644 --- a/FOSSDB/apps/fossdb/urls.py +++ b/FOSSDB/apps/fossdb/urls.py @@ -4,5 +4,6 @@ from . import views urlpatterns = [ path("", views.index, name="index"), - path("add", views.add_project, name="add-project"), + path("add/", views.add_project, name="add-project"), + path("//", views.ProjectDetailView.as_view(), name="project-detail"), ] diff --git a/FOSSDB/apps/fossdb/views.py b/FOSSDB/apps/fossdb/views.py index 35fa898..1a53e34 100644 --- a/FOSSDB/apps/fossdb/views.py +++ b/FOSSDB/apps/fossdb/views.py @@ -1,6 +1,9 @@ from django import forms +from django.conf import settings from django.contrib.auth.decorators import login_required, permission_required -from django.shortcuts import redirect, render +from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin +from django.shortcuts import get_object_or_404, redirect, render +from django.urls import reverse_lazy from django.views.generic import CreateView, DeleteView, DetailView, UpdateView from .forms import ProjectForm @@ -8,6 +11,8 @@ from .hosting_platform.forms import HostingPlatformForm from .models import Project from .programming_language.forms import ProgrammingLanguageForm +User = settings.AUTH_USER_MODEL + @login_required(login_url="login/") @permission_required("fossdb.add_project", login_url="login/", raise_exception=True) @@ -52,8 +57,15 @@ def index(request): return render(request, "fossdb/index.html", context) - - - +class ProjectDetailView(DetailView): + model = Project + template_name = "fossdb/detailed_view.html" + context_object_name = "project" + slug_field = "name" + slug_url_kwarg = "project_name" + + def get_queryset(self): + queryset = super().get_queryset() + return queryset.filter(owner__username=self.kwargs.get("username")) diff --git a/templates/fossdb/detailed_view.html b/templates/fossdb/detailed_view.html new file mode 100644 index 0000000..ba842da --- /dev/null +++ b/templates/fossdb/detailed_view.html @@ -0,0 +1,38 @@ +{% extends "layout.html" %} +{% load static %} +{% block title %}{{ project.name }}{% endblock %} +{% block meta %}{% endblock %} +{% block content %} +

    @{{ project.owner.username }}

    +

    {{ project.name }}

    +

    {{ project.description }}

    +
      + {% for license in project.licenses.all %} +
    • + {{ license.short_name }} +
    • + {% empty %} +

      No license

      + {% endfor %} +
    +
      + {% for language in project.projectprogramminglanguage_set.all %} +
    • {{ language.language }} | {{ language.percentage }}%
    • + {% empty %} +

      No language

      + {% endfor %} +
    +
      + {% for tag in project.tag.all %} +
    • {{ tag.name }}
    • + {% empty %} + {% endfor %} +
    +

    {{ project.date_created|date:"d.m.Y, G:i" }}

    + + +{% endblock %} From b041bf3773030dbf4a2c8532e64b09f3972be297 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Mon, 26 Jun 2023 14:41:58 +0000 Subject: [PATCH 111/144] Added `Project` update view --- FOSSDB/apps/fossdb/urls.py | 1 + FOSSDB/apps/fossdb/views.py | 19 +++++++++++++++++++ templates/fossdb/update_view.html | 20 ++++++++++++++++++++ 3 files changed, 40 insertions(+) create mode 100644 templates/fossdb/update_view.html diff --git a/FOSSDB/apps/fossdb/urls.py b/FOSSDB/apps/fossdb/urls.py index 4e0ad33..a86d3c2 100644 --- a/FOSSDB/apps/fossdb/urls.py +++ b/FOSSDB/apps/fossdb/urls.py @@ -6,4 +6,5 @@ urlpatterns = [ path("", views.index, name="index"), path("add/", views.add_project, name="add-project"), path("//", views.ProjectDetailView.as_view(), name="project-detail"), + path("//update/", views.ProjectUpdateView.as_view(), name="project-update"), ] diff --git a/FOSSDB/apps/fossdb/views.py b/FOSSDB/apps/fossdb/views.py index 1a53e34..16a03fb 100644 --- a/FOSSDB/apps/fossdb/views.py +++ b/FOSSDB/apps/fossdb/views.py @@ -69,3 +69,22 @@ class ProjectDetailView(DetailView): return queryset.filter(owner__username=self.kwargs.get("username")) +class ProjectUpdateView(LoginRequiredMixin, UserPassesTestMixin, UpdateView): + model = Project + template_name = "fossdb/update_view.html" + form_class = ( + ProjectForm, + HostingPlatformForm, + ProgrammingLanguageForm, + ) + slug_field = "name" + slug_url_kwarg = "project_name" + + def get_queryset(self): + queryset = super().get_queryset() + return queryset.filter(owner__username=self.kwargs.get("username")) + + def test_func(self): + return self.get_object().owner == self.request.user + + diff --git a/templates/fossdb/update_view.html b/templates/fossdb/update_view.html new file mode 100644 index 0000000..38b1f46 --- /dev/null +++ b/templates/fossdb/update_view.html @@ -0,0 +1,20 @@ +{% extends "layout.html" %} +{% block title %}Update {{ project.name }}{% endblock %} +{% block content %} +
    + {% csrf_token %} + {{ project_form.as_p }} + + {{ language_formset.management_form }} + {% for form in language_formset %} + + + + + + {% endfor %} +
    {{ form.language.label_tag }}{{ form.language }}{{ form.percentage }}
    + {{ host_formset.as_p }} + +
    +{% endblock %} From 360a1d76c056f184b5c5ec91e044b3ba9ee53145 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Mon, 26 Jun 2023 14:42:10 +0000 Subject: [PATCH 112/144] Added `Project` delete view --- FOSSDB/apps/fossdb/urls.py | 1 + FOSSDB/apps/fossdb/views.py | 13 +++++++++++++ templates/fossdb/delete_view.html | 9 +++++++++ 3 files changed, 23 insertions(+) create mode 100644 templates/fossdb/delete_view.html diff --git a/FOSSDB/apps/fossdb/urls.py b/FOSSDB/apps/fossdb/urls.py index a86d3c2..7653018 100644 --- a/FOSSDB/apps/fossdb/urls.py +++ b/FOSSDB/apps/fossdb/urls.py @@ -7,4 +7,5 @@ urlpatterns = [ path("add/", views.add_project, name="add-project"), path("//", views.ProjectDetailView.as_view(), name="project-detail"), path("//update/", views.ProjectUpdateView.as_view(), name="project-update"), + path("//delete/", views.ProjectDeleteView.as_view(), name="project-delete"), ] diff --git a/FOSSDB/apps/fossdb/views.py b/FOSSDB/apps/fossdb/views.py index 16a03fb..8a29c1f 100644 --- a/FOSSDB/apps/fossdb/views.py +++ b/FOSSDB/apps/fossdb/views.py @@ -88,3 +88,16 @@ class ProjectUpdateView(LoginRequiredMixin, UserPassesTestMixin, UpdateView): return self.get_object().owner == self.request.user +class ProjectDeleteView(LoginRequiredMixin, UserPassesTestMixin, DeleteView): + model = Project + template_name = "fossdb/delete_view.html" + slug_field = "name" + slug_url_kwarg = "project_name" + success_url = reverse_lazy("index") + + def get_queryset(self): + queryset = super().get_queryset() + return queryset.filter(owner__username=self.kwargs.get("username")) + + def test_func(self): + return self.get_object().owner == self.request.user diff --git a/templates/fossdb/delete_view.html b/templates/fossdb/delete_view.html new file mode 100644 index 0000000..b0c59df --- /dev/null +++ b/templates/fossdb/delete_view.html @@ -0,0 +1,9 @@ +{% extends "layout.html" %} +{% block title %}Delete {{ project.name }}{% endblock %} +{% block content %} +

    Are you sue you want to delete {{ project.name }}?

    +
    + {% csrf_token %} + +
    +{% endblock %} From dd9d2bee21db2cb029f30fbbdd17052dfd4691c6 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Mon, 26 Jun 2023 14:42:19 +0000 Subject: [PATCH 113/144] Fix --- templates/fossdb/index.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/templates/fossdb/index.html b/templates/fossdb/index.html index 2236b47..96caf62 100644 --- a/templates/fossdb/index.html +++ b/templates/fossdb/index.html @@ -3,17 +3,17 @@ {% block title %}{{ title }}{% endblock %} {% block meta %}{% endblock %} {% block content %} - - -
    +
    {% for project in projects %} @{{ project.owner }}

    {{ project.name }}

    -
    +
    From 2528d7d7ad39f867eb6b42c0d395af5ea6e479b6 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Mon, 26 Jun 2023 15:00:08 +0000 Subject: [PATCH 114/144] Added `Project` create view --- FOSSDB/apps/fossdb/urls.py | 2 +- FOSSDB/apps/fossdb/views.py | 69 ++++++++++++++--------------- templates/fossdb/detailed_view.html | 20 ++++++--- 3 files changed, 48 insertions(+), 43 deletions(-) diff --git a/FOSSDB/apps/fossdb/urls.py b/FOSSDB/apps/fossdb/urls.py index 7653018..c06a67b 100644 --- a/FOSSDB/apps/fossdb/urls.py +++ b/FOSSDB/apps/fossdb/urls.py @@ -4,7 +4,7 @@ from . import views urlpatterns = [ path("", views.index, name="index"), - path("add/", views.add_project, name="add-project"), + path("add/", views.ProjectCreateView.as_view(), name="add-project"), path("//", views.ProjectDetailView.as_view(), name="project-detail"), path("//update/", views.ProjectUpdateView.as_view(), name="project-update"), path("//delete/", views.ProjectDeleteView.as_view(), name="project-delete"), diff --git a/FOSSDB/apps/fossdb/views.py b/FOSSDB/apps/fossdb/views.py index 8a29c1f..a152097 100644 --- a/FOSSDB/apps/fossdb/views.py +++ b/FOSSDB/apps/fossdb/views.py @@ -1,6 +1,5 @@ from django import forms from django.conf import settings -from django.contrib.auth.decorators import login_required, permission_required from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin from django.shortcuts import get_object_or_404, redirect, render from django.urls import reverse_lazy @@ -14,41 +13,6 @@ from .programming_language.forms import ProgrammingLanguageForm User = settings.AUTH_USER_MODEL -@login_required(login_url="login/") -@permission_required("fossdb.add_project", login_url="login/", raise_exception=True) -def add_project(request): - project_form = ProjectForm(request.POST or None) - hosting_platform_form = HostingPlatformForm(request.POST or None) - programming_language_form = ProgrammingLanguageForm(request.POST or None) - - _forms: dict[str, forms.ModelForm] = { - "project_form": project_form, - "hosting_platform_form": hosting_platform_form, - "programming_language_form": programming_language_form, - } - - if request.method == "POST": - if all([form.is_valid() for form in _forms.values()]): - project = project_form.save(commit=False) - project.author = request.user - project.save() - - hosting_platform = hosting_platform_form.save(commit=False) - hosting_platform.project = project - hosting_platform.save() - - # TODO: allow adding multiple languages - programming_language = programming_language_form.save(commit=False) - programming_language.project = project - programming_language.save() - - project.save_m2m() - return redirect("index") - - context = {"title": "Add project", **_forms} - return render(request, "fossdb/add_project.html", context) - - def index(request): context = { "title": "FOSSDB", @@ -57,6 +21,39 @@ def index(request): return render(request, "fossdb/index.html", context) +class ProjectCreateView(LoginRequiredMixin, CreateView): + model = Project + form_class = ProjectForm + template_name = "fossdb/add_project.html" + + def form_valid(self, form): + form.instance.owner = self.request.user + response = super().form_valid(form) + + hosting_platform_form = HostingPlatformForm(self.request.POST, instance=self.object) + if hosting_platform_form.is_valid(): + hosting_platform = hosting_platform_form.save(commit=False) + hosting_platform.project = self.object + hosting_platform.save() + + # TODO: allow adding multiple languages + programming_language_form = ProgrammingLanguageForm(self.request.POST, instance=self.object) + if programming_language_form.is_valid(): + programming_language = programming_language_form.save(commit=False) + programming_language.project = self.object + programming_language.save() + + return response + + def get_context_data(self, *args, **kwargs): + context = super().get_context_data(**kwargs) + context["title"] = "Add project" + context["project_form"] = ProjectForm() + context["hosting_platform_form"] = HostingPlatformForm() + context["programming_language_form"] = ProgrammingLanguageForm() + return context + + class ProjectDetailView(DetailView): model = Project template_name = "fossdb/detailed_view.html" diff --git a/templates/fossdb/detailed_view.html b/templates/fossdb/detailed_view.html index ba842da..9c097bb 100644 --- a/templates/fossdb/detailed_view.html +++ b/templates/fossdb/detailed_view.html @@ -7,25 +7,33 @@

    {{ project.name }}

    {{ project.description }}

      - {% for language in project.projectprogramminglanguage_set.all %} -
    • {{ language.language }} | {{ language.percentage }}%
    • + {% for language in project.programming_language.all %} +
    • {{ language }}%
    • {% empty %}

      No language

      {% endfor %}
      - {% for tag in project.tag.all %} -
    • {{ tag.name }}
    • + {% for os in project.oprating_system.all %} +
    • {{ os.version }}
    • {% empty %} +

      No OS

      + {% endfor %} +
    +
      + {% for tag in project.tag.all %} +
    • {{ tag }}
    • + {% empty %} +

      No tag

      {% endfor %}

    {{ project.date_created|date:"d.m.Y, G:i" }}

    From fa40a0acc8a3727403d6497e345d6fd3660ddbf1 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Mon, 26 Jun 2023 16:23:05 +0000 Subject: [PATCH 115/144] Deleted `account` --- FOSSDB/apps/account/__init__.py | 0 FOSSDB/apps/account/admin.py | 0 FOSSDB/apps/account/apps.py | 6 ------ FOSSDB/apps/account/forms.py | 11 ----------- FOSSDB/apps/account/tests.py | 0 FOSSDB/apps/account/urls.py | 9 --------- FOSSDB/apps/account/views.py | 20 -------------------- FOSSDB/apps/fossdb/models.py | 11 ++--------- FOSSDB/settings.py | 2 +- FOSSDB/urls.py | 1 - templates/registration/login.html | 13 ------------- templates/registration/sign_up.html | 11 ----------- 12 files changed, 3 insertions(+), 81 deletions(-) delete mode 100644 FOSSDB/apps/account/__init__.py delete mode 100644 FOSSDB/apps/account/admin.py delete mode 100644 FOSSDB/apps/account/apps.py delete mode 100644 FOSSDB/apps/account/forms.py delete mode 100644 FOSSDB/apps/account/tests.py delete mode 100644 FOSSDB/apps/account/urls.py delete mode 100644 FOSSDB/apps/account/views.py delete mode 100644 templates/registration/login.html delete mode 100644 templates/registration/sign_up.html diff --git a/FOSSDB/apps/account/__init__.py b/FOSSDB/apps/account/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/FOSSDB/apps/account/admin.py b/FOSSDB/apps/account/admin.py deleted file mode 100644 index e69de29..0000000 diff --git a/FOSSDB/apps/account/apps.py b/FOSSDB/apps/account/apps.py deleted file mode 100644 index 2c684a9..0000000 --- a/FOSSDB/apps/account/apps.py +++ /dev/null @@ -1,6 +0,0 @@ -from django.apps import AppConfig - - -class AccountConfig(AppConfig): - default_auto_field = "django.db.models.BigAutoField" - name = "account" diff --git a/FOSSDB/apps/account/forms.py b/FOSSDB/apps/account/forms.py deleted file mode 100644 index 1b47e64..0000000 --- a/FOSSDB/apps/account/forms.py +++ /dev/null @@ -1,11 +0,0 @@ -from django import forms -from django.contrib.auth.forms import UserCreationForm -from django.contrib.auth.models import User - - -class RegisterForm(UserCreationForm): - email = forms.EmailField(required=True) - - class Meta: - model = User - fields = ["username", "email", "password1", "password2"] diff --git a/FOSSDB/apps/account/tests.py b/FOSSDB/apps/account/tests.py deleted file mode 100644 index e69de29..0000000 diff --git a/FOSSDB/apps/account/urls.py b/FOSSDB/apps/account/urls.py deleted file mode 100644 index 8fa14e8..0000000 --- a/FOSSDB/apps/account/urls.py +++ /dev/null @@ -1,9 +0,0 @@ -from django.urls import path - -from . import views - -urlpatterns = [ - path("", views.sign_up, name="singup"), - path("signup", views.sign_up, name="signup"), - path("login", views.login_, name="login"), -] diff --git a/FOSSDB/apps/account/views.py b/FOSSDB/apps/account/views.py deleted file mode 100644 index 4bf3238..0000000 --- a/FOSSDB/apps/account/views.py +++ /dev/null @@ -1,20 +0,0 @@ -from django.contrib.auth import login -from django.shortcuts import redirect, render - -from .forms import RegisterForm - - -def sign_up(request): - if request.method == "POST": - form = RegisterForm(request.POST) - if form.is_valid(): - user = form.save() - login(request, user) - return redirect("") - else: - form = RegisterForm() - return render(request, "registration/sign_up.html", {"title": "Sign Up", "form": form}) - - -def login_(request): - return render(request, "registration/login.html", {"title": "Login"}) diff --git a/FOSSDB/apps/fossdb/models.py b/FOSSDB/apps/fossdb/models.py index 4a2e73a..d615307 100644 --- a/FOSSDB/apps/fossdb/models.py +++ b/FOSSDB/apps/fossdb/models.py @@ -1,18 +1,16 @@ import uuid -from django.conf import settings +from django.contrib.auth.models import User from django.db import models from .license.models import License from .operating_system.models import OperatingSystemVersion from .tag.models import Tag -User = settings.AUTH_USER_MODEL - class Project(models.Model): uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False, verbose_name="ID") - owner = models.ForeignKey(User, on_delete=models.CASCADE, db_index=True) + owner = models.ForeignKey(User, on_delete=models.CASCADE) name = models.CharField(max_length=255) description = models.TextField(blank=True, default="") license = models.ManyToManyField(License, blank=True) @@ -29,8 +27,3 @@ class Project(models.Model): def __str__(self): return f"{self.owner} | {self.name}" - - def save(self, *args, **kwargs): - if not self.uuid: - self.uuid = uuid.uuid3(uuid.uuid4(), f"{self.owner.username}-{self.name}") - super().save(*args, **kwargs) diff --git a/FOSSDB/settings.py b/FOSSDB/settings.py index 8d9989d..c846f5e 100644 --- a/FOSSDB/settings.py +++ b/FOSSDB/settings.py @@ -35,7 +35,6 @@ DEBUG = config["DEBUG"] # Application definition INSTALLED_APPS = [ - "account", "fossdb", "django.contrib.admin", "django.contrib.auth", @@ -134,6 +133,7 @@ MEDIA_ROOT = BASE_PATH.joinpath("media") # https://docs.djangoproject.com/en/4.0/ref/settings/#default-auto-field DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField" +# LOGIN_URL = "login/" LOGIN_REDIRECT_URL = "/" LOGOUT_REDIRECT_URL = "/" diff --git a/FOSSDB/urls.py b/FOSSDB/urls.py index 6618184..1bb535d 100644 --- a/FOSSDB/urls.py +++ b/FOSSDB/urls.py @@ -20,7 +20,6 @@ from django.urls import include, path urlpatterns = [ path("", include("fossdb.urls")), - path("", include("account.urls")), path("admin/", admin.site.urls), path("", include("django.contrib.auth.urls")), ] diff --git a/templates/registration/login.html b/templates/registration/login.html deleted file mode 100644 index e1ca078..0000000 --- a/templates/registration/login.html +++ /dev/null @@ -1,13 +0,0 @@ -{% extends "layout.html" %} -{% load static %} -{% block title %}{{ title }}{% endblock %} -{% block meta %}{% endblock %} -{% block content %} -
    - {% csrf_token %}{{ form }} -

    - Don't have an account? Create one Here! -

    - -
    -{% endblock %} diff --git a/templates/registration/sign_up.html b/templates/registration/sign_up.html deleted file mode 100644 index 40b7bad..0000000 --- a/templates/registration/sign_up.html +++ /dev/null @@ -1,11 +0,0 @@ -{% extends "layout.html" %} -{% block title %}Sign Up{% endblock %} -{% block content %} -
    - {% csrf_token %}{{ form }} -

    - Have an account? Login Here! -

    - -
    -{% endblock %} From 6398e844a6d35214349fbe74b9ff758e550fc3dd Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Mon, 26 Jun 2023 16:30:54 +0000 Subject: [PATCH 116/144] Revert "Deleted `account`" This reverts commit fa40a0acc8a3727403d6497e345d6fd3660ddbf1. --- FOSSDB/apps/account/__init__.py | 0 FOSSDB/apps/account/admin.py | 0 FOSSDB/apps/account/apps.py | 6 ++++++ FOSSDB/apps/account/forms.py | 11 +++++++++++ FOSSDB/apps/account/tests.py | 0 FOSSDB/apps/account/urls.py | 9 +++++++++ FOSSDB/apps/account/views.py | 20 ++++++++++++++++++++ FOSSDB/apps/fossdb/models.py | 11 +++++++++-- FOSSDB/settings.py | 2 +- FOSSDB/urls.py | 1 + templates/registration/login.html | 13 +++++++++++++ templates/registration/sign_up.html | 11 +++++++++++ 12 files changed, 81 insertions(+), 3 deletions(-) create mode 100644 FOSSDB/apps/account/__init__.py create mode 100644 FOSSDB/apps/account/admin.py create mode 100644 FOSSDB/apps/account/apps.py create mode 100644 FOSSDB/apps/account/forms.py create mode 100644 FOSSDB/apps/account/tests.py create mode 100644 FOSSDB/apps/account/urls.py create mode 100644 FOSSDB/apps/account/views.py create mode 100644 templates/registration/login.html create mode 100644 templates/registration/sign_up.html diff --git a/FOSSDB/apps/account/__init__.py b/FOSSDB/apps/account/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/FOSSDB/apps/account/admin.py b/FOSSDB/apps/account/admin.py new file mode 100644 index 0000000..e69de29 diff --git a/FOSSDB/apps/account/apps.py b/FOSSDB/apps/account/apps.py new file mode 100644 index 0000000..2c684a9 --- /dev/null +++ b/FOSSDB/apps/account/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class AccountConfig(AppConfig): + default_auto_field = "django.db.models.BigAutoField" + name = "account" diff --git a/FOSSDB/apps/account/forms.py b/FOSSDB/apps/account/forms.py new file mode 100644 index 0000000..1b47e64 --- /dev/null +++ b/FOSSDB/apps/account/forms.py @@ -0,0 +1,11 @@ +from django import forms +from django.contrib.auth.forms import UserCreationForm +from django.contrib.auth.models import User + + +class RegisterForm(UserCreationForm): + email = forms.EmailField(required=True) + + class Meta: + model = User + fields = ["username", "email", "password1", "password2"] diff --git a/FOSSDB/apps/account/tests.py b/FOSSDB/apps/account/tests.py new file mode 100644 index 0000000..e69de29 diff --git a/FOSSDB/apps/account/urls.py b/FOSSDB/apps/account/urls.py new file mode 100644 index 0000000..8fa14e8 --- /dev/null +++ b/FOSSDB/apps/account/urls.py @@ -0,0 +1,9 @@ +from django.urls import path + +from . import views + +urlpatterns = [ + path("", views.sign_up, name="singup"), + path("signup", views.sign_up, name="signup"), + path("login", views.login_, name="login"), +] diff --git a/FOSSDB/apps/account/views.py b/FOSSDB/apps/account/views.py new file mode 100644 index 0000000..4bf3238 --- /dev/null +++ b/FOSSDB/apps/account/views.py @@ -0,0 +1,20 @@ +from django.contrib.auth import login +from django.shortcuts import redirect, render + +from .forms import RegisterForm + + +def sign_up(request): + if request.method == "POST": + form = RegisterForm(request.POST) + if form.is_valid(): + user = form.save() + login(request, user) + return redirect("") + else: + form = RegisterForm() + return render(request, "registration/sign_up.html", {"title": "Sign Up", "form": form}) + + +def login_(request): + return render(request, "registration/login.html", {"title": "Login"}) diff --git a/FOSSDB/apps/fossdb/models.py b/FOSSDB/apps/fossdb/models.py index d615307..4a2e73a 100644 --- a/FOSSDB/apps/fossdb/models.py +++ b/FOSSDB/apps/fossdb/models.py @@ -1,16 +1,18 @@ import uuid -from django.contrib.auth.models import User +from django.conf import settings from django.db import models from .license.models import License from .operating_system.models import OperatingSystemVersion from .tag.models import Tag +User = settings.AUTH_USER_MODEL + class Project(models.Model): uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False, verbose_name="ID") - owner = models.ForeignKey(User, on_delete=models.CASCADE) + owner = models.ForeignKey(User, on_delete=models.CASCADE, db_index=True) name = models.CharField(max_length=255) description = models.TextField(blank=True, default="") license = models.ManyToManyField(License, blank=True) @@ -27,3 +29,8 @@ class Project(models.Model): def __str__(self): return f"{self.owner} | {self.name}" + + def save(self, *args, **kwargs): + if not self.uuid: + self.uuid = uuid.uuid3(uuid.uuid4(), f"{self.owner.username}-{self.name}") + super().save(*args, **kwargs) diff --git a/FOSSDB/settings.py b/FOSSDB/settings.py index c846f5e..8d9989d 100644 --- a/FOSSDB/settings.py +++ b/FOSSDB/settings.py @@ -35,6 +35,7 @@ DEBUG = config["DEBUG"] # Application definition INSTALLED_APPS = [ + "account", "fossdb", "django.contrib.admin", "django.contrib.auth", @@ -133,7 +134,6 @@ MEDIA_ROOT = BASE_PATH.joinpath("media") # https://docs.djangoproject.com/en/4.0/ref/settings/#default-auto-field DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField" -# LOGIN_URL = "login/" LOGIN_REDIRECT_URL = "/" LOGOUT_REDIRECT_URL = "/" diff --git a/FOSSDB/urls.py b/FOSSDB/urls.py index 1bb535d..6618184 100644 --- a/FOSSDB/urls.py +++ b/FOSSDB/urls.py @@ -20,6 +20,7 @@ from django.urls import include, path urlpatterns = [ path("", include("fossdb.urls")), + path("", include("account.urls")), path("admin/", admin.site.urls), path("", include("django.contrib.auth.urls")), ] diff --git a/templates/registration/login.html b/templates/registration/login.html new file mode 100644 index 0000000..e1ca078 --- /dev/null +++ b/templates/registration/login.html @@ -0,0 +1,13 @@ +{% extends "layout.html" %} +{% load static %} +{% block title %}{{ title }}{% endblock %} +{% block meta %}{% endblock %} +{% block content %} +
    + {% csrf_token %}{{ form }} +

    + Don't have an account? Create one Here! +

    + +
    +{% endblock %} diff --git a/templates/registration/sign_up.html b/templates/registration/sign_up.html new file mode 100644 index 0000000..40b7bad --- /dev/null +++ b/templates/registration/sign_up.html @@ -0,0 +1,11 @@ +{% extends "layout.html" %} +{% block title %}Sign Up{% endblock %} +{% block content %} +
    + {% csrf_token %}{{ form }} +

    + Have an account? Login Here! +

    + +
    +{% endblock %} From 927e46dfee72c9603313cad36c04ae5d3c63020b Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Mon, 26 Jun 2023 16:50:20 +0000 Subject: [PATCH 117/144] Removed uuid gen --- FOSSDB/apps/fossdb/models.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/FOSSDB/apps/fossdb/models.py b/FOSSDB/apps/fossdb/models.py index 4a2e73a..7953744 100644 --- a/FOSSDB/apps/fossdb/models.py +++ b/FOSSDB/apps/fossdb/models.py @@ -12,7 +12,7 @@ User = settings.AUTH_USER_MODEL class Project(models.Model): uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False, verbose_name="ID") - owner = models.ForeignKey(User, on_delete=models.CASCADE, db_index=True) + owner = models.ForeignKey(User, on_delete=models.CASCADE) name = models.CharField(max_length=255) description = models.TextField(blank=True, default="") license = models.ManyToManyField(License, blank=True) @@ -29,8 +29,3 @@ class Project(models.Model): def __str__(self): return f"{self.owner} | {self.name}" - - def save(self, *args, **kwargs): - if not self.uuid: - self.uuid = uuid.uuid3(uuid.uuid4(), f"{self.owner.username}-{self.name}") - super().save(*args, **kwargs) From 4ab45b4347631c4e4fb5a5bf406346f1e46bb6ff Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Mon, 26 Jun 2023 17:13:10 +0000 Subject: [PATCH 118/144] Fix `account` --- FOSSDB/apps/account/forms.py | 11 +++++++--- FOSSDB/apps/account/models.py | 0 FOSSDB/apps/account/urls.py | 5 ++--- FOSSDB/apps/account/views.py | 40 ++++++++++++++++++++++++++--------- 4 files changed, 40 insertions(+), 16 deletions(-) create mode 100644 FOSSDB/apps/account/models.py diff --git a/FOSSDB/apps/account/forms.py b/FOSSDB/apps/account/forms.py index 1b47e64..b3f01a2 100644 --- a/FOSSDB/apps/account/forms.py +++ b/FOSSDB/apps/account/forms.py @@ -3,9 +3,14 @@ from django.contrib.auth.forms import UserCreationForm from django.contrib.auth.models import User -class RegisterForm(UserCreationForm): - email = forms.EmailField(required=True) +class SignUpForm(UserCreationForm): + email = forms.EmailField(required=False) class Meta: model = User - fields = ["username", "email", "password1", "password2"] + fields = ( + "username", + "email", + "password1", + "password2", + ) diff --git a/FOSSDB/apps/account/models.py b/FOSSDB/apps/account/models.py new file mode 100644 index 0000000..e69de29 diff --git a/FOSSDB/apps/account/urls.py b/FOSSDB/apps/account/urls.py index 8fa14e8..f060b68 100644 --- a/FOSSDB/apps/account/urls.py +++ b/FOSSDB/apps/account/urls.py @@ -3,7 +3,6 @@ from django.urls import path from . import views urlpatterns = [ - path("", views.sign_up, name="singup"), - path("signup", views.sign_up, name="signup"), - path("login", views.login_, name="login"), + path("signup/", views.signup_view, name="signup"), + path("login/", views.login_view, name="login"), ] diff --git a/FOSSDB/apps/account/views.py b/FOSSDB/apps/account/views.py index 4bf3238..88ba798 100644 --- a/FOSSDB/apps/account/views.py +++ b/FOSSDB/apps/account/views.py @@ -1,20 +1,40 @@ -from django.contrib.auth import login +from django.contrib.auth import authenticate, login +from django.contrib.auth.forms import AuthenticationForm from django.shortcuts import redirect, render -from .forms import RegisterForm +from .forms import SignUpForm -def sign_up(request): +def signup_view(request): + form = SignUpForm(request.POST or None) if request.method == "POST": - form = RegisterForm(request.POST) if form.is_valid(): user = form.save() + raw_password = form.cleaned_data.get("password1") + user = authenticate( + username=user.username, + password=raw_password, + ) login(request, user) - return redirect("") - else: - form = RegisterForm() - return render(request, "registration/sign_up.html", {"title": "Sign Up", "form": form}) + return redirect("index") + + context = { + "title": "Sign Up", + "form": form, + } + return render(request, "registration/signup.html", context) -def login_(request): - return render(request, "registration/login.html", {"title": "Login"}) +def login_view(request): + form = AuthenticationForm(data=request.POST or None) + if request.method == "POST": + if form.is_valid(): + user = form.get_user() + login(request, user) + return redirect("index") + + context = { + "title": "Login", + "form": form, + } + return render(request, "registration/login.html", context) From 28ed2827e81aa36a4f8a11f01246f8d5ff71c4b7 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Mon, 26 Jun 2023 17:13:47 +0000 Subject: [PATCH 119/144] Fix `UpdateView` --- FOSSDB/apps/fossdb/views.py | 56 +++++++++++++++---- FOSSDB/settings.py | 1 + templates/fossdb/update_view.html | 16 ++---- templates/registration/login.html | 3 +- .../{sign_up.html => signup.html} | 3 +- 5 files changed, 55 insertions(+), 24 deletions(-) rename templates/registration/{sign_up.html => signup.html} (85%) diff --git a/FOSSDB/apps/fossdb/views.py b/FOSSDB/apps/fossdb/views.py index a152097..5d8b5e7 100644 --- a/FOSSDB/apps/fossdb/views.py +++ b/FOSSDB/apps/fossdb/views.py @@ -1,5 +1,3 @@ -from django import forms -from django.conf import settings from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin from django.shortcuts import get_object_or_404, redirect, render from django.urls import reverse_lazy @@ -10,8 +8,6 @@ from .hosting_platform.forms import HostingPlatformForm from .models import Project from .programming_language.forms import ProgrammingLanguageForm -User = settings.AUTH_USER_MODEL - def index(request): context = { @@ -25,6 +21,8 @@ class ProjectCreateView(LoginRequiredMixin, CreateView): model = Project form_class = ProjectForm template_name = "fossdb/add_project.html" + login_url = "/login/" + redirect_field_name = "redirect_to" def form_valid(self, form): form.instance.owner = self.request.user @@ -69,13 +67,30 @@ class ProjectDetailView(DetailView): class ProjectUpdateView(LoginRequiredMixin, UserPassesTestMixin, UpdateView): model = Project template_name = "fossdb/update_view.html" - form_class = ( - ProjectForm, - HostingPlatformForm, - ProgrammingLanguageForm, - ) + form_class = ProjectForm slug_field = "name" slug_url_kwarg = "project_name" + login_url = "/login/" + redirect_field_name = "redirect_to" + + def form_valid(self, form): + form.instance.owner = self.request.user + response = super().form_valid(form) + + hosting_platform_form = HostingPlatformForm(self.request.POST, instance=self.object) + if hosting_platform_form.is_valid(): + hosting_platform = hosting_platform_form.save(commit=False) + hosting_platform.project = self.object + hosting_platform.save() + + # TODO: allow adding multiple languages + programming_language_form = ProgrammingLanguageForm(self.request.POST, instance=self.object) + if programming_language_form.is_valid(): + programming_language = programming_language_form.save(commit=False) + programming_language.project = self.object + programming_language.save() + + return response def get_queryset(self): queryset = super().get_queryset() @@ -84,13 +99,31 @@ class ProjectUpdateView(LoginRequiredMixin, UserPassesTestMixin, UpdateView): def test_func(self): return self.get_object().owner == self.request.user + def handle_no_permission(self): + return redirect("index") + + def get_context_data(self, *args, **kwargs): + context = super().get_context_data(**kwargs) + if self.request.POST: + context["project_form"] = ProjectForm(self.request.POST, instance=self.object) + context["hosting_platform_form"] = HostingPlatformForm(self.request.POST, instance=self.object) + context["programming_language_form"] = ProgrammingLanguageForm(self.request.POST, instance=self.object) + else: + context["project_form"] = ProjectForm(instance=self.object) + context["hosting_platform_form"] = HostingPlatformForm(instance=self.object) + context["programming_language_form"] = ProgrammingLanguageForm(instance=self.object) + + return context + class ProjectDeleteView(LoginRequiredMixin, UserPassesTestMixin, DeleteView): model = Project template_name = "fossdb/delete_view.html" slug_field = "name" slug_url_kwarg = "project_name" - success_url = reverse_lazy("index") + login_url = "/login/" + redirect_field_name = "redirect_to" + success_url = "/" def get_queryset(self): queryset = super().get_queryset() @@ -98,3 +131,6 @@ class ProjectDeleteView(LoginRequiredMixin, UserPassesTestMixin, DeleteView): def test_func(self): return self.get_object().owner == self.request.user + + def handle_no_permission(self): + return redirect("index") diff --git a/FOSSDB/settings.py b/FOSSDB/settings.py index 8d9989d..c840486 100644 --- a/FOSSDB/settings.py +++ b/FOSSDB/settings.py @@ -136,6 +136,7 @@ MEDIA_ROOT = BASE_PATH.joinpath("media") DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField" LOGIN_REDIRECT_URL = "/" LOGOUT_REDIRECT_URL = "/" +LOGIN_URL = "login/" # HTTPS settings # SESSION_COOKIE_SECURE = True diff --git a/templates/fossdb/update_view.html b/templates/fossdb/update_view.html index 38b1f46..48c0d7c 100644 --- a/templates/fossdb/update_view.html +++ b/templates/fossdb/update_view.html @@ -1,20 +1,12 @@ {% extends "layout.html" %} -{% block title %}Update {{ project.name }}{% endblock %} +{% block title %}Edit {{ project.name }}{% endblock %} {% block content %}
    {% csrf_token %} {{ project_form.as_p }} - - {{ language_formset.management_form }} - {% for form in language_formset %} - - - - - - {% endfor %} -
    {{ form.language.label_tag }}{{ form.language }}{{ form.percentage }}
    - {{ host_formset.as_p }} + {{ hosting_platform_form.as_table }} +
    + {{ programming_language_form.as_table }}
    {% endblock %} diff --git a/templates/registration/login.html b/templates/registration/login.html index e1ca078..c8eb1e4 100644 --- a/templates/registration/login.html +++ b/templates/registration/login.html @@ -4,7 +4,8 @@ {% block meta %}{% endblock %} {% block content %}
    - {% csrf_token %}{{ form }} + {% csrf_token %} + {{ form.as_p }}

    Don't have an account? Create one Here!

    diff --git a/templates/registration/sign_up.html b/templates/registration/signup.html similarity index 85% rename from templates/registration/sign_up.html rename to templates/registration/signup.html index 40b7bad..abfb049 100644 --- a/templates/registration/sign_up.html +++ b/templates/registration/signup.html @@ -2,7 +2,8 @@ {% block title %}Sign Up{% endblock %} {% block content %} - {% csrf_token %}{{ form }} + {% csrf_token %} + {{ form.as_p }}

    Have an account? Login Here!

    From 906fa002c6b165e42df1aadc8c08026e75993077 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Mon, 26 Jun 2023 17:14:12 +0000 Subject: [PATCH 120/144] Delete migrations --- FOSSDB/apps/fossdb/migrations/0001_initial.py | 104 ------------------ .../0002_rename_author_project_owner.py | 18 --- 2 files changed, 122 deletions(-) delete mode 100644 FOSSDB/apps/fossdb/migrations/0001_initial.py delete mode 100644 FOSSDB/apps/fossdb/migrations/0002_rename_author_project_owner.py diff --git a/FOSSDB/apps/fossdb/migrations/0001_initial.py b/FOSSDB/apps/fossdb/migrations/0001_initial.py deleted file mode 100644 index ba092d8..0000000 --- a/FOSSDB/apps/fossdb/migrations/0001_initial.py +++ /dev/null @@ -1,104 +0,0 @@ -# Generated by Django 4.2.2 on 2023-06-26 13:46 - -from django.conf import settings -from django.db import migrations, models -import django.db.models.deletion -import uuid - - -class Migration(migrations.Migration): - - initial = True - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ] - - operations = [ - migrations.CreateModel( - name='HostingPlatform', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=100, unique=True)), - ], - ), - migrations.CreateModel( - name='License', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('short_name', models.CharField(max_length=50, unique=True)), - ('full_name', models.CharField(max_length=100, unique=True)), - ('url', models.URLField(blank=True, default='')), - ('text', models.TextField(blank=True, default='')), - ], - ), - migrations.CreateModel( - name='OperatingSystem', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=100, unique=True)), - ('description', models.TextField(blank=True, default='')), - ], - ), - migrations.CreateModel( - name='OperatingSystemVersion', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('version', models.CharField(blank=True, default='', max_length=50)), - ('codename', models.CharField(blank=True, default='', max_length=100)), - ('is_lts', models.BooleanField(blank=True, default=False)), - ('operating_system', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='fossdb.operatingsystem')), - ], - ), - migrations.CreateModel( - name='ProgrammingLanguage', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=100, unique=True)), - ], - ), - migrations.CreateModel( - name='Project', - fields=[ - ('uuid', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=255)), - ('description', models.TextField(blank=True, default='')), - ('date_created', models.DateTimeField(auto_now_add=True)), - ('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), - ('license', models.ManyToManyField(blank=True, to='fossdb.license')), - ('operating_system', models.ManyToManyField(blank=True, to='fossdb.operatingsystemversion')), - ], - ), - migrations.CreateModel( - name='Tag', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(db_index=True, max_length=100, unique=True)), - ('description', models.TextField(blank=True, default='')), - ('icon', models.ImageField(blank=True, null=True, upload_to='types/icons/')), - ], - ), - migrations.CreateModel( - name='ProjectProgrammingLanguage', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('percentage', models.PositiveIntegerField()), - ('programming_language', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='fossdb.programminglanguage')), - ('project', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='fossdb.project')), - ], - ), - migrations.CreateModel( - name='ProjectHostingPlatform', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('url', models.URLField(unique=True)), - ('hosting_platform', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='fossdb.hostingplatform')), - ('project', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='fossdb.project')), - ], - ), - migrations.AddField( - model_name='project', - name='tag', - field=models.ManyToManyField(blank=True, to='fossdb.tag'), - ), - ] diff --git a/FOSSDB/apps/fossdb/migrations/0002_rename_author_project_owner.py b/FOSSDB/apps/fossdb/migrations/0002_rename_author_project_owner.py deleted file mode 100644 index e9aa5dc..0000000 --- a/FOSSDB/apps/fossdb/migrations/0002_rename_author_project_owner.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 4.2.2 on 2023-06-26 14:06 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('fossdb', '0001_initial'), - ] - - operations = [ - migrations.RenameField( - model_name='project', - old_name='author', - new_name='owner', - ), - ] From a1dbb904746c34996c7e6877d705db8366c0d657 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Mon, 26 Jun 2023 17:15:29 +0000 Subject: [PATCH 121/144] Removed license badge --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 0524bad..da9efdf 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,5 @@ # FOSSDB -[![License](https://img.shields.io/badge/license-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0.en.html) ![Django Test](https://github.com/kristoferssolo/FOSSDB/actions/workflows/test.yml/badge.svg) ![Ruff](https://github.com/kristoferssolo/FOSSDB/actions/workflows/ruff.yml/badge.svg) From 3cfe95d21426166d6574b4ca50fac10e95619649 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Tue, 27 Jun 2023 09:45:11 +0000 Subject: [PATCH 122/144] Fix `DetailView` Shows all fields of `Project` in `DetailView` --- FOSSDB/apps/fossdb/hosting_platform/models.py | 4 +- FOSSDB/apps/fossdb/migrations/0001_initial.py | 104 ++++++++++++++++++ .../0002_project_proggramming_language.py | 18 +++ ...g_language_project_programming_language.py | 18 +++ ...004_remove_project_programming_language.py | 17 +++ .../fossdb/programming_language/models.py | 5 +- FOSSDB/apps/fossdb/views.py | 50 +++------ templates/fossdb/detailed_view.html | 27 +++-- 8 files changed, 193 insertions(+), 50 deletions(-) create mode 100644 FOSSDB/apps/fossdb/migrations/0001_initial.py create mode 100644 FOSSDB/apps/fossdb/migrations/0002_project_proggramming_language.py create mode 100644 FOSSDB/apps/fossdb/migrations/0003_rename_proggramming_language_project_programming_language.py create mode 100644 FOSSDB/apps/fossdb/migrations/0004_remove_project_programming_language.py diff --git a/FOSSDB/apps/fossdb/hosting_platform/models.py b/FOSSDB/apps/fossdb/hosting_platform/models.py index 842f31f..62874e5 100644 --- a/FOSSDB/apps/fossdb/hosting_platform/models.py +++ b/FOSSDB/apps/fossdb/hosting_platform/models.py @@ -1,7 +1,5 @@ from django.db import models -from fossdb.models import Project - class HostingPlatform(models.Model): name = models.CharField(max_length=100, unique=True) @@ -12,7 +10,7 @@ class HostingPlatform(models.Model): class ProjectHostingPlatform(models.Model): hosting_platform = models.ForeignKey(HostingPlatform, on_delete=models.CASCADE) - project = models.OneToOneField(Project, on_delete=models.CASCADE) + project = models.OneToOneField("Project", on_delete=models.CASCADE) url = models.URLField(unique=True) def __str__(self): diff --git a/FOSSDB/apps/fossdb/migrations/0001_initial.py b/FOSSDB/apps/fossdb/migrations/0001_initial.py new file mode 100644 index 0000000..f7e9410 --- /dev/null +++ b/FOSSDB/apps/fossdb/migrations/0001_initial.py @@ -0,0 +1,104 @@ +# Generated by Django 4.2.2 on 2023-06-26 17:16 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='HostingPlatform', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=100, unique=True)), + ], + ), + migrations.CreateModel( + name='License', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('short_name', models.CharField(max_length=50, unique=True)), + ('full_name', models.CharField(max_length=100, unique=True)), + ('url', models.URLField(blank=True, default='')), + ('text', models.TextField(blank=True, default='')), + ], + ), + migrations.CreateModel( + name='OperatingSystem', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=100, unique=True)), + ('description', models.TextField(blank=True, default='')), + ], + ), + migrations.CreateModel( + name='OperatingSystemVersion', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('version', models.CharField(blank=True, default='', max_length=50)), + ('codename', models.CharField(blank=True, default='', max_length=100)), + ('is_lts', models.BooleanField(blank=True, default=False)), + ('operating_system', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='fossdb.operatingsystem')), + ], + ), + migrations.CreateModel( + name='ProgrammingLanguage', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=100, unique=True)), + ], + ), + migrations.CreateModel( + name='Project', + fields=[ + ('uuid', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=255)), + ('description', models.TextField(blank=True, default='')), + ('date_created', models.DateTimeField(auto_now_add=True)), + ('license', models.ManyToManyField(blank=True, to='fossdb.license')), + ('operating_system', models.ManyToManyField(blank=True, to='fossdb.operatingsystemversion')), + ('owner', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ], + ), + migrations.CreateModel( + name='Tag', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(db_index=True, max_length=100, unique=True)), + ('description', models.TextField(blank=True, default='')), + ('icon', models.ImageField(blank=True, null=True, upload_to='types/icons/')), + ], + ), + migrations.CreateModel( + name='ProjectProgrammingLanguage', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('percentage', models.PositiveIntegerField()), + ('programming_language', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='fossdb.programminglanguage')), + ('project', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='fossdb.project')), + ], + ), + migrations.CreateModel( + name='ProjectHostingPlatform', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('url', models.URLField(unique=True)), + ('hosting_platform', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='fossdb.hostingplatform')), + ('project', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='fossdb.project')), + ], + ), + migrations.AddField( + model_name='project', + name='tag', + field=models.ManyToManyField(blank=True, to='fossdb.tag'), + ), + ] diff --git a/FOSSDB/apps/fossdb/migrations/0002_project_proggramming_language.py b/FOSSDB/apps/fossdb/migrations/0002_project_proggramming_language.py new file mode 100644 index 0000000..bbfd090 --- /dev/null +++ b/FOSSDB/apps/fossdb/migrations/0002_project_proggramming_language.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2.2 on 2023-06-26 17:38 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('fossdb', '0001_initial'), + ] + + operations = [ + migrations.AddField( + model_name='project', + name='proggramming_language', + field=models.ManyToManyField(blank=True, through='fossdb.ProjectProgrammingLanguage', to='fossdb.programminglanguage'), + ), + ] diff --git a/FOSSDB/apps/fossdb/migrations/0003_rename_proggramming_language_project_programming_language.py b/FOSSDB/apps/fossdb/migrations/0003_rename_proggramming_language_project_programming_language.py new file mode 100644 index 0000000..ba7467c --- /dev/null +++ b/FOSSDB/apps/fossdb/migrations/0003_rename_proggramming_language_project_programming_language.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2.2 on 2023-06-26 17:43 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('fossdb', '0002_project_proggramming_language'), + ] + + operations = [ + migrations.RenameField( + model_name='project', + old_name='proggramming_language', + new_name='programming_language', + ), + ] diff --git a/FOSSDB/apps/fossdb/migrations/0004_remove_project_programming_language.py b/FOSSDB/apps/fossdb/migrations/0004_remove_project_programming_language.py new file mode 100644 index 0000000..aa9b3c5 --- /dev/null +++ b/FOSSDB/apps/fossdb/migrations/0004_remove_project_programming_language.py @@ -0,0 +1,17 @@ +# Generated by Django 4.2.2 on 2023-06-26 17:45 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('fossdb', '0003_rename_proggramming_language_project_programming_language'), + ] + + operations = [ + migrations.RemoveField( + model_name='project', + name='programming_language', + ), + ] diff --git a/FOSSDB/apps/fossdb/programming_language/models.py b/FOSSDB/apps/fossdb/programming_language/models.py index 7c62a0d..853b793 100644 --- a/FOSSDB/apps/fossdb/programming_language/models.py +++ b/FOSSDB/apps/fossdb/programming_language/models.py @@ -1,5 +1,4 @@ from django.db import models -from fossdb.models import Project class ProgrammingLanguage(models.Model): @@ -10,9 +9,9 @@ class ProgrammingLanguage(models.Model): class ProjectProgrammingLanguage(models.Model): - project = models.ForeignKey(Project, on_delete=models.CASCADE) + project = models.ForeignKey("Project", on_delete=models.CASCADE) programming_language = models.ForeignKey(ProgrammingLanguage, on_delete=models.CASCADE) percentage = models.PositiveIntegerField() def __str__(self): - return f"{self.project} | {self.programming_language} | {self.percentage}%" + return f"{self.project.owner}/{self.project.name} | {self.programming_language} | {self.percentage}%" diff --git a/FOSSDB/apps/fossdb/views.py b/FOSSDB/apps/fossdb/views.py index 5d8b5e7..ac25d58 100644 --- a/FOSSDB/apps/fossdb/views.py +++ b/FOSSDB/apps/fossdb/views.py @@ -1,12 +1,15 @@ from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin +from django.db import transaction from django.shortcuts import get_object_or_404, redirect, render from django.urls import reverse_lazy from django.views.generic import CreateView, DeleteView, DetailView, UpdateView from .forms import ProjectForm from .hosting_platform.forms import HostingPlatformForm +from .hosting_platform.models import ProjectHostingPlatform from .models import Project from .programming_language.forms import ProgrammingLanguageForm +from .programming_language.models import ProjectProgrammingLanguage def index(request): @@ -25,21 +28,23 @@ class ProjectCreateView(LoginRequiredMixin, CreateView): redirect_field_name = "redirect_to" def form_valid(self, form): - form.instance.owner = self.request.user - response = super().form_valid(form) + response = None + with transaction.atomic(): + form.instance.owner = self.request.user + response = super().form_valid(form) - hosting_platform_form = HostingPlatformForm(self.request.POST, instance=self.object) - if hosting_platform_form.is_valid(): - hosting_platform = hosting_platform_form.save(commit=False) - hosting_platform.project = self.object - hosting_platform.save() + hosting_platform_form = HostingPlatformForm(self.request.POST, instance=self.object) + if hosting_platform_form.is_valid(): + hosting_platform = hosting_platform_form.save(commit=False) + hosting_platform.project = self.object + hosting_platform.save() - # TODO: allow adding multiple languages - programming_language_form = ProgrammingLanguageForm(self.request.POST, instance=self.object) - if programming_language_form.is_valid(): - programming_language = programming_language_form.save(commit=False) - programming_language.project = self.object - programming_language.save() + # TODO: allow adding multiple languages + programming_language_form = ProgrammingLanguageForm(self.request.POST, instance=self.object) + if programming_language_form.is_valid(): + programming_language = programming_language_form.save(commit=False) + programming_language.project = self.object + programming_language.save() return response @@ -73,25 +78,6 @@ class ProjectUpdateView(LoginRequiredMixin, UserPassesTestMixin, UpdateView): login_url = "/login/" redirect_field_name = "redirect_to" - def form_valid(self, form): - form.instance.owner = self.request.user - response = super().form_valid(form) - - hosting_platform_form = HostingPlatformForm(self.request.POST, instance=self.object) - if hosting_platform_form.is_valid(): - hosting_platform = hosting_platform_form.save(commit=False) - hosting_platform.project = self.object - hosting_platform.save() - - # TODO: allow adding multiple languages - programming_language_form = ProgrammingLanguageForm(self.request.POST, instance=self.object) - if programming_language_form.is_valid(): - programming_language = programming_language_form.save(commit=False) - programming_language.project = self.object - programming_language.save() - - return response - def get_queryset(self): queryset = super().get_queryset() return queryset.filter(owner__username=self.kwargs.get("username")) diff --git a/templates/fossdb/detailed_view.html b/templates/fossdb/detailed_view.html index 9c097bb..b3ffc73 100644 --- a/templates/fossdb/detailed_view.html +++ b/templates/fossdb/detailed_view.html @@ -1,11 +1,14 @@ {% extends "layout.html" %} {% load static %} -{% block title %}{{ project.name }}{% endblock %} +{% block title %}{{ project.owner }}/{{ project.name }}{% endblock %} {% block meta %}{% endblock %} {% block content %} -

    @{{ project.owner.username }}

    -

    {{ project.name }}

    +

    @{{ project.owner }}

    +

    {{ project.name }}

    {{ project.description }}

    +

    + {{ project.projecthostingplatform.hosting_platform }} +

      {% for license in project.license.all %}
    • @@ -16,15 +19,8 @@ {% endfor %}
      - {% for language in project.programming_language.all %} -
    • {{ language }}%
    • - {% empty %} -

      No language

      - {% endfor %} -
    -
      - {% for os in project.oprating_system.all %} -
    • {{ os.version }}
    • + {% for os in project.operating_system.all %} +
    • {{ os }}
    • {% empty %}

      No OS

      {% endfor %} @@ -36,6 +32,13 @@

      No tag

      {% endfor %}
    +
      + {% for language in project.projectprogramminglanguage_set.all %} +
    • {{ language.programming_language }} {{ language.percentage }}%
    • + {% empty %} +

      No language

      + {% endfor %} +

    {{ project.date_created|date:"d.m.Y, G:i" }}


    {% for project in projects %} - @{{ project.owner }} -

    {{ project.name }}

    -
    - - - -

    {{ project.date_created }}

    +
    +

    + {{ project.owner }}/{{ project.name }} +

    +

    {{ project.description }}

    +
    {% empty %}

    No projects yet (

    {% endfor %} From ffa9827f4430f728d7584c51b2a944a7772e9c3c Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Tue, 27 Jun 2023 13:57:24 +0000 Subject: [PATCH 125/144] Modified `User` model Replaced `id` with `uuid` and added profile picture field --- FOSSDB/apps/account/admin.py | 19 ++++++++ FOSSDB/apps/account/forms.py | 3 +- .../apps/account/migrations/0001_initial.py | 45 ++++++++++++++++++ .../migrations/0002_customuser_profile_pic.py | 18 +++++++ .../0003_alter_customuser_profile_pic.py | 18 +++++++ .../0004_alter_customuser_profile_pic.py | 18 +++++++ ..._profile_pic_customuser_profile_picture.py | 18 +++++++ .../0006_alter_customuser_profile_picture.py | 18 +++++++ .../0007_alter_customuser_profile_picture.py | 20 ++++++++ .../migrations/0008_rename_customuser_user.py | 20 ++++++++ .../migrations/0009_rename_user_customuser.py | 20 ++++++++ .../migrations/0010_rename_customuser_user.py | 20 ++++++++ FOSSDB/apps/account/models.py | 42 ++++++++++++++++ FOSSDB/apps/account/urls.py | 1 + FOSSDB/apps/account/views.py | 13 ++++- FOSSDB/apps/fossdb/migrations/0001_initial.py | 2 +- FOSSDB/apps/fossdb/models.py | 4 +- FOSSDB/apps/fossdb/star/models.py | 4 +- FOSSDB/settings.py | 2 + FOSSDB/urls.py | 4 +- media/profile_pics/default.jpg | Bin 0 -> 52953 bytes templates/account/profile.html | 10 ++++ 22 files changed, 310 insertions(+), 9 deletions(-) create mode 100644 FOSSDB/apps/account/migrations/0001_initial.py create mode 100644 FOSSDB/apps/account/migrations/0002_customuser_profile_pic.py create mode 100644 FOSSDB/apps/account/migrations/0003_alter_customuser_profile_pic.py create mode 100644 FOSSDB/apps/account/migrations/0004_alter_customuser_profile_pic.py create mode 100644 FOSSDB/apps/account/migrations/0005_rename_profile_pic_customuser_profile_picture.py create mode 100644 FOSSDB/apps/account/migrations/0006_alter_customuser_profile_picture.py create mode 100644 FOSSDB/apps/account/migrations/0007_alter_customuser_profile_picture.py create mode 100644 FOSSDB/apps/account/migrations/0008_rename_customuser_user.py create mode 100644 FOSSDB/apps/account/migrations/0009_rename_user_customuser.py create mode 100644 FOSSDB/apps/account/migrations/0010_rename_customuser_user.py create mode 100644 media/profile_pics/default.jpg create mode 100644 templates/account/profile.html diff --git a/FOSSDB/apps/account/admin.py b/FOSSDB/apps/account/admin.py index e69de29..867f339 100644 --- a/FOSSDB/apps/account/admin.py +++ b/FOSSDB/apps/account/admin.py @@ -0,0 +1,19 @@ +from django.contrib import admin +from django.contrib.auth.admin import UserAdmin + +from .models import User + + +class CustomUserAdmin(UserAdmin): + model = User + fieldsets = UserAdmin.fieldsets + ( + ( + None, + { + "fields": ("profile_picture",), + }, + ), + ) + + +admin.site.register(User, CustomUserAdmin) diff --git a/FOSSDB/apps/account/forms.py b/FOSSDB/apps/account/forms.py index 80d92b6..149eafc 100644 --- a/FOSSDB/apps/account/forms.py +++ b/FOSSDB/apps/account/forms.py @@ -1,7 +1,8 @@ from django import forms from django.contrib.auth.forms import UserCreationForm -from django.contrib.auth.models import User + +from .models import User class SignUpForm(UserCreationForm): diff --git a/FOSSDB/apps/account/migrations/0001_initial.py b/FOSSDB/apps/account/migrations/0001_initial.py new file mode 100644 index 0000000..5fd38f4 --- /dev/null +++ b/FOSSDB/apps/account/migrations/0001_initial.py @@ -0,0 +1,45 @@ +# Generated by Django 4.2.2 on 2023-06-27 12:54 + +import django.contrib.auth.models +import django.contrib.auth.validators +from django.db import migrations, models +import django.utils.timezone +import uuid + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('auth', '0012_alter_user_first_name_max_length'), + ] + + operations = [ + migrations.CreateModel( + name='CustomUser', + fields=[ + ('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')), + ('email', models.EmailField(blank=True, max_length=254, verbose_name='email address')), + ('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')), + ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False, verbose_name='ID')), + ('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()), + ], + ), + ] diff --git a/FOSSDB/apps/account/migrations/0002_customuser_profile_pic.py b/FOSSDB/apps/account/migrations/0002_customuser_profile_pic.py new file mode 100644 index 0000000..63126a7 --- /dev/null +++ b/FOSSDB/apps/account/migrations/0002_customuser_profile_pic.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2.2 on 2023-06-27 13:02 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('account', '0001_initial'), + ] + + operations = [ + migrations.AddField( + model_name='customuser', + name='profile_pic', + field=models.ImageField(default='default.jpg', upload_to='profile_pics/'), + ), + ] diff --git a/FOSSDB/apps/account/migrations/0003_alter_customuser_profile_pic.py b/FOSSDB/apps/account/migrations/0003_alter_customuser_profile_pic.py new file mode 100644 index 0000000..10db396 --- /dev/null +++ b/FOSSDB/apps/account/migrations/0003_alter_customuser_profile_pic.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2.2 on 2023-06-27 13:28 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('account', '0002_customuser_profile_pic'), + ] + + operations = [ + migrations.AlterField( + model_name='customuser', + name='profile_pic', + field=models.BinaryField(blank=True), + ), + ] diff --git a/FOSSDB/apps/account/migrations/0004_alter_customuser_profile_pic.py b/FOSSDB/apps/account/migrations/0004_alter_customuser_profile_pic.py new file mode 100644 index 0000000..1b2c597 --- /dev/null +++ b/FOSSDB/apps/account/migrations/0004_alter_customuser_profile_pic.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2.2 on 2023-06-27 13:32 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('account', '0003_alter_customuser_profile_pic'), + ] + + operations = [ + migrations.AlterField( + model_name='customuser', + name='profile_pic', + field=models.BinaryField(blank=True, editable=True), + ), + ] diff --git a/FOSSDB/apps/account/migrations/0005_rename_profile_pic_customuser_profile_picture.py b/FOSSDB/apps/account/migrations/0005_rename_profile_pic_customuser_profile_picture.py new file mode 100644 index 0000000..1dee064 --- /dev/null +++ b/FOSSDB/apps/account/migrations/0005_rename_profile_pic_customuser_profile_picture.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2.2 on 2023-06-27 13:33 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('account', '0004_alter_customuser_profile_pic'), + ] + + operations = [ + migrations.RenameField( + model_name='customuser', + old_name='profile_pic', + new_name='profile_picture', + ), + ] diff --git a/FOSSDB/apps/account/migrations/0006_alter_customuser_profile_picture.py b/FOSSDB/apps/account/migrations/0006_alter_customuser_profile_picture.py new file mode 100644 index 0000000..1b959e4 --- /dev/null +++ b/FOSSDB/apps/account/migrations/0006_alter_customuser_profile_picture.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2.2 on 2023-06-27 13:34 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('account', '0005_rename_profile_pic_customuser_profile_picture'), + ] + + operations = [ + migrations.AlterField( + model_name='customuser', + name='profile_picture', + field=models.ImageField(default='profile_pic/default.jpg', upload_to='profile_pics/'), + ), + ] diff --git a/FOSSDB/apps/account/migrations/0007_alter_customuser_profile_picture.py b/FOSSDB/apps/account/migrations/0007_alter_customuser_profile_picture.py new file mode 100644 index 0000000..48f53d8 --- /dev/null +++ b/FOSSDB/apps/account/migrations/0007_alter_customuser_profile_picture.py @@ -0,0 +1,20 @@ +# Generated by Django 4.2.2 on 2023-06-27 13:43 + +import account.models +from django.db import migrations, models +import pathlib + + +class Migration(migrations.Migration): + + dependencies = [ + ('account', '0006_alter_customuser_profile_picture'), + ] + + operations = [ + migrations.AlterField( + model_name='customuser', + name='profile_picture', + field=models.ImageField(default=pathlib.PurePosixPath('profile_pic/default.jpg'), upload_to=account.models.get_profile_pic_path), + ), + ] diff --git a/FOSSDB/apps/account/migrations/0008_rename_customuser_user.py b/FOSSDB/apps/account/migrations/0008_rename_customuser_user.py new file mode 100644 index 0000000..25c325b --- /dev/null +++ b/FOSSDB/apps/account/migrations/0008_rename_customuser_user.py @@ -0,0 +1,20 @@ +# Generated by Django 4.2.2 on 2023-06-27 13:51 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('fossdb', '0001_initial'), + ('auth', '0012_alter_user_first_name_max_length'), + ('admin', '0003_logentry_add_action_flag_choices'), + ('account', '0007_alter_customuser_profile_picture'), + ] + + operations = [ + migrations.RenameModel( + old_name='CustomUser', + new_name='User', + ), + ] diff --git a/FOSSDB/apps/account/migrations/0009_rename_user_customuser.py b/FOSSDB/apps/account/migrations/0009_rename_user_customuser.py new file mode 100644 index 0000000..e853ebd --- /dev/null +++ b/FOSSDB/apps/account/migrations/0009_rename_user_customuser.py @@ -0,0 +1,20 @@ +# Generated by Django 4.2.2 on 2023-06-27 13:53 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('fossdb', '0001_initial'), + ('auth', '0012_alter_user_first_name_max_length'), + ('admin', '0003_logentry_add_action_flag_choices'), + ('account', '0008_rename_customuser_user'), + ] + + operations = [ + migrations.RenameModel( + old_name='User', + new_name='CustomUser', + ), + ] diff --git a/FOSSDB/apps/account/migrations/0010_rename_customuser_user.py b/FOSSDB/apps/account/migrations/0010_rename_customuser_user.py new file mode 100644 index 0000000..31d690b --- /dev/null +++ b/FOSSDB/apps/account/migrations/0010_rename_customuser_user.py @@ -0,0 +1,20 @@ +# Generated by Django 4.2.2 on 2023-06-27 13:55 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('admin', '0003_logentry_add_action_flag_choices'), + ('auth', '0012_alter_user_first_name_max_length'), + ('fossdb', '0001_initial'), + ('account', '0009_rename_user_customuser'), + ] + + operations = [ + migrations.RenameModel( + old_name='CustomUser', + new_name='User', + ), + ] diff --git a/FOSSDB/apps/account/models.py b/FOSSDB/apps/account/models.py index e69de29..1cf7561 100644 --- a/FOSSDB/apps/account/models.py +++ b/FOSSDB/apps/account/models.py @@ -0,0 +1,42 @@ +import uuid +from pathlib import Path + +from django.contrib.auth.models import AbstractUser +from django.core.exceptions import ObjectDoesNotExist +from django.db import models + + +def get_profile_pic_path(instance, filename) -> Path: + ext = filename.split(".")[-1] + filename = f"{instance.id}.{ext}" + return Path("profile_pics", filename) + + +class User(AbstractUser): + id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False, verbose_name="ID") + profile_picture = models.ImageField(upload_to=get_profile_pic_path, default=Path("profile_pic", "default.jpg")) + + @property + def full_name(self): + if not self.first_name and not self.last_name: + return "" + elif self.first_name and not self.last_name: + return self.first_name + elif not self.first_name and self.last_name: + return self.last_name + else: + return f"{self.first_name} {self.last_name}" + + def save(self, *args, **kwags): + old_instance = None + if self.pk: + try: + old_instance = User.objects.get(pk=self.pk) + except ObjectDoesNotExist: + pass + super(User, self).save(*args, **kwags) + + # Check if old instance exists and profile picture is different + if old_instance is not None: + if old_instance.profile_picture and self.profile_picture and old_instance.profile_picture.url != self.profile_picture.url: + old_instance.profile_picture.delete(save=False) diff --git a/FOSSDB/apps/account/urls.py b/FOSSDB/apps/account/urls.py index f060b68..c812fd2 100644 --- a/FOSSDB/apps/account/urls.py +++ b/FOSSDB/apps/account/urls.py @@ -5,4 +5,5 @@ from . import views urlpatterns = [ path("signup/", views.signup_view, name="signup"), path("login/", views.login_view, name="login"), + path("/", views.profile, name="profile"), ] diff --git a/FOSSDB/apps/account/views.py b/FOSSDB/apps/account/views.py index 179216d..873c458 100644 --- a/FOSSDB/apps/account/views.py +++ b/FOSSDB/apps/account/views.py @@ -1,8 +1,19 @@ from django.contrib.auth import authenticate, login from django.contrib.auth.forms import AuthenticationForm -from django.shortcuts import redirect, render +from django.shortcuts import get_object_or_404, redirect, render from .forms import SignUpForm +from .models import User + + +def profile(request, username): + user = get_object_or_404(User, username=username) + + context = { + "title": user.username + ("" if not user.full_name else f" ({user.full_name})"), + "user": user, + } + return render(request, "account/profile.html", context) def signup_view(request): diff --git a/FOSSDB/apps/fossdb/migrations/0001_initial.py b/FOSSDB/apps/fossdb/migrations/0001_initial.py index e0946dc..fc86c22 100644 --- a/FOSSDB/apps/fossdb/migrations/0001_initial.py +++ b/FOSSDB/apps/fossdb/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 4.2.2 on 2023-06-27 10:33 +# Generated by Django 4.2.2 on 2023-06-27 12:54 from django.conf import settings from django.db import migrations, models diff --git a/FOSSDB/apps/fossdb/models.py b/FOSSDB/apps/fossdb/models.py index 7233a15..5e0f71e 100644 --- a/FOSSDB/apps/fossdb/models.py +++ b/FOSSDB/apps/fossdb/models.py @@ -1,6 +1,6 @@ import uuid -from django.contrib.auth.models import User +from django.conf import settings from django.db import models @@ -12,7 +12,7 @@ from .tag.models import Tag class Project(models.Model): id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False, verbose_name="ID") - owner = models.ForeignKey(User, on_delete=models.CASCADE) + owner = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE) name = models.CharField(max_length=255) description = models.TextField(blank=True, default="") license = models.ManyToManyField(License, blank=True) diff --git a/FOSSDB/apps/fossdb/star/models.py b/FOSSDB/apps/fossdb/star/models.py index 74f0452..cfa2034 100644 --- a/FOSSDB/apps/fossdb/star/models.py +++ b/FOSSDB/apps/fossdb/star/models.py @@ -1,9 +1,7 @@ from django.conf import settings from django.db import models -User = settings.AUTH_USER_MODEL - class Star(models.Model): - user = models.ForeignKey(User, on_delete=models.CASCADE) + user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE) project = models.ForeignKey("Project", on_delete=models.CASCADE, related_name="stars") diff --git a/FOSSDB/settings.py b/FOSSDB/settings.py index dbdf365..9e80206 100644 --- a/FOSSDB/settings.py +++ b/FOSSDB/settings.py @@ -75,6 +75,8 @@ TEMPLATES = [ WSGI_APPLICATION = "FOSSDB.wsgi.application" +AUTH_USER_MODEL = "account.User" + # Database # https://docs.djangoproject.com/en/4.0/ref/settings/#databases diff --git a/FOSSDB/urls.py b/FOSSDB/urls.py index 6618184..d5c0637 100644 --- a/FOSSDB/urls.py +++ b/FOSSDB/urls.py @@ -21,8 +21,10 @@ from django.urls import include, path urlpatterns = [ path("", include("fossdb.urls")), path("", include("account.urls")), + # path("", include("django.contrib.auth.urls")), path("admin/", admin.site.urls), - path("", include("django.contrib.auth.urls")), ] urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) +if settings.DEBUG: + urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) diff --git a/media/profile_pics/default.jpg b/media/profile_pics/default.jpg new file mode 100644 index 0000000000000000000000000000000000000000..82ff366b18839d1c3696b16f201bac44aef7f137 GIT binary patch literal 52953 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%0A_e(1X67R4)=85;9f_+EHrh zAbcs}5Y8)#^}x$7ceI9Fe!s3%Dd;X`1_A-GO+S1p`DfzLvz|FU_a(7>uwHc5>O`Kr zot8;k{xH=}Vn^E8K^|;cu)UG^;ExImF<}jP|75^HYwBQaN7?;intZLqYus|?DkzhK z!FnPc!%tt4h~LhtjNRgr<^=UvU%Re{`Q}v*m)wM7)V+hnKjnmUV9Mj+WNf;J8@9hJ zJ$3~x!;$RefceGKj_=oO>8;&V@-TV0f3PlKWd;?XeC1QY_lYB4?!p7y^4XuF_lrc2y4wx=wVwMf(QN#p##~=REZc4U9tnX%xS$)fW+Jx3V{> zgu=sHSLH5GYk2YP)NMyNq%AO{D;};pCja2wYA9-N!pW&r)|!}b_x3?;KIOjr-FN$? z2P3B6_{%@=Wl;5~;K`Ubb_+k1Oi*2}fPB(&lk;qPc*4q)DRw>JRFXek==NeNUS*&kV&Kq?ZPYdfehPB$kf4uQF|*$M9O_WfwCfD?>hPtOaSM%t`O-@! zbbnG?SaVV87z9}7)L!nh1!p_axvoTU{dDJJ(GT~+;(|vS;y*||PSVAG_k2w2c+#%G zjMhGz$3EMpYEG}p?nPB`CTB9R>$qom?_gPu8>2ZUad`se>%0$kvπyWHDV=0nXJ z?QNY+EAbJgvYA9CRmb2`{z6A@z6ANyw|oaH_>?;`1d7v?Y@bNyruyjFKy=K!>NENu za>d*tJA8e*-PGb)gLP$EgaYT288O?u86II9tmh$Jj%4l?!RJJP(Pto1YjcNwe63)5 zs6k~^(W!zPQNNQPwV-rX!N|ESF%z7u;7ZiaLz(+F={K6x0V`Q~qQ{+2s=QAe>+bi| zRKdph%%-oc)*I5UtgF|BQ6{>y;g^fb8?00lH=J-+DW=pEbY}O1cRh0FM-G<%lmp#Y z51vB`aKA0)m$&(kj&_&6YC7Jl5KfH z^{hHD{ed!qn_Ao)1e~68yXC;5zi^kX6M#v_&G~gtK%ci!u75WQ@b-4n`zeaA!uav z&6V*u`n4$y|GUY$Pu?9U|0#1ccUQDVAq23R3DX=VPqVCM?1kjo$@f;XI+!i&6w7MX zq2$HBHJ)iwrmx@q`=_#hCQjpI#(h&psqnzWYO<>w0EoHM=oKFxALR@nV#=nvh=$SR z3kvXDr?`Mk;1w_W92XQ%Sz513O;>K@*Mj4805og=O6jsGQ`*S{2#p0L^x?aK-yIZn zLSor3V_Se@N&WH4e2HAi+HmdgZ*R%Gf(3!Mj!Cp4@@iZh9`&a3%nOV6lWv|mkw-js z>|hNabLV8_S~jg(W1amU@;5T;E9h!bZeMG)#qSKNn3q$q-Bb-3s1e^!wXM8lYPLNLd8g%w;57`&zqfARyhUX$w znjdve2hW7BRT)1ck*A{s#qqF*D@6ei#|q=r72~k{{j59t(`jUf+P#t>?selP}8y%ju9&C(q>v z$t23~bjiYI3e8fGx6@Z%_9+aU*MK%QKPc!!?zAx;S~|K=!gBF54sHZ7ST26fE^ckr zLo63R(e%M=z{StO!S>$-!9lePg^RR|I=}3s+(_n03lPmGQCq6Tx`TQu#<9-K()>9U zUzm=b$jgJ$=l_QC_pc}G8q-5#DnrI}qjX~fYR5*+s4kaj#AR6fZ`H9B!!kqh)`zYE z=1v>-7(p?M%fIr3t_4mr&yR7wjy{S!Tk>Q62a&Ut~t$eCPxiz{Tap5PY_%QRN zgb)RgEzipr2O9`1fpaw*LLP%2+xf&r(Lk_$wj&$NeYOV}7f0Y<#E->xlw9UWnoE{g zo@`PmFiCtzSv@53bgNDYLck_Iv#F^yDG4}q5asqu9mWzXWy%)I%xfZ3u0EJxDr_}a zilCHjRUWwd`1(1ZeEqZPho_QmmqLVJ(_bE{@z1O)`sy4I^FCj!-m^w~INoJU{mr32 zG_oPO9bUHQ;<^SwT(&y{cDZ-$de(WztU&%?S2wL+%Ahgxv`whA z0?XgDwgZ(2#4raL$`bPS%)?X;Z&ttfkpSU9V%mbD`#lU#%@`YLm_^&!A>Nb?emg!3 zM^x73m0dFcX(oAgVNp%Oq-_&+b^ydtae7#WYgEfnMJ-RRh#(#_F@MgJJJ~jEj;U^O z!9sith!KR+C-`_A_%sTr-yLe^SHa766_Li%f$DM3`updISC@(9lZj?v1;n7_E$wlo zgboHcWEzs>9p;_gvhirw0i&E!4;T&;vqoJ?S%$+w7K}0gtfSf1%Ysn`42N82@SMP; zA)a(d)cdTo<=n#|tQN3efNUDZxgFd69RBG=f z1kxU{@B{YE;fj7F1X$G~I%{+0gJ+StN@kOu8im)2)JmU{?`t_47%GyOM*efsAe4cD z;kBkFJw7&u+?%>u%hw#7t<_7|$dsQ{#qzn_BOv;DBaf#{D>4R8kewzy^aaQGfx6<9J|s@R0LQ)8Kj}WC zxhQ9S?{FPJ{y6WTkaMl^3?r2*eWUzcgLurt#C9w#TSz!nV5UwjMgY0daJk%}Iq4DQ zTvmO9V(Aiq0sw?$u}}b3SRq+vEEE7!R!G)!77D-#00{M)5>DVcc6jH>W~16FLjer0 zp`IK8H8~QCe*AsYi>tI|9T#j`phdq$UoylREZ$_G4eXNaHgT%IA6eSN!t}9EH?o@e zWxe=M;dmpeD1MRVnTvaUb++U!;e5t8NPHIV?yi-bwcCF2Q2V}^9dIchMx9JIrozH; zKc^Z@PTL}0CEk3GScz~y1FR3^BzolJ6abvyn|gk*GPhd0`35-G)&>*>x7qV)Ro?cw zh+b03Blb(h(Ug0aR|s$7Ks?>rmZluShh(v`%5KTt^q6(WXBr{dBl=-@mp1(TA5YSy zoaZ)h-9Cgf>V@E(@&rZ6zzlW&9rn>h>JyZErSW5DHF&E$Xmg={Rbj&<3dXbGCFSlS z>;D6=$J2h00IWq~VfC6hS%(FF!5{o&^aeI{Ba4{B<-xa$yY$GPayreNumqZ}L)_Yq ziPwBimZet~7h^hJ?S%@nv5PUZe1!Jd9t*}ex`i-`FZR*)sQYXLA?4)+-hH;l{+`r* zwsPK`8&Zd@K5SmW;|zgT_3$~+Y}QEh)=TDA(SktiL_fM_p<{?IpY{;bxT&vIkf{W* z_>HzK|0BT1QWMm!cC)*3^y>5gm17v=Xn8+IB0<`hg~C$ILSf;ed_rNdINUTKUp@9m ztvaEiNHn=)yU~u?tqReUOa?ny7U8%ZEUwUMgrVsv;G%fV{FBDU&S%})`fP`{a{VOG%tph zW&2*RYWkl0>Tc^u&UU%hFL?0^TialtmC4qbyC$AX_YNx@H9Ef$-povR1GRKL`E~0& zui%U7tvz4)ejbO8d^K8eqCF(Lm41TM^RAZI#OTaLh`Ii^=m4KZe&Gl=mTC8{N`VP^ zj^1ptT1@apFY}P6?9{~Sxo0H1t6j~vr9;e1F@i1@L$$WhK@dOJ=h7ciCv+HLK$9~z zVZ?@hFUEDt<~lr z=peFtW>+TS=a>~y9EXuIK!B6klq|ulw*r85T>u& z3V&Q)?-8uj&I7g=eN@!YMg*O+$pnsbaWC5L9n$ZM)3tL8aOj9&>E6>dDlaemb$YPY z?2V*6?Ds}4<9Dlbnq;mOT%-E%I!Vb%0p8^* zlW|ZQ!Jy)I~7t(Mr#o(*`Q^d)UAQ{4*@-8Vk z;Ih^pk(nilTLESS_kpd5#Y4s$pfh zu7pz%rLBGT6`KrhF6XuEBGp;#Jo~CIRJBe|T>*oDr8*KSGn?0>jieP;#6ZTH23$1S zN=H**9;xHb;Rb&7-Ew|Oy)1mqY@I)Qh=dHerS!Oo(SIDQ@gQ`cZT%dV!ink=gmJi5 zgRlg?1Ldxx$@+DQ{WsVZpG5L}IUsvSp>q=2Z(Kc>$y5SWTZLc{;*%AaF;-vJ@^0#z zX-x*7?0Ls%-bhwZ0NH;k`Z4j9IU`~H_?D2f`p8Mws05IsYk)%8aVW- zM~gdYtN(S6AiBW>ih;U+Tgt|k4xD$6Jqf-~H@Cd+UA@^3bdpI>o2oAS0S)KJe|hs8dA>st;>KU>z1q`V<4tj-s@zKiXS-gs)* zv6T@102+3eaq4ekzYwTxUD%B9Giu6ji11iHzkDOQ@9m}x{%zm3BU7W;Ji*o1!6`f} zA$Krc*ruRp$b%-NyS@4S_Kcq~BkEb2H1?uSxq00G6&dtc4zyspvcaMK ztCEt+l`8G67Ei=eBF=P?$eiq)0G7lz7RB}iW!`+4w~-q$-WH|GrwP);fj}8l z9jAtwq|i!<%4G1b8%5P7G1e_9L%CyrYaH8Y9OzA8R)|GSA1Uw&a!~nZ!_ctXNyJUC zirGD^WK&*qe#iA}HPbjb=^2OvG#ilv`0^ed-_>GdVfth!SAEF73a(enxtj6wt=U7A z#Kus49`p_qZ`&muNtAD(DC!l5>%@HbH@T{t7J;XG_Xr*aTR79LF6BTap1#oM7Cm0& z(W`jn396*@tspZil3sks4`ya?NyXh!6MLBPVxpsJM>Pr`+MwwtE7nMZ_h~&S@|gZxGq-y4C6yRzYap!EPGvzjRT;X?TX;5wQBW#r zDP2McSq4lXf)tB|$GU6oyvK(e9W_puYsv(Z#*- zqBm1Chpd|)I3-#1HvEGj>|eBXw)q4t19kHmUY)9*=hKQIi02Y**~4dMNf3hxkd|O{ zRY|-p-cYvOg==w!^BG`hI{GtOM6HA&gk2qra;5KjRP&s0^KlApeQ$u1DT?%cZ-5g> zcHrY;UwII^nvn3fo@ER8Ka;F{u~aGOB#-*6}NL2ecFGccB_KJn_+aHjQ?N;l7?&q(5~@sm=_Dox75+#ogC2X(qi4 zqG;DOdrS~4c?QasaNhm*)^eiAO@SUw)IF8BA878Tn1NzDeja@|^FK zA4|qh@Q4%pfoE`PGDE<8bWJ7yykp)-a6Ca0Gt*45>wb!+DCC>P=;1Q~|JXrf$VI8r zAg1gC^CZSeiYv>0A~tLE{5`W2;BaCsO=N}THHya9kn%I7ni{o9z+5c&+uv361iev* zzFqbVyxYId{{4z;-j*3}NTEgU(4?6qUgt)TNDx>{v_wfmKA_ZsN06IR7?j8eSdXY2 z;h9#8NK9YRNfldskn{C)`-`F);r?0$KFx^~0(+f#g?S8jK&eZj&fVvK5&C7}+OhJY zl1-5+CP(_ppb_$x^R#<~Btosutng-bW&O?iLR@Sy_eCYFAV1~Ixr{z0a^YA;JzI0r z@S;yr+Hi`UJ?Pr109GikM@!V*(9RY=2s>r1m7iXs7r=I{@iFuL+9hSD1#XP#zG$O9$#a8y{CHa+wk$3Eq zn1PZQtC1~9iwc24Q;E(S+@x1{&=@^zaZy^DUFxG=f4P6o!97-%FI_RinswZ3t%o+U z7FVqF6S90hEhJY#7rW0k*wkss?Z9N$C`8(CmkwWAf1th3rn)VN0t?Fg_^~(sa{q!~ z{r&>i@99CzQR-Xx0!F%hTY6XZX`%D>vU_~}YRNv^%eIY*<=EDDiCP)Or03sRm!q%L z{xVm-Is1;Uq$WHgJ5^p>1jZf(Kn+?bTpu4;C6UPX!ar^*=!8T{l@>HbVeyEkg9sL_ zL)xhaM>pQnI`qLXo{B752iC$Fpmks^oIeG-9sjbYsHrxd<|g(v?fXCW*{-eZK1|5> zA=ECEB#R|g)IzGm+bZ%e#GV<-^G9@zq=7-(%MK4AkrfA3YugSQ+#`TNxgGvN9Yx zb^o*HE*He8$VTrBdRRr8&bDr6xjW{B|t0V2Y87+(R~$UO61 z=eLy{^Py&TP+uk(T-_64RDKH*7~CzBN1@7|NIveVO{z>XPjU!H0|Cds{7f850w6ec>mUiiO+t7m#T|4j_F&8#6kkW93p5*O`2|(~SJJ$8+LR zRB+jxyV~GSCslUj%PHd(lL9DFXT0_>+V3K%FdDE8Rs^_c$hPF4xIUJL*Lu zt^dK2wk)8zU{_O=u?V*e?djZjREK(WiP$lfw3wSO;OYdAYcZ5g$O|m1Gfj|h(wkl- za>>+KuKi5zkFa*MU=$|D#JDL%IMha%mSuzVI+-ewb&mt8#gcIL%)l7|V8@kYqHI`{ z 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 user.username }} + {{ user.username }}’s profile picture +

    {{ user.email }}

    +{% endblock %} From 9019c76d5a6bfb50a92058f983980d0c76f3fd3b Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Tue, 27 Jun 2023 14:03:09 +0000 Subject: [PATCH 126/144] Fix typo --- FOSSDB/apps/account/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FOSSDB/apps/account/models.py b/FOSSDB/apps/account/models.py index 1cf7561..46ed42e 100644 --- a/FOSSDB/apps/account/models.py +++ b/FOSSDB/apps/account/models.py @@ -14,7 +14,7 @@ def get_profile_pic_path(instance, filename) -> Path: class User(AbstractUser): id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False, verbose_name="ID") - profile_picture = models.ImageField(upload_to=get_profile_pic_path, default=Path("profile_pic", "default.jpg")) + profile_picture = models.ImageField(upload_to=get_profile_pic_path, default=Path("profile_pics", "default.jpg")) @property def full_name(self): From 6759ff4b580d75400c54a0a026a21611fa129d2b Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Wed, 28 Jun 2023 02:27:46 +0000 Subject: [PATCH 127/144] Some changes --- .gitignore | 2 + .../apps/account/migrations/0001_initial.py | 6 +- .../migrations/0002_customuser_profile_pic.py | 18 ---- .../0003_alter_customuser_profile_pic.py | 18 ---- .../0004_alter_customuser_profile_pic.py | 18 ---- ..._profile_pic_customuser_profile_picture.py | 18 ---- .../0006_alter_customuser_profile_picture.py | 18 ---- .../0007_alter_customuser_profile_picture.py | 20 ---- .../migrations/0008_rename_customuser_user.py | 20 ---- .../migrations/0009_rename_user_customuser.py | 20 ---- .../migrations/0010_rename_customuser_user.py | 20 ---- FOSSDB/apps/account/models.py | 2 +- FOSSDB/apps/fossdb/admin.py | 5 +- FOSSDB/apps/fossdb/filters.py | 28 +++++ FOSSDB/apps/fossdb/hosting_platform/forms.py | 2 +- FOSSDB/apps/fossdb/migrations/0001_initial.py | 12 ++- .../fossdb/migrations/0002_alter_tag_icon.py | 18 ++++ ...r_projectprogramminglanguage_percentage.py | 18 ++++ FOSSDB/apps/fossdb/models.py | 17 ++- FOSSDB/apps/fossdb/operating_system/models.py | 11 ++ .../fossdb/programming_language/models.py | 2 +- FOSSDB/apps/fossdb/urls.py | 4 +- FOSSDB/apps/fossdb/views.py | 101 +++++++++--------- FOSSDB/settings.py | 1 + FOSSDB/urls.py | 7 +- templates/fossdb/add_project.html | 14 --- templates/fossdb/create_view.html | 34 ++++++ templates/fossdb/detailed_view.html | 1 - templates/fossdb/index.html | 14 ++- templates/fossdb/update_view.html | 12 --- 30 files changed, 213 insertions(+), 268 deletions(-) delete mode 100644 FOSSDB/apps/account/migrations/0002_customuser_profile_pic.py delete mode 100644 FOSSDB/apps/account/migrations/0003_alter_customuser_profile_pic.py delete mode 100644 FOSSDB/apps/account/migrations/0004_alter_customuser_profile_pic.py delete mode 100644 FOSSDB/apps/account/migrations/0005_rename_profile_pic_customuser_profile_picture.py delete mode 100644 FOSSDB/apps/account/migrations/0006_alter_customuser_profile_picture.py delete mode 100644 FOSSDB/apps/account/migrations/0007_alter_customuser_profile_picture.py delete mode 100644 FOSSDB/apps/account/migrations/0008_rename_customuser_user.py delete mode 100644 FOSSDB/apps/account/migrations/0009_rename_user_customuser.py delete mode 100644 FOSSDB/apps/account/migrations/0010_rename_customuser_user.py create mode 100644 FOSSDB/apps/fossdb/filters.py create mode 100644 FOSSDB/apps/fossdb/migrations/0002_alter_tag_icon.py create mode 100644 FOSSDB/apps/fossdb/migrations/0003_alter_projectprogramminglanguage_percentage.py delete mode 100644 templates/fossdb/add_project.html create mode 100644 templates/fossdb/create_view.html delete mode 100644 templates/fossdb/update_view.html diff --git a/.gitignore b/.gitignore index 370e58e..a4081bc 100644 --- a/.gitignore +++ b/.gitignore @@ -135,3 +135,5 @@ debug /static/admin/ /static/fontawesomefree/ config.json +/media/profile_pics/* +!/media/profile_pics/default.jpg diff --git a/FOSSDB/apps/account/migrations/0001_initial.py b/FOSSDB/apps/account/migrations/0001_initial.py index 5fd38f4..5b6cc36 100644 --- a/FOSSDB/apps/account/migrations/0001_initial.py +++ b/FOSSDB/apps/account/migrations/0001_initial.py @@ -1,5 +1,6 @@ -# Generated by Django 4.2.2 on 2023-06-27 12:54 +# Generated by Django 4.2.2 on 2023-06-27 16:35 +import account.models import django.contrib.auth.models import django.contrib.auth.validators from django.db import migrations, models @@ -17,7 +18,7 @@ class Migration(migrations.Migration): operations = [ migrations.CreateModel( - name='CustomUser', + name='User', fields=[ ('password', models.CharField(max_length=128, verbose_name='password')), ('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')), @@ -30,6 +31,7 @@ class Migration(migrations.Migration): ('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')), ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False, verbose_name='ID')), + ('profile_picture', models.ImageField(default='profile_pics/default.jpg', upload_to=account.models.get_profile_pic_path)), ('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')), ], diff --git a/FOSSDB/apps/account/migrations/0002_customuser_profile_pic.py b/FOSSDB/apps/account/migrations/0002_customuser_profile_pic.py deleted file mode 100644 index 63126a7..0000000 --- a/FOSSDB/apps/account/migrations/0002_customuser_profile_pic.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 4.2.2 on 2023-06-27 13:02 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('account', '0001_initial'), - ] - - operations = [ - migrations.AddField( - model_name='customuser', - name='profile_pic', - field=models.ImageField(default='default.jpg', upload_to='profile_pics/'), - ), - ] diff --git a/FOSSDB/apps/account/migrations/0003_alter_customuser_profile_pic.py b/FOSSDB/apps/account/migrations/0003_alter_customuser_profile_pic.py deleted file mode 100644 index 10db396..0000000 --- a/FOSSDB/apps/account/migrations/0003_alter_customuser_profile_pic.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 4.2.2 on 2023-06-27 13:28 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('account', '0002_customuser_profile_pic'), - ] - - operations = [ - migrations.AlterField( - model_name='customuser', - name='profile_pic', - field=models.BinaryField(blank=True), - ), - ] diff --git a/FOSSDB/apps/account/migrations/0004_alter_customuser_profile_pic.py b/FOSSDB/apps/account/migrations/0004_alter_customuser_profile_pic.py deleted file mode 100644 index 1b2c597..0000000 --- a/FOSSDB/apps/account/migrations/0004_alter_customuser_profile_pic.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 4.2.2 on 2023-06-27 13:32 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('account', '0003_alter_customuser_profile_pic'), - ] - - operations = [ - migrations.AlterField( - model_name='customuser', - name='profile_pic', - field=models.BinaryField(blank=True, editable=True), - ), - ] diff --git a/FOSSDB/apps/account/migrations/0005_rename_profile_pic_customuser_profile_picture.py b/FOSSDB/apps/account/migrations/0005_rename_profile_pic_customuser_profile_picture.py deleted file mode 100644 index 1dee064..0000000 --- a/FOSSDB/apps/account/migrations/0005_rename_profile_pic_customuser_profile_picture.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 4.2.2 on 2023-06-27 13:33 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('account', '0004_alter_customuser_profile_pic'), - ] - - operations = [ - migrations.RenameField( - model_name='customuser', - old_name='profile_pic', - new_name='profile_picture', - ), - ] diff --git a/FOSSDB/apps/account/migrations/0006_alter_customuser_profile_picture.py b/FOSSDB/apps/account/migrations/0006_alter_customuser_profile_picture.py deleted file mode 100644 index 1b959e4..0000000 --- a/FOSSDB/apps/account/migrations/0006_alter_customuser_profile_picture.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 4.2.2 on 2023-06-27 13:34 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('account', '0005_rename_profile_pic_customuser_profile_picture'), - ] - - operations = [ - migrations.AlterField( - model_name='customuser', - name='profile_picture', - field=models.ImageField(default='profile_pic/default.jpg', upload_to='profile_pics/'), - ), - ] diff --git a/FOSSDB/apps/account/migrations/0007_alter_customuser_profile_picture.py b/FOSSDB/apps/account/migrations/0007_alter_customuser_profile_picture.py deleted file mode 100644 index 48f53d8..0000000 --- a/FOSSDB/apps/account/migrations/0007_alter_customuser_profile_picture.py +++ /dev/null @@ -1,20 +0,0 @@ -# Generated by Django 4.2.2 on 2023-06-27 13:43 - -import account.models -from django.db import migrations, models -import pathlib - - -class Migration(migrations.Migration): - - dependencies = [ - ('account', '0006_alter_customuser_profile_picture'), - ] - - operations = [ - migrations.AlterField( - model_name='customuser', - name='profile_picture', - field=models.ImageField(default=pathlib.PurePosixPath('profile_pic/default.jpg'), upload_to=account.models.get_profile_pic_path), - ), - ] diff --git a/FOSSDB/apps/account/migrations/0008_rename_customuser_user.py b/FOSSDB/apps/account/migrations/0008_rename_customuser_user.py deleted file mode 100644 index 25c325b..0000000 --- a/FOSSDB/apps/account/migrations/0008_rename_customuser_user.py +++ /dev/null @@ -1,20 +0,0 @@ -# Generated by Django 4.2.2 on 2023-06-27 13:51 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('fossdb', '0001_initial'), - ('auth', '0012_alter_user_first_name_max_length'), - ('admin', '0003_logentry_add_action_flag_choices'), - ('account', '0007_alter_customuser_profile_picture'), - ] - - operations = [ - migrations.RenameModel( - old_name='CustomUser', - new_name='User', - ), - ] diff --git a/FOSSDB/apps/account/migrations/0009_rename_user_customuser.py b/FOSSDB/apps/account/migrations/0009_rename_user_customuser.py deleted file mode 100644 index e853ebd..0000000 --- a/FOSSDB/apps/account/migrations/0009_rename_user_customuser.py +++ /dev/null @@ -1,20 +0,0 @@ -# Generated by Django 4.2.2 on 2023-06-27 13:53 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('fossdb', '0001_initial'), - ('auth', '0012_alter_user_first_name_max_length'), - ('admin', '0003_logentry_add_action_flag_choices'), - ('account', '0008_rename_customuser_user'), - ] - - operations = [ - migrations.RenameModel( - old_name='User', - new_name='CustomUser', - ), - ] diff --git a/FOSSDB/apps/account/migrations/0010_rename_customuser_user.py b/FOSSDB/apps/account/migrations/0010_rename_customuser_user.py deleted file mode 100644 index 31d690b..0000000 --- a/FOSSDB/apps/account/migrations/0010_rename_customuser_user.py +++ /dev/null @@ -1,20 +0,0 @@ -# Generated by Django 4.2.2 on 2023-06-27 13:55 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('admin', '0003_logentry_add_action_flag_choices'), - ('auth', '0012_alter_user_first_name_max_length'), - ('fossdb', '0001_initial'), - ('account', '0009_rename_user_customuser'), - ] - - operations = [ - migrations.RenameModel( - old_name='CustomUser', - new_name='User', - ), - ] diff --git a/FOSSDB/apps/account/models.py b/FOSSDB/apps/account/models.py index 46ed42e..a4164e6 100644 --- a/FOSSDB/apps/account/models.py +++ b/FOSSDB/apps/account/models.py @@ -14,7 +14,7 @@ def get_profile_pic_path(instance, filename) -> Path: class User(AbstractUser): id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False, verbose_name="ID") - profile_picture = models.ImageField(upload_to=get_profile_pic_path, default=Path("profile_pics", "default.jpg")) + profile_picture = models.ImageField(upload_to=get_profile_pic_path, default="profile_pics/default.jpg") @property def full_name(self): diff --git a/FOSSDB/apps/fossdb/admin.py b/FOSSDB/apps/fossdb/admin.py index ed62fd0..9fd82e2 100644 --- a/FOSSDB/apps/fossdb/admin.py +++ b/FOSSDB/apps/fossdb/admin.py @@ -20,7 +20,10 @@ class ProjectHostingPlatformInline(admin.TabularInline): class ProjectAdmin(admin.ModelAdmin): inlines = [ProjectHostingPlatformInline, ProjectProgrammingLanguageInline] - list_display = ("name", "owner", "_languages") + list_display = ( + "name", + "owner", + ) def _languages(self, object): return " | ".join([i.programming_language.name for i in object.projectprogramminglanguage_set.all()]) diff --git a/FOSSDB/apps/fossdb/filters.py b/FOSSDB/apps/fossdb/filters.py new file mode 100644 index 0000000..cc81ca6 --- /dev/null +++ b/FOSSDB/apps/fossdb/filters.py @@ -0,0 +1,28 @@ +import django_filters +from django.contrib.auth import get_user_model + +from .models import Project + +User = get_user_model() + + +class UserFilter(django_filters.FilterSet): + username = django_filters.CharFilter(lookup_expr="icontains") + + class Meta: + model = User + fields = ("username",) + + +class ProjectFilter(django_filters.FilterSet): + owner = UserFilter() + name = django_filters.CharFilter(lookup_expr="icontains") + description = django_filters.CharFilter(lookup_expr="icontains") + + class Meta: + model = Project + fields = ( + "owner", + "name", + "description", + ) diff --git a/FOSSDB/apps/fossdb/hosting_platform/forms.py b/FOSSDB/apps/fossdb/hosting_platform/forms.py index f4ab0f0..2f69d24 100644 --- a/FOSSDB/apps/fossdb/hosting_platform/forms.py +++ b/FOSSDB/apps/fossdb/hosting_platform/forms.py @@ -1,6 +1,6 @@ from django import forms -from .models import ProjectHostingPlatform, HostingPlatform +from .models import HostingPlatform, ProjectHostingPlatform class HostingPlatformForm(forms.ModelForm): diff --git a/FOSSDB/apps/fossdb/migrations/0001_initial.py b/FOSSDB/apps/fossdb/migrations/0001_initial.py index fc86c22..b947c0a 100644 --- a/FOSSDB/apps/fossdb/migrations/0001_initial.py +++ b/FOSSDB/apps/fossdb/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 4.2.2 on 2023-06-27 12:54 +# Generated by Django 4.2.2 on 2023-06-27 16:35 from django.conf import settings from django.db import migrations, models @@ -75,7 +75,7 @@ class Migration(migrations.Migration): ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('name', models.CharField(db_index=True, max_length=100, unique=True)), ('description', models.TextField(blank=True, default='')), - ('icon', models.ImageField(blank=True, null=True, upload_to='types/icons/')), + ('icon', models.ImageField(blank=True, upload_to='types/icons/')), ], ), migrations.CreateModel( @@ -106,4 +106,12 @@ class Migration(migrations.Migration): name='tag', field=models.ManyToManyField(blank=True, to='fossdb.tag'), ), + migrations.AddConstraint( + model_name='project', + constraint=models.UniqueConstraint(fields=('owner', 'name'), name='unique_owner_name'), + ), + migrations.AddConstraint( + model_name='operatingsystemversion', + constraint=models.UniqueConstraint(fields=('operating_system', 'version'), name='unique_os_version'), + ), ] diff --git a/FOSSDB/apps/fossdb/migrations/0002_alter_tag_icon.py b/FOSSDB/apps/fossdb/migrations/0002_alter_tag_icon.py new file mode 100644 index 0000000..5992142 --- /dev/null +++ b/FOSSDB/apps/fossdb/migrations/0002_alter_tag_icon.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2.2 on 2023-06-27 16:36 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('fossdb', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='tag', + name='icon', + field=models.ImageField(blank=True, null=True, upload_to='types/icons/'), + ), + ] diff --git a/FOSSDB/apps/fossdb/migrations/0003_alter_projectprogramminglanguage_percentage.py b/FOSSDB/apps/fossdb/migrations/0003_alter_projectprogramminglanguage_percentage.py new file mode 100644 index 0000000..c5403b8 --- /dev/null +++ b/FOSSDB/apps/fossdb/migrations/0003_alter_projectprogramminglanguage_percentage.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2.2 on 2023-06-27 18:09 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('fossdb', '0002_alter_tag_icon'), + ] + + operations = [ + migrations.AlterField( + model_name='projectprogramminglanguage', + name='percentage', + field=models.PositiveIntegerField(blank=True, null=True), + ), + ] diff --git a/FOSSDB/apps/fossdb/models.py b/FOSSDB/apps/fossdb/models.py index 5e0f71e..fef774f 100644 --- a/FOSSDB/apps/fossdb/models.py +++ b/FOSSDB/apps/fossdb/models.py @@ -6,7 +6,7 @@ from django.db import models from .license.models import License from .operating_system.models import OperatingSystemVersion -from .programming_language.models import ProgrammingLanguage, ProjectProgrammingLanguage +from .programming_language.models import ProgrammingLanguage from .tag.models import Tag @@ -18,7 +18,7 @@ class Project(models.Model): license = models.ManyToManyField(License, blank=True) tag = models.ManyToManyField(Tag, blank=True) operating_system = models.ManyToManyField(OperatingSystemVersion, blank=True) - programming_language = models.ManyToManyField(ProgrammingLanguage, through=ProjectProgrammingLanguage, blank=True) + programming_language = models.ManyToManyField(ProgrammingLanguage, through="ProjectProgrammingLanguage", blank=True) date_created = models.DateTimeField(auto_now_add=True) @property @@ -29,4 +29,15 @@ class Project(models.Model): return f"/{self.owner}/{self.name}" def __str__(self): - return f"{self.owner} | {self.name}" + return f"{self.owner}/{self.name}" + + class Meta: + constraints = ( + models.UniqueConstraint( + fields=( + "owner", + "name", + ), + name="unique_owner_name", + ), + ) diff --git a/FOSSDB/apps/fossdb/operating_system/models.py b/FOSSDB/apps/fossdb/operating_system/models.py index 24cc7ca..911d8fd 100644 --- a/FOSSDB/apps/fossdb/operating_system/models.py +++ b/FOSSDB/apps/fossdb/operating_system/models.py @@ -17,3 +17,14 @@ class OperatingSystemVersion(models.Model): def __str__(self): return f"{self.operating_system.name} {self.version} {'LTS' if self.is_lts else ''}" + + class Meta: + constraints = ( + models.UniqueConstraint( + fields=( + "operating_system", + "version", + ), + name="unique_os_version", + ), + ) diff --git a/FOSSDB/apps/fossdb/programming_language/models.py b/FOSSDB/apps/fossdb/programming_language/models.py index 853b793..d2357d3 100644 --- a/FOSSDB/apps/fossdb/programming_language/models.py +++ b/FOSSDB/apps/fossdb/programming_language/models.py @@ -11,7 +11,7 @@ class ProgrammingLanguage(models.Model): class ProjectProgrammingLanguage(models.Model): project = models.ForeignKey("Project", on_delete=models.CASCADE) programming_language = models.ForeignKey(ProgrammingLanguage, on_delete=models.CASCADE) - percentage = models.PositiveIntegerField() + percentage = models.PositiveIntegerField(blank=True, null=True) def __str__(self): return f"{self.project.owner}/{self.project.name} | {self.programming_language} | {self.percentage}%" diff --git a/FOSSDB/apps/fossdb/urls.py b/FOSSDB/apps/fossdb/urls.py index e2bb536..a831e57 100644 --- a/FOSSDB/apps/fossdb/urls.py +++ b/FOSSDB/apps/fossdb/urls.py @@ -3,9 +3,9 @@ from django.urls import path from . import views urlpatterns = [ - path("", views.index, name="index"), + path("", views.ProjectListView.as_view(), name="index"), path("add/", views.ProjectCreateView.as_view(), name="add-project"), path("//", views.ProjectDetailView.as_view(), name="project-detail"), - path("//update/", views.ProjectUpdateView.as_view(), name="project-update"), + path("//edit/", views.ProjectUpdateView.as_view(), name="project-update"), path("//delete/", views.ProjectDeleteView.as_view(), name="project-delete"), ] diff --git a/FOSSDB/apps/fossdb/views.py b/FOSSDB/apps/fossdb/views.py index abd7b23..71668a5 100644 --- a/FOSSDB/apps/fossdb/views.py +++ b/FOSSDB/apps/fossdb/views.py @@ -1,58 +1,67 @@ from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin -from django.db import transaction -from django.shortcuts import get_object_or_404, redirect, render +from django.forms import inlineformset_factory +from django.shortcuts import redirect from django.views.generic import CreateView, DeleteView, DetailView, UpdateView +from django_filters.views import FilterView + +from .filters import ProjectFilter + from .forms import ProjectForm from .hosting_platform.forms import HostingPlatformForm - from .models import Project from .programming_language.forms import ProgrammingLanguageForm +from .programming_language.models import ProjectProgrammingLanguage + +ProgrammingLanguageInlineFormset = inlineformset_factory( + Project, + ProjectProgrammingLanguage, + form=ProgrammingLanguageForm, + extra=1, +) -def index(request): - context = { - "title": "FOSSDB", - "projects": Project.objects.all(), - } - return render(request, "fossdb/index.html", context) +class ProjectListView(FilterView): + model = Project + template_name = "fossdb/index.html" + filterset_class = ProjectFilter + context_object_name = "projects" + paginate_by = 10 # optional 10 projects a page class ProjectCreateView(LoginRequiredMixin, CreateView): model = Project form_class = ProjectForm - template_name = "fossdb/add_project.html" + template_name = "fossdb/create_view.html" login_url = "/login/" redirect_field_name = "redirect_to" - def form_valid(self, form): - response = None - with transaction.atomic(): - form.instance.owner = self.request.user - response = super().form_valid(form) - - hosting_platform_form = HostingPlatformForm(self.request.POST, instance=self.object) - if hosting_platform_form.is_valid(): - hosting_platform = hosting_platform_form.save(commit=False) - hosting_platform.project = self.object - hosting_platform.save() - - # TODO: allow adding multiple languages - programming_language_form = ProgrammingLanguageForm(self.request.POST, instance=self.object) - if programming_language_form.is_valid(): - programming_language = programming_language_form.save(commit=False) - programming_language.project = self.object - programming_language.save() - - return response - def get_context_data(self, *args, **kwargs): - context = super().get_context_data(**kwargs) - context["title"] = "Add project" - context["project_form"] = ProjectForm() - context["hosting_platform_form"] = HostingPlatformForm() - context["programming_language_form"] = ProgrammingLanguageForm() - return context + data = super().get_context_data(**kwargs) + data["hosting_platform"] = HostingPlatformForm(self.request.POST or None, prefix="hosting") + data["programming_language"] = ProgrammingLanguageInlineFormset(self.request.POST or None, prefix="language") + data["empty_form"] = ProgrammingLanguageInlineFormset(prefix="language_empty") + return data + + def form_valid(self, form): + context = self.get_context_data() + form.instance.owner = self.request.user + hosting_platform = context["hosting_platform"] + programming_language = context["programming_language"] + self.object = form.save() + if hosting_platform.is_valid(): + hosting_platform.instance.project = self.object + hosting_platform.save() + # TODO: allow adding multiple languages + if programming_language.is_valid(): + for instance in programming_language.save(commit=False): + instance.project = self.object + instance.save() + programming_language.save_m2m() + if hosting_platform.is_valid() and programming_language.is_valid(): + return super().form_valid(form) + else: + return self.render_to_response(self.get_context_data(form=form)) class ProjectDetailView(DetailView): @@ -65,7 +74,7 @@ class ProjectDetailView(DetailView): class ProjectUpdateView(LoginRequiredMixin, UserPassesTestMixin, UpdateView): model = Project - template_name = "fossdb/update_view.html" + template_name = "fossdb/create_view.html" form_class = ProjectForm slug_field = "name" slug_url_kwarg = "project_name" @@ -79,17 +88,11 @@ class ProjectUpdateView(LoginRequiredMixin, UserPassesTestMixin, UpdateView): return redirect("index") def get_context_data(self, *args, **kwargs): - context = super().get_context_data(**kwargs) - if self.request.POST: - context["project_form"] = ProjectForm(self.request.POST, instance=self.object) - context["hosting_platform_form"] = HostingPlatformForm(self.request.POST, instance=self.object) - context["programming_language_form"] = ProgrammingLanguageForm(self.request.POST, instance=self.object) - else: - context["project_form"] = ProjectForm(instance=self.object) - context["hosting_platform_form"] = HostingPlatformForm(instance=self.object) - context["programming_language_form"] = ProgrammingLanguageForm(instance=self.object) - - return context + data = super(ProjectUpdateView, self).get_context_data(**kwargs) + data["hosting_platform"] = HostingPlatformForm(self.request.POST or None, instance=self.object.projecthostingplatform, prefix="hosting") + data["programming_language"] = ProgrammingLanguageInlineFormset(self.request.POST or None, instance=self.object, prefix="language") + data["empty_form"] = ProgrammingLanguageInlineFormset(prefix="language_empty") + return data class ProjectDeleteView(LoginRequiredMixin, UserPassesTestMixin, DeleteView): diff --git a/FOSSDB/settings.py b/FOSSDB/settings.py index 9e80206..bc2bd4c 100644 --- a/FOSSDB/settings.py +++ b/FOSSDB/settings.py @@ -37,6 +37,7 @@ DEBUG = config["DEBUG"] INSTALLED_APPS = [ "account", "fossdb", + "django_filters", "django.contrib.admin", "django.contrib.auth", "django.contrib.contenttypes", diff --git a/FOSSDB/urls.py b/FOSSDB/urls.py index d5c0637..af7155c 100644 --- a/FOSSDB/urls.py +++ b/FOSSDB/urls.py @@ -19,12 +19,11 @@ from django.contrib import admin from django.urls import include, path urlpatterns = [ + path("admin/", admin.site.urls), path("", include("fossdb.urls")), path("", include("account.urls")), - # path("", include("django.contrib.auth.urls")), - path("admin/", admin.site.urls), + path("", include("django.contrib.auth.urls")), ] urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) -if settings.DEBUG: - urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) +urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) diff --git a/templates/fossdb/add_project.html b/templates/fossdb/add_project.html deleted file mode 100644 index b25bbd7..0000000 --- a/templates/fossdb/add_project.html +++ /dev/null @@ -1,14 +0,0 @@ -{% extends "layout.html" %} -{% load static %} -{% block title %}{{ title }}{% endblock %} -{% block meta %}{% endblock %} -{% block content %} - - {% csrf_token %} - {{ project_form.as_p }} - {{ hosting_platform_form.as_table }} -
    - {{ programming_language_form.as_table }} - - -{% endblock %} diff --git a/templates/fossdb/create_view.html b/templates/fossdb/create_view.html new file mode 100644 index 0000000..aa624a2 --- /dev/null +++ b/templates/fossdb/create_view.html @@ -0,0 +1,34 @@ +{% extends "layout.html" %} +{% load static %} +{% block title %}{{ title }}{% endblock %} +{% block meta %}{% endblock %} +{% block content %} +
    + {% csrf_token %} + {{ form.as_p }} + {{ hosting_platform.management_form }} + {{ hosting_platform.as_table }} +
    + {{ programming_language.management_form }} + {% for form in programming_language %}
    {{ form.as_table }}
    {% endfor %} +
    + + + + + + +
    + +{% endblock %} diff --git a/templates/fossdb/detailed_view.html b/templates/fossdb/detailed_view.html index b3ffc73..6e26ccb 100644 --- a/templates/fossdb/detailed_view.html +++ b/templates/fossdb/detailed_view.html @@ -39,7 +39,6 @@

    No language

    {% endfor %}
-

{{ project.date_created|date:"d.m.Y, G:i" }}

diff --git a/templates/fossdb/index.html b/templates/fossdb/index.html index c4fbc3f..93f2dbd 100644 --- a/templates/fossdb/index.html +++ b/templates/fossdb/index.html @@ -3,6 +3,7 @@ {% block title %}{{ title }}{% endblock %} {% block meta %}{% endblock %} {% block content %} +

{{ username }}

@@ -10,14 +11,17 @@ Admin
+
+ {{ filter.form.as_p }} + +
{% for project in projects %}
-

- {{ project.owner }}/{{ project.name }} -

-

{{ project.description }}

+ {{ project }}
+
{{ project.description }}
+
{% empty %} -

No projects yet (

+

No projects found

{% endfor %} {% endblock %} diff --git a/templates/fossdb/update_view.html b/templates/fossdb/update_view.html deleted file mode 100644 index 48c0d7c..0000000 --- a/templates/fossdb/update_view.html +++ /dev/null @@ -1,12 +0,0 @@ -{% extends "layout.html" %} -{% block title %}Edit {{ project.name }}{% endblock %} -{% block content %} -
- {% csrf_token %} - {{ project_form.as_p }} - {{ hosting_platform_form.as_table }} -
- {{ programming_language_form.as_table }} - -
-{% endblock %} From 26862579109b2b68140b195e0d93707823c0ebfb Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Wed, 28 Jun 2023 10:20:18 +0000 Subject: [PATCH 128/144] Changed folder structure --- {FOSSDB => src/FOSSDB}/__init__.py | 0 .../FOSSDB}/apps/account/__init__.py | 0 {FOSSDB => src/FOSSDB}/apps/account/admin.py | 0 {FOSSDB => src/FOSSDB}/apps/account/apps.py | 0 {FOSSDB => src/FOSSDB}/apps/account/forms.py | 0 .../apps/account/migrations/0001_initial.py | 0 .../apps/account/migrations/__init__.py | 0 {FOSSDB => src/FOSSDB}/apps/account/models.py | 2 +- {FOSSDB => src/FOSSDB}/apps/account/tests.py | 0 {FOSSDB => src/FOSSDB}/apps/account/urls.py | 0 {FOSSDB => src/FOSSDB}/apps/account/views.py | 0 .../FOSSDB}/apps/fossdb/__init__.py | 0 {FOSSDB => src/FOSSDB}/apps/fossdb/admin.py | 0 {FOSSDB => src/FOSSDB}/apps/fossdb/apps.py | 0 {FOSSDB => src/FOSSDB}/apps/fossdb/filters.py | 0 {FOSSDB => src/FOSSDB}/apps/fossdb/forms.py | 0 .../apps/fossdb/hosting_platform/forms.py | 0 .../apps/fossdb/hosting_platform/models.py | 0 .../FOSSDB}/apps/fossdb/license/models.py | 0 .../apps/fossdb/migrations/0001_initial.py | 0 .../fossdb/migrations/0002_alter_tag_icon.py | 0 ...r_projectprogramminglanguage_percentage.py | 0 .../apps/fossdb/migrations/__init__.py | 0 {FOSSDB => src/FOSSDB}/apps/fossdb/models.py | 0 .../apps/fossdb/operating_system/models.py | 0 .../apps/fossdb/programming_language/forms.py | 0 .../fossdb/programming_language/models.py | 0 .../FOSSDB}/apps/fossdb/star/models.py | 0 .../FOSSDB}/apps/fossdb/tag/models.py | 0 {FOSSDB => src/FOSSDB}/apps/fossdb/tests.py | 0 {FOSSDB => src/FOSSDB}/apps/fossdb/urls.py | 0 {FOSSDB => src/FOSSDB}/apps/fossdb/views.py | 0 {FOSSDB => src/FOSSDB}/asgi.py | 0 {FOSSDB => src/FOSSDB}/settings.py | 21 +++++++++++++----- {FOSSDB => src/FOSSDB}/urls.py | 7 +++--- {FOSSDB => src/FOSSDB}/wsgi.py | 0 manage.py => src/manage.py | 0 .../940e8e9e-77d4-42bb-84fd-04d332de403b.png | Bin 0 -> 29814 bytes .../media/profile-pics}/default.jpg | Bin .../templates}/account/login.html | 0 .../templates}/account/profile.html | 0 .../templates}/account/signup.html | 0 .../templates}/fossdb/create_view.html | 0 .../templates}/fossdb/delete_view.html | 0 .../templates}/fossdb/detailed_view.html | 0 .../templates}/fossdb/index.html | 0 {templates => src/templates}/layout.html | 0 47 files changed, 20 insertions(+), 10 deletions(-) rename {FOSSDB => src/FOSSDB}/__init__.py (100%) rename {FOSSDB => src/FOSSDB}/apps/account/__init__.py (100%) rename {FOSSDB => src/FOSSDB}/apps/account/admin.py (100%) rename {FOSSDB => src/FOSSDB}/apps/account/apps.py (100%) rename {FOSSDB => src/FOSSDB}/apps/account/forms.py (100%) rename {FOSSDB => src/FOSSDB}/apps/account/migrations/0001_initial.py (100%) rename {FOSSDB => src/FOSSDB}/apps/account/migrations/__init__.py (100%) rename {FOSSDB => src/FOSSDB}/apps/account/models.py (97%) rename {FOSSDB => src/FOSSDB}/apps/account/tests.py (100%) rename {FOSSDB => src/FOSSDB}/apps/account/urls.py (100%) rename {FOSSDB => src/FOSSDB}/apps/account/views.py (100%) rename {FOSSDB => src/FOSSDB}/apps/fossdb/__init__.py (100%) rename {FOSSDB => src/FOSSDB}/apps/fossdb/admin.py (100%) rename {FOSSDB => src/FOSSDB}/apps/fossdb/apps.py (100%) rename {FOSSDB => src/FOSSDB}/apps/fossdb/filters.py (100%) rename {FOSSDB => src/FOSSDB}/apps/fossdb/forms.py (100%) rename {FOSSDB => src/FOSSDB}/apps/fossdb/hosting_platform/forms.py (100%) rename {FOSSDB => src/FOSSDB}/apps/fossdb/hosting_platform/models.py (100%) rename {FOSSDB => src/FOSSDB}/apps/fossdb/license/models.py (100%) rename {FOSSDB => src/FOSSDB}/apps/fossdb/migrations/0001_initial.py (100%) rename {FOSSDB => src/FOSSDB}/apps/fossdb/migrations/0002_alter_tag_icon.py (100%) rename {FOSSDB => src/FOSSDB}/apps/fossdb/migrations/0003_alter_projectprogramminglanguage_percentage.py (100%) rename {FOSSDB => src/FOSSDB}/apps/fossdb/migrations/__init__.py (100%) rename {FOSSDB => src/FOSSDB}/apps/fossdb/models.py (100%) rename {FOSSDB => src/FOSSDB}/apps/fossdb/operating_system/models.py (100%) rename {FOSSDB => src/FOSSDB}/apps/fossdb/programming_language/forms.py (100%) rename {FOSSDB => src/FOSSDB}/apps/fossdb/programming_language/models.py (100%) rename {FOSSDB => src/FOSSDB}/apps/fossdb/star/models.py (100%) rename {FOSSDB => src/FOSSDB}/apps/fossdb/tag/models.py (100%) rename {FOSSDB => src/FOSSDB}/apps/fossdb/tests.py (100%) rename {FOSSDB => src/FOSSDB}/apps/fossdb/urls.py (100%) rename {FOSSDB => src/FOSSDB}/apps/fossdb/views.py (100%) rename {FOSSDB => src/FOSSDB}/asgi.py (100%) rename {FOSSDB => src/FOSSDB}/settings.py (90%) rename {FOSSDB => src/FOSSDB}/urls.py (79%) rename {FOSSDB => src/FOSSDB}/wsgi.py (100%) rename manage.py => src/manage.py (100%) create mode 100644 src/media/profile-pics/940e8e9e-77d4-42bb-84fd-04d332de403b.png rename {media/profile_pics => src/media/profile-pics}/default.jpg (100%) rename {templates => src/templates}/account/login.html (100%) rename {templates => src/templates}/account/profile.html (100%) rename {templates => src/templates}/account/signup.html (100%) rename {templates => src/templates}/fossdb/create_view.html (100%) rename {templates => src/templates}/fossdb/delete_view.html (100%) rename {templates => src/templates}/fossdb/detailed_view.html (100%) rename {templates => src/templates}/fossdb/index.html (100%) rename {templates => src/templates}/layout.html (100%) diff --git a/FOSSDB/__init__.py b/src/FOSSDB/__init__.py similarity index 100% rename from FOSSDB/__init__.py rename to src/FOSSDB/__init__.py diff --git a/FOSSDB/apps/account/__init__.py b/src/FOSSDB/apps/account/__init__.py similarity index 100% rename from FOSSDB/apps/account/__init__.py rename to src/FOSSDB/apps/account/__init__.py diff --git a/FOSSDB/apps/account/admin.py b/src/FOSSDB/apps/account/admin.py similarity index 100% rename from FOSSDB/apps/account/admin.py rename to src/FOSSDB/apps/account/admin.py diff --git a/FOSSDB/apps/account/apps.py b/src/FOSSDB/apps/account/apps.py similarity index 100% rename from FOSSDB/apps/account/apps.py rename to src/FOSSDB/apps/account/apps.py diff --git a/FOSSDB/apps/account/forms.py b/src/FOSSDB/apps/account/forms.py similarity index 100% rename from FOSSDB/apps/account/forms.py rename to src/FOSSDB/apps/account/forms.py diff --git a/FOSSDB/apps/account/migrations/0001_initial.py b/src/FOSSDB/apps/account/migrations/0001_initial.py similarity index 100% rename from FOSSDB/apps/account/migrations/0001_initial.py rename to src/FOSSDB/apps/account/migrations/0001_initial.py diff --git a/FOSSDB/apps/account/migrations/__init__.py b/src/FOSSDB/apps/account/migrations/__init__.py similarity index 100% rename from FOSSDB/apps/account/migrations/__init__.py rename to src/FOSSDB/apps/account/migrations/__init__.py diff --git a/FOSSDB/apps/account/models.py b/src/FOSSDB/apps/account/models.py similarity index 97% rename from FOSSDB/apps/account/models.py rename to src/FOSSDB/apps/account/models.py index a4164e6..49c64da 100644 --- a/FOSSDB/apps/account/models.py +++ b/src/FOSSDB/apps/account/models.py @@ -14,7 +14,7 @@ def get_profile_pic_path(instance, filename) -> Path: class User(AbstractUser): id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False, verbose_name="ID") - profile_picture = models.ImageField(upload_to=get_profile_pic_path, default="profile_pics/default.jpg") + profile_picture = models.ImageField(upload_to=get_profile_pic_path, default="profile-pics/default.jpg") @property def full_name(self): diff --git a/FOSSDB/apps/account/tests.py b/src/FOSSDB/apps/account/tests.py similarity index 100% rename from FOSSDB/apps/account/tests.py rename to src/FOSSDB/apps/account/tests.py diff --git a/FOSSDB/apps/account/urls.py b/src/FOSSDB/apps/account/urls.py similarity index 100% rename from FOSSDB/apps/account/urls.py rename to src/FOSSDB/apps/account/urls.py diff --git a/FOSSDB/apps/account/views.py b/src/FOSSDB/apps/account/views.py similarity index 100% rename from FOSSDB/apps/account/views.py rename to src/FOSSDB/apps/account/views.py diff --git a/FOSSDB/apps/fossdb/__init__.py b/src/FOSSDB/apps/fossdb/__init__.py similarity index 100% rename from FOSSDB/apps/fossdb/__init__.py rename to src/FOSSDB/apps/fossdb/__init__.py diff --git a/FOSSDB/apps/fossdb/admin.py b/src/FOSSDB/apps/fossdb/admin.py similarity index 100% rename from FOSSDB/apps/fossdb/admin.py rename to src/FOSSDB/apps/fossdb/admin.py diff --git a/FOSSDB/apps/fossdb/apps.py b/src/FOSSDB/apps/fossdb/apps.py similarity index 100% rename from FOSSDB/apps/fossdb/apps.py rename to src/FOSSDB/apps/fossdb/apps.py diff --git a/FOSSDB/apps/fossdb/filters.py b/src/FOSSDB/apps/fossdb/filters.py similarity index 100% rename from FOSSDB/apps/fossdb/filters.py rename to src/FOSSDB/apps/fossdb/filters.py diff --git a/FOSSDB/apps/fossdb/forms.py b/src/FOSSDB/apps/fossdb/forms.py similarity index 100% rename from FOSSDB/apps/fossdb/forms.py rename to src/FOSSDB/apps/fossdb/forms.py diff --git a/FOSSDB/apps/fossdb/hosting_platform/forms.py b/src/FOSSDB/apps/fossdb/hosting_platform/forms.py similarity index 100% rename from FOSSDB/apps/fossdb/hosting_platform/forms.py rename to src/FOSSDB/apps/fossdb/hosting_platform/forms.py diff --git a/FOSSDB/apps/fossdb/hosting_platform/models.py b/src/FOSSDB/apps/fossdb/hosting_platform/models.py similarity index 100% rename from FOSSDB/apps/fossdb/hosting_platform/models.py rename to src/FOSSDB/apps/fossdb/hosting_platform/models.py diff --git a/FOSSDB/apps/fossdb/license/models.py b/src/FOSSDB/apps/fossdb/license/models.py similarity index 100% rename from FOSSDB/apps/fossdb/license/models.py rename to src/FOSSDB/apps/fossdb/license/models.py diff --git a/FOSSDB/apps/fossdb/migrations/0001_initial.py b/src/FOSSDB/apps/fossdb/migrations/0001_initial.py similarity index 100% rename from FOSSDB/apps/fossdb/migrations/0001_initial.py rename to src/FOSSDB/apps/fossdb/migrations/0001_initial.py diff --git a/FOSSDB/apps/fossdb/migrations/0002_alter_tag_icon.py b/src/FOSSDB/apps/fossdb/migrations/0002_alter_tag_icon.py similarity index 100% rename from FOSSDB/apps/fossdb/migrations/0002_alter_tag_icon.py rename to src/FOSSDB/apps/fossdb/migrations/0002_alter_tag_icon.py diff --git a/FOSSDB/apps/fossdb/migrations/0003_alter_projectprogramminglanguage_percentage.py b/src/FOSSDB/apps/fossdb/migrations/0003_alter_projectprogramminglanguage_percentage.py similarity index 100% rename from FOSSDB/apps/fossdb/migrations/0003_alter_projectprogramminglanguage_percentage.py rename to src/FOSSDB/apps/fossdb/migrations/0003_alter_projectprogramminglanguage_percentage.py diff --git a/FOSSDB/apps/fossdb/migrations/__init__.py b/src/FOSSDB/apps/fossdb/migrations/__init__.py similarity index 100% rename from FOSSDB/apps/fossdb/migrations/__init__.py rename to src/FOSSDB/apps/fossdb/migrations/__init__.py diff --git a/FOSSDB/apps/fossdb/models.py b/src/FOSSDB/apps/fossdb/models.py similarity index 100% rename from FOSSDB/apps/fossdb/models.py rename to src/FOSSDB/apps/fossdb/models.py diff --git a/FOSSDB/apps/fossdb/operating_system/models.py b/src/FOSSDB/apps/fossdb/operating_system/models.py similarity index 100% rename from FOSSDB/apps/fossdb/operating_system/models.py rename to src/FOSSDB/apps/fossdb/operating_system/models.py diff --git a/FOSSDB/apps/fossdb/programming_language/forms.py b/src/FOSSDB/apps/fossdb/programming_language/forms.py similarity index 100% rename from FOSSDB/apps/fossdb/programming_language/forms.py rename to src/FOSSDB/apps/fossdb/programming_language/forms.py diff --git a/FOSSDB/apps/fossdb/programming_language/models.py b/src/FOSSDB/apps/fossdb/programming_language/models.py similarity index 100% rename from FOSSDB/apps/fossdb/programming_language/models.py rename to src/FOSSDB/apps/fossdb/programming_language/models.py diff --git a/FOSSDB/apps/fossdb/star/models.py b/src/FOSSDB/apps/fossdb/star/models.py similarity index 100% rename from FOSSDB/apps/fossdb/star/models.py rename to src/FOSSDB/apps/fossdb/star/models.py diff --git a/FOSSDB/apps/fossdb/tag/models.py b/src/FOSSDB/apps/fossdb/tag/models.py similarity index 100% rename from FOSSDB/apps/fossdb/tag/models.py rename to src/FOSSDB/apps/fossdb/tag/models.py diff --git a/FOSSDB/apps/fossdb/tests.py b/src/FOSSDB/apps/fossdb/tests.py similarity index 100% rename from FOSSDB/apps/fossdb/tests.py rename to src/FOSSDB/apps/fossdb/tests.py diff --git a/FOSSDB/apps/fossdb/urls.py b/src/FOSSDB/apps/fossdb/urls.py similarity index 100% rename from FOSSDB/apps/fossdb/urls.py rename to src/FOSSDB/apps/fossdb/urls.py diff --git a/FOSSDB/apps/fossdb/views.py b/src/FOSSDB/apps/fossdb/views.py similarity index 100% rename from FOSSDB/apps/fossdb/views.py rename to src/FOSSDB/apps/fossdb/views.py diff --git a/FOSSDB/asgi.py b/src/FOSSDB/asgi.py similarity index 100% rename from FOSSDB/asgi.py rename to src/FOSSDB/asgi.py diff --git a/FOSSDB/settings.py b/src/FOSSDB/settings.py similarity index 90% rename from FOSSDB/settings.py rename to src/FOSSDB/settings.py index bc2bd4c..23c7b7e 100644 --- a/FOSSDB/settings.py +++ b/src/FOSSDB/settings.py @@ -21,7 +21,7 @@ sys.path.insert(0, str(BASE_PATH.joinpath("FOSSDB", "apps"))) # Quick-start development settings - unsuitable for production # See https://docs.djangoproject.com/en/4.0/howto/deployment/checklist/ -with open(BASE_PATH.joinpath("config.json"), "r", encoding="UTF-8") as config_file: +with open(BASE_PATH.parent / "config.json", "r", encoding="UTF-8") as config_file: config = json.load(config_file) # SECURITY WARNING: keep the secret key used in production secret! @@ -61,7 +61,9 @@ ROOT_URLCONF = "FOSSDB.urls" TEMPLATES = [ { "BACKEND": "django.template.backends.django.DjangoTemplates", - "DIRS": [BASE_PATH.joinpath("templates")], + "DIRS": [ + BASE_PATH / "templates", + ], "APP_DIRS": True, "OPTIONS": { "context_processors": [ @@ -128,10 +130,17 @@ USE_TZ = True # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/4.0/howto/static-files/ -STATIC_URL = "/static/" -STATIC_ROOT = BASE_PATH.joinpath("static") -MEDIA_URL = "/media/" -MEDIA_ROOT = BASE_PATH.joinpath("media") +STATIC_URL = "static/" +STATICFILE_DIRS = [ + BASE_PATH / "static", +] +STATIC_ROOT = BASE_PATH.parent / "local-cdn" / "static" + +MEDIA_URL = "media/" +MEDIAFILES_DIRS = [ + BASE_PATH / "media", +] +MEDIA_ROOT = BASE_PATH.parent / "local-cdn" / "media" # Default primary key field type # https://docs.djangoproject.com/en/4.0/ref/settings/#default-auto-field diff --git a/FOSSDB/urls.py b/src/FOSSDB/urls.py similarity index 79% rename from FOSSDB/urls.py rename to src/FOSSDB/urls.py index af7155c..9310a1d 100644 --- a/FOSSDB/urls.py +++ b/src/FOSSDB/urls.py @@ -14,7 +14,6 @@ Including another URLconf 2. Add a URL to urlpatterns: path("blog/", include("blog.urls")) """ from django.conf import settings -from django.conf.urls.static import static from django.contrib import admin from django.urls import include, path @@ -24,6 +23,8 @@ urlpatterns = [ path("", include("account.urls")), path("", include("django.contrib.auth.urls")), ] +if settings.DEBUG: + from django.conf.urls.static import static -urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) -urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) + urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) + urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) diff --git a/FOSSDB/wsgi.py b/src/FOSSDB/wsgi.py similarity index 100% rename from FOSSDB/wsgi.py rename to src/FOSSDB/wsgi.py diff --git a/manage.py b/src/manage.py similarity index 100% rename from manage.py rename to src/manage.py diff --git a/src/media/profile-pics/940e8e9e-77d4-42bb-84fd-04d332de403b.png b/src/media/profile-pics/940e8e9e-77d4-42bb-84fd-04d332de403b.png new file mode 100644 index 0000000000000000000000000000000000000000..a8c7ebaa36bd2921c67c7dfa3e84772f92ce7299 GIT binary patch literal 29814 zcmYJbcRbba8$bR!_TJ;zGb4NNy^|F}W(ZN4WplFkh$JJTC?#ZXB9x3n9DAgkV-v!$ zzPI=1`~Cg?@G#E(y6*eF_Vc=~mqb%zJ#rFe5(t9G4fM5dK@bl35eFh70N)OReqzBl zVjq1Qe+Z)Jx%z_jd%tr9e`E^Ku?{fzb_)o+>vslKg#J?|8QtbRTaBXbbzTrqVeD&2LM{9Dnh*YhV|Mtt14o5M^&x1b- z)0=uuh7}e=DO%C5Le+_oRqxHq^KRX`^_iTYhqG^r(`bAQ?sC6iKcLT=*+rOK{W@Bi zS{(;L-N{2jXEp{U0Sbhz#-O zosLsKdL5<_cq?mH5cC2!H)dEcm`0gWF*#bRV817+gw;8PZBlwm-`BUsF+g6^RSzHH z(#TVMTp=hWwSQ~)L+7q`Mn1Fs0J7< zr@N=jcPU)rAU0qrTJHXANJSE77-b6w=Otv?trUY~q7et9Cp$@11uLr$kk8@zRax?p^xf6E+O%S!Ib7wY?wC)PREH z2t2g0sp%MjQIFB4p@(=^Z|2JmJ++`8+QNk>Q(l|VUc3?rYUHMC6Y`8y^CnGfIDjA;Y zuS(lxr9KqOt9S-Az^osM!*fLL)V;eCz^SRJfe&SV|7cT7kbkqxreNO&;=?u7cIWmT zqI8l%hcUT4u<`ZvZ3lqo-5G+spnyoV|r^S`li(6(UGrtk_@VWV#4xeyl&@o zI~~JZHuZ{4&SEeIgf5%cs!*r#_Xcw&z|DTE<3npNDk=;L_IITE*zw818k?h(E{^2n zWLqF6ED*!m6@#Hgyj@!;`fC|i4BqQZ{|l@5o|=qpX3lnCx^}MJQTTl=EiJ(*HIBFg zjDW#3pZ$hUyx}fYqnW+GHIp!qwj&8CsdrUX)nX4kltTKLmb>+CN)027Rrvb#yz7c& zNX9%ECj?nq_TwH4A*vFGHHi{)8>Nj-kz;QSO_C@ydrNURhu>G^5iT8J<~|g;#SkTi zKN>#K1efVeq8FM0?Ehs7qbe^mF7&)%ViHNzwFB`c4{H%6w&(_QTo%2)Kpblq9se>l zGebUHTU!f-DU&mw5hq%`#GENPx!=9JECSRHQ_6&pzh!DFe#b0Z4JTJnk(5h2Z~qEl6|ir@{5>^j%gs9Pk;sXrlvlH7;)au9t51az&X35oKvFD$|16neJag2 zE8y4hwSWu1i3-anK*^7hWa?z=o|tK%Ciot^{4p_o0}7X~Cp_mJt*wJv0i82ICvGnC z^8CI-)zJvVj@P9P4%M6eN4In@w5kK^S&HH0RleGcj)7re>o9~8Czldjo@-fd9KFwW z9f&|kk%*Ww50+tvGLE<;*nNz&A>#6NsRz2VP@}4dHSO6hB7YTJng%dv>d)EYExiUzqW~ZJfDa{W-A6hY3fV4z z=rs?VC=llr6$=7j)3m#rQ#B=08Blh1ws>@RHNwAxu8R{GGS_d`HE6p?{BG28lF+BA zprtODs3O%GhX_nx-E!hC!Oe>{-&#s^ZOY7VFE z+Mcd;cNA45YKGH8ilr6na?k@paR+cOBI0O68Kc>m`T~Q1m>eiT)6x>xWs`XLWJJUE zghtbu(mmze5$FNW|J4IPoY8G4?>WAcJ!&od>h8|eD+QO;9UT|vHnnc#3~X_xFiyKG z=c8Nd%a2gfcIS%85NMk4klxNy3H?W265XqG9m2a3(FcL=d=St77JNrZZ)JV?@`X@` zFwy-dE@#)-$-c;w*7Hkw^g)jaQDR^+6juJ93)F9W&4dtWz4Cxcii)yhOD05IkfL|s zg}&tkD^lYZIXz@%0TjO5N&Epm&`QA35*|5d>TSh3FZh@ke0&S2Stu&xQv6COwB!Fm z4+Q=*TKzU)4J1iPNvjfllQ{bHg|Sqc0m3i+FWi8Q1!@x}5?VmorUnMYLc+pf1^yQ_ zP!{k~RNOEg^x2}0jt;5ejT;`0*+eC+5Vz~a*-6g7fBzVnTmrZmxME`5n&%%CwT2ve zzQAzSB#5Abqg|3Hx@|xTaR)G-D(0ih#^6U-?BUmfxKZL z0>xrxJ9zkai!3*WDgN#``M43p{r+8et|%i2Lm9(UUn|()m{TYI#A*7_)D+YR9*@d{ zdfvQyhe?JeqX{C%(ko^Ngd_Ibo0!jFT`NkLP}3v@q3RS!5FRZgugbO-TWE7f!@}&W zt&guEHJtJ3p}VF)h;ryKHUu5gCZR*2K(wvt@57+By+Gy))W+7{>BQlX_5PmmgXvH@ z<8L`K`aiFMgb1izi+MnXwG&(^C#Qn2q`KNi*5v^)RErVTUX&i*8%wH}H@6p3ykQ~U zmmwuUn$_n>(%M7Zh)VvL@`IgYP+@dxEN$i9gi{Kal*mgguDbH=U$;CE0ugqig85EtONJ9NRV zNSN8PFp{?N{8^y0^ZeoiNoPz3>lNu2>Fsz{#%-)tjuNojAL>WYA`#&V3qgVArd7|g zp2uzQJ4B`YeDhSBuVyfPI1A5_j!j$F0*WcFuHI!#sZmQD*7$8|Ig2QFwBh^H(mCX; zagostS8~JSOJhm?P*spH*qG)x&@-qN=nTobz$^C_nO~|x0r~Ii~k3V!1;}8n@qW&(ctKF zdfL9|n%zpD=6O-&f4!R7w=M9`?Mk~5HKl*A)X+(iz!8x#)dvp^+xzvkle$og&jP}G z4UQd{Qq!-E=JZ=CSUI`p<#Vk49wWeLU~r>1ms(3=`x&z7?_b}hi#&sY!J*XeUZ}~* zU;LdHLdxxP^rJ<1AMmsK(z@RAlw`dah?e+=28X_E#ISw_jzAq)w29Afq#)pRJbT^+ zU0+64VdC9jE%A_Eal7CX`I{GC9>WWOmr6>tZCH+Uw3aOPa(!FA)IwY;AulCz^S!>X zQ_A_HtK%{hY7v0rB2-VZoVL_LXvC`QSSHHUbj&ico|3f3;#0lR=-ayu-&YYJOyTPBP;a4I;_Dw$}sII9g7h8wbz*kqZusoN6?pSfd zK0JKTXD-%G@q*tkf5uwGjg0MCbf(t6c*t*YyT@Pg=7Q$ytM7Xm#X`Bn;nicv{rQg#MTFA>L>aSch~sb8eA#trtReChRd@!guRay}kC+l~GC`e@-2 zKEn7S<}mO5H{zy8U*Nwfw}a6dG;(K9l1FXvE9C7i6;sQ{6o|;^C&xS*)~DZOA1nq2 zsiTgoTDNX);mDmV|qJ+z*6S$Zfn`>%GdWvcYew?a7&3W z$&zmUWGknG#`$jMRv#^ONB3*TBUu#5FgQQ~#-TPm<}(8-3Rb1qqsC3<-N*knIjmt^ zJUV8(qm4-!IeD!AysS`iE<<{SgyhY0ujilWzj1d?sr+9=Nmww2`A}F|cK%RsB{v*Uuly2eq+AL?3XlC!iKT{-;l>>Ur@H`>Xv;nbeiJgxgn`5JytoRiTlVdVZZ`=Y5uM0Jy=MuM5`ASR1@gY2KToVS)J^Y2uJD_pMpwgPj$u@5C7Ghcn$bS4;nVz zx~5K2kn)g0wvZhkxW(Wshj%x22-oqbbM()Pv@a~l4n(JqL;WxVzV8;#i9Od@M6vA$ zKP||VBy8ZQ0}P^Ae%>j3wdqrr^4+ndMxM{(MboZdUQsT@e5IK-3YXoP zN1^4`y0M91&8@)so^Z{(&BObPRaJvrkQcBB0)Ii6XN z3)N2J6gfr@ZsDU@b)#VfJ!lbg0-d$}4N?vcjDHHFvYuJ?en;RkDvtD(|MJe!K|5(J z6FCXpHPP8_S>9{c=1=DQN1AmAsjofCpTBYA#?;?GgN`7}=G9+*fZa&!-}u^KAIjZA zw%gZow6|N@NxrVm9xtR=Gyq#lB7U*L61Wg0w>V3cxsgA_mrLHYprtpu>{D**-P_Vw@Ma5ciNG& zwYGY{8X)T$=dU}kA6I_+>z{v1Z|S}D0`eW9sk(=H+N6lskxrU}`(cj)T`%*+EX2=Q z58s}KWZROogCMNKh3g6|lgPk487l;-Jh;(93nclx27-EX~`9?eUrrWVJMe8`* zL@mdcwOVuf0ezz{*Lva;(r7GGYN7y|W5eHV!U%Ks-h+Wie=MRnosO66pQiI+QRkt{ z?-%4e?HpY%shAn09rMFD*cdN=<9 z?@w2axpil-`%j0FtvzS-t9I(V4DA>ltZ`GmZg>&I=Pywf-J4I8)wyRV-?JgwuY z=?xq)3}rnpd7XhDbuDEP+}*RH4;1u$^GXz6nkj*#**ifo^50=n@j zv`n&2#kAm&#L!rZ#1A2?7#UOc#Ey&kvj;xSn^*f$u&aEUl?g6d)iVm`0l%afDIG1X zR4Rc}8ndcIkX2S1iFc)EYYW}VqIHtZFUhO?^q#(zqA+RQYh9ZJA!lhhM9s!~=T`}o zEBi2SV&|xeK>X&_NotKEamsW8ca-QdH_}=Ir2qO6;Geg796<$x&NaV~_>0?zM8E5P z9nP${hl$XK+~YRgRz8PH4sdtAtowLSl~zLS5xgUljVEH7@8GMdyD}*wNUayjSk^MLu}qzuWGE0&iS6k(dEL&Vj20h=^G|D_P^#EiH*>Iw9ZR}l zVPRETT8itI1rtn^<>j-!E0Mpne_ul^-e=g%5*1^1q9D%PV;i&1=CV1HNXvhlRo-XG z9BIQXSQd!0skr2hi)hLn=34gOof2$=zb?Fp+AExv+8dAWWUSd}Rbekswoe=XLoaXt zgrNMp(9)C8jKY^`-O;s5mxa$0HEe9)k^-cHg1=PBu`ROt*saB)?ltjkaw>V6-15wz9_bB1i{=q@tK0PFdlDznj9K`IiV6bA z3zkq=#XIKPtP+G(8;q$ubsTW3cN&TJj%}w@ClGx>x)Z)D5pi_Ti5#2ZQ#7{wrf&qc zA$!Be-{V>HW#s9H{?so6XG{5dE?tCB$1OWMR@+lG9^HJ1$psWC#+OW@#-{V`8q4X_m`;7}tK62cbd>u^ug3h3BYxLF!N?V0QP%*;%U$2Y&QyX$0U z+wUWhOI1?F>4aj!p`=gBbID(8|0+egG2b}$TAE|Rb%0<&uHYwZo*^}*TuhEpHCcGTUXlLeM7f*+s5xgtooC%0=6*V{RBq zSb6`i^Re@8rvw9=QaFKkWSvd`8TB)mu$85ZK|qF2;!AcAwa>^9gIDl@x_R8OnAMo^ zABSSfhffKq55JFC-2TNO)|O=HwTOC%)WQB+o>UnaVT$=6)@c!t?ZHC1bRSw|VB=+V zb|xtHdgzvhVbvBb@D~m~4YxqaC8dp3rAmwvnmU+0wLg%+hj)mW`YBjTp50<7F1*lFffipRJ=kRaN3r)Kz~Has83rm#5fGjM?1f zsEP0FL9_KyH-E`WhWH*fEGYQvOw$7ryj^cg%eQK_y6ZSjV{Z(S7Iz}))#CuD71c9- zzA~TsH>^T6VDpVdQLX}7KImAAPWf0X%w_nf`W}iMnW>N0>uc`BjL@+U9o9DlB+ica z(s7QTUEK%pIOwe_n{*<<&nK<8gp?fAY^9EQWp__M%{R4TH0Dl+cKXlQ$llZn?p9K+ zd=}hg=*#`tSYT)ilF1NqOa=!HZ)1P*i`#AF9Vc=X!KH6&J$?T0RA5fM3ix(#}d3Ww;_jBEKlV;9v zs^^wbpcXVpbiWMWt}@S}&CJe)V!xhuc!9Q4BtBKMixQ7^3&<-cK>3vu0L8&f^Ls(= z(aJ`VD)%?4S884QCAP;5WA6Dh7g*P?vYnkzUlvzZ+FMi5FlQkVb#L(A@L6ZRa@7eb zp9gp}$r>H@v=n>awhVuMs zzu`_>0H}t4eNDDX9;P9Ce`Rg^kg^y!h@t!VqS7sy^TXAwq1hNZ=t(@=SD}U8%l2v_ zV=KFbe{XGdqoZ7tslU15O48mOXkf~CXqj;j-%pq|T9|cO7T50qNy_(T+`96OBLAS) zi#5#U<8$Wt@ei+idhW`VcjafsuWk-5)$_*fs2Ot?>@x!8t#v_`=uDK<;@zmgfx6Tn z*CYy!-(3FVjwVmGr{i~qlNVlD84Zb8A7HO5cLp(SAvx}SW8jheNZ@*h9PWxQDWcvm zfgt-3_3=}rWF^U%Nan*ofA6!3RuR0=i|$#8pa0OkjUQIfo$;LXC}D5(^Ix7k4H}z> z&dXrPk&%tpbc_xHX&UHM+`mGX0}BVJEL^?P@g7rq^JI5N!M?F)jVpWXI|&jj^t><0 z28_iy2ft*v;e38r7=6O|A?jv+6kTl;Yd$Qo3}aj#NO|xior9v0ARg?!6+c)7v(IuT zsKp;(!gsv5r;c?(OkRowfJTESXf)MeIG<*eK%k%(?SD~sWi>nA)7Kt@i|5(S`fm0L z+9|qOXn%6N+W}oKRqKWaHkBC8^UM;+DMjU*0*5e=ct3Ld zkM+?vS)>H_uPhPU9tWu4x=4@tNJmPb>J-)F#`hnt(wr*DxC1=eXGSChkHbAjYCPc1 zf4RT@P()4Al8LYT+&nl@u(r3|eW5pZ=H%pPn!iZ39!nO2m zQUpjz#e9d+Ng&+;nRS|#;X-QSm0eD?b5IV80GKR~o(kNhx@g+9*_@6PAp7=PN^&S^ zkdXgwkeeidEfWEg%79F$#K4ccvInvlK}Z;xGRt+idQ~Z_(IH^f$fbP*sZ`Ay#u8%03gK0kbe;}HaeG-_4XcI z#W~1yWdHOWAR@wu%in5dA!U-9YX@TAdUwAtj!SUs6h)pNN{`OYM+BYU%|lAUl?cz< z4A-(ET*+nghawSaaztZjB}g3<%pXG^zxRW&g8$6|FeCuhQYV9i`owjA5d?|x@pOisZd=iCHBUN87WiUAC^}90C&FOe=disMCc?Tt41L}Qw<*X(AnB%2JSt}L z=n>;W#l!W-8urzS0%}Aig~0?1Xndi80}B8S>|RN2fngv%qC~(1Rt@y~ zVCTWOqkY&XFYmd}b6f*#%0vp&HUr;( zsOyF(KFc!C$j&CpuSECNYsIVegj1eD4xMV>zx_E#CMF(`xzV8fED!%xq+o^;Ni}bR zu@=EyL=|7Z;GeD9~9F%^X|;S&Xelo!HPRg~fMHDgnQnqw-uK5$3%-Qp=RJ?#8=f}VKbR)8Yzs0s$13ZpUCDd)-@ zU)?_uo#?r%(UJ=TUbI`Gyu0Y&ee0SSO?0ON;Xiewynt&Amm50**aaR7yaSEE(1pj8 z*yhrwZ={j;^#k6(Q~N;5oQC22;(n!_pDgI^Q3f0@@M8aVPtIHKFRvEA;yLYN|7dcw z{g%6!va?+h_WtHBnYyOraq+T~mKeUt5KVq;!Y@J}OJCnTSSDA@2n0GTa-&NoSl@#H zg@ucENAuF1p^>mpa5)AWo0kCDXxz9#LPHAx@do;5gGZC+7;hW)hod<9R4rOJ6lSMQ z{kYErRh&L&rmjl?jXn(B8-hTR+L%bj6|f|7{W?|=F{|UoiADXKncOjsbm>d!e{N;` zD?7Y!t>dmBZTLsjqJPKE6#9y{W9hRYt) z%Z(SC;K;zbSk1&le|yK>A1||kDf9iRPgGW&X&?-x!0#Ae>3QS zKC^>sFsJwgOSZ6Hx>m)1&HIzWsh8I+=8Alk>e<5OG`_-ozQqJ|(OEkN-cn5V+r0Uk z-*BZ)&9EyhWScsPbXZVQOHMD)Q0kwh3}! zChVVAtq8RUJ1%p+Z4aB7qB);QU$V)iMgZAz6#E6auG6m1?g#I36D+SY+$DV|UrtP6 zri$gT$oa+Kp+6LTMU-ORD3UF0RJD0$x^};ssPdbe?3eq(jj4j${Oa z1hK6VImXz%Q$QLqZ>8wHXdZLunK|`hYcGgF`&6g&4)g=e=p;)p9A4^kr~lbdC3&}2 zC0A8t_ZWEuH!q%&G`l?kv7?8c$}LJWji{Z(VBlY>7lv_6$%-hkfj_oc5B9~jgb9ce zafVM!+=mNZvJatBJYi0fFC$1e*T-44DLA|@>6HFO$`*UED*EAx7^y6hco+<8+B}vz z>o{Jxwv!_$x7^&>?`{Gq1yUd+c0ac5tF56ON#H}jaGnL_cmhgvLyReRVB&$>b2o=i zw2&bx+%Hz%(rb9{&*m2@H6CI^Cx4S!NKY;MHTV3z^SR}4RnXT4&&Lg+pnwm*#NSm~ zg&dncc#X;>rs)zvX99V(keLwF=CH$4Y;yUAaOmL{Kt=YWAUxZ&_}we&^ftJu5nWi? zT(2Tr#s9(9`&AVB;-3;gG8F-H4}BKzK&tCW!>32Y$QN{_NO=9dzwhXP4|5ami=awH zar^C^oCO8zU;t`R@LiW?-tfYPr63=~X3c_X`W$-2dA_o7F2(&4YYQm$s}~(4c1ZM< z$dXc3G9ii(s^?kk!jWj6Y^(T7>&=I@r;f&^WV**g_XVobcDABBgEmBhut$3}VlTSY z3(vHVZVkEZQs0rny%M_r_YQ!v9bxpUgTYrBRznq*BBE$V59Y& zz7}PY3Cel1GoTaO$P?jkzB7(4J85Xkl_Yq;oEm34iJkO$9is=X(OgOAvmbp>hECk{GlXn9HMx-p^^LcYj+cPK ztoMa2xQr=TU94DU-#}bkTqw^84t1#9y9&>x0yUcV8?*{K6~Le$las&uBtVJ{Cdgt^ zb-8}s^H-z7?)H1fuZ!%Lu^9MW_hOZ^L~VIAwTc}7vz<8LhH1JtXuoNHUIUH$xnlzl z6IZgn-j7WSs>j<^MqeE-`5TfTMTVF9tBRJE<=X4NGQ;G~c%x8!&lK#FM86|n0IA_8+fG^5UV*2;=IpBR00=c z)xN4ztE+%#e>jP2|9;d`-N~{I1~Tj*sW0L7+~pp!=Z9`K-&l4}2~=afrEQm86W>)l zB-6TnG8cMeA9UtUnVcrU8Ndi-QlroEYu$#JS+_Uh&gY$^nL8;F!{fYD)&7n@L6ZH; zN6{DCi>$UYG$S*mku-C#RMoJ6=>qg@=yEhdh4^w{$ixwcQH# z<6C4=r1{kyJfNQHjx#`kmPrhoQQQm){&R=xN{bFB?;I;{S38X76+BHMP_p~9>tIEo zb2QXd6~T?7=BOj(%$zF*(;jQfZBEvtAk#Ve60E|_Q8bdyn9~{CK+%d3K<|Yp%RiAm z8>G(ZrIVggxN~Q=C*omyzP-441vkPCO4x+E+_fhlnpJWJQ-W4dF6*ZaYK6+6BbRKe z#E008A*GGQ)PcvTZbGbcaWmMm1UttOH^v{mE@~0_0V#-4Hi(yC?rPGD%Z`zBRw>Hg zxaeYKuFw9o`r!^2QX-`O-~8cj6OTW^Q)h9_+BcYy-jS2L~hn+(>oJTWQ>X8&-~`~ z@Z&!?;fyeX7W|A}X!zuOyxhcutiS%t-?XIyMjUE3in@{67{|Z)q)cuA{EpdtYy&__}j7eB1_bU^)QfCk)hl77QSn>A3 zJ5INPkCD+w$!UH$U#=!_|KwLxP+%r=VC_8X>+5AWaLEiWs*}3M^1EXs3V9bHwL9bX zW|2mQehl9$@|X9qB^NW?0SvIk-YD-47rrj1H()$CTY30o3%9uoam7mo++fwr^s@WM zBNg>y(*GH#Cs&o1(XhH@EvVZX4s7VLxR5P|`mnQKG#n>tuERJbJk(u$26hszri^iq zvFZ*51MVj+=|1Z>pJU*-4epl_b&ay5!4GRih=(Y8hyHb^NQ7N>6YfS6_AS@^G14j=Rsm z^WOBtgX&U1pRf51?@%0m15d+U>h>L30WbS14q3GOi9X!>aGN+hTt`CPU_d+AvVD{l z`32r{gjPck{$$d0C~|}Jg`HFA z#V;$3PYFkG;Yzu4avwPqG- zG((iod%e#(;HtRi56!{9CsQ|r)(&K=sv@AMt6eDnm^t-Oro^S--e=z89&Zi%=v*bb z5(6{3vok%luJfaLmba)*te39s%fkr2fJQ``=#AAk&Ht45x=T#4`M`b-K^VH zqWFV0>N?a?27h;|76)8oR_-HUmt{j(m8pTeg1B`z%FQR`7y)W9)Dm$rfb(vgr?y+* z%C6ldU*6Pc4+am*qcaOjc{I1?E}0rO6*v{+s0ssdJxW{-zCSS3PM$@?m0=2<1)@p> zf;QdN`hK)_GXL{3r-Tx5H4b5TXKA@=ksbJTCni6xfB4wFv7t)Grj?70)3wMcVqhyZ z0U3gWi)6*RbLgp4bT^`(<6O`!?0mS|;l)1~r|;4SdzZ)RI1zevjg5;0oWHdQ6C&zo z*@A*C&wxR$W~CM-q>YO8(Fru%%(j%lxLro+i!-Ml4~a#xPjVx!C~&@SZ$DpE=V0Ac zijvUfzx-Ofy%KIa^Q#=>--cG7qE?R*)2OMgoPuZGa{6*fWh+tcMg1-vtPb3OHV_}% z<#gj$RV-BuX72luYWFw4lk_9<_=bNJ*)LvEvGF)fz9F-aRk$12_sG8(>CwBxPHIA} z4y+)k3r^ZZ$yto!^j~O#v-@$E7%Ck_#tpTu)PlV^!g#GXVy1Iq+z7S&y+E*|9=E|e z!#RrBN`u+QBOfAoRa35}Kd02$;ij-I1O3altb(BU_pz0})egLH-t*F3+puiAa|jE3HG7*2Tcyy8GiF zp-0R<+$E%WWy{YkHvoX41pT)T3=x+Uzk6w21$Bf`XDBmSOt(ibN5r8($KSUImO`~i zQ7|_jF~>Zxg*flvdG_qtBbXDZAusn_#gXiiHtY5QW6HBeR5#i;IgMJ<%a3pP=i{zF z|G-QGwQd%%$;Acg_&Z}c-l1~rBV67+9^|9Oqfk$8&K;t>i*#xwO4jbO`BR<#Q58_? zbJ3$r1WD3lFWt|^)6q%Lce}=&!bkfm>{p}@y7H-s@faDDD0QAT56EidcLI6jYHRb}M~MDne$l8)?+UnJ)#f8ThX>lhu`Z*G&pa%NxcgBeayL76_s|W)h3%Sfn^-*y4TJ6otPOET}V>Nz( z5xDCvnZNgwBO-eC(S>Gur%604GpGl?;ZL@6$R+{m9(0gZoCkOeHnI@by?fqm`3aVX*SssK*|@mL{)ek4WRlWop77N&nOyG4HLYPk44T z=jmvA*iT&bU(_xiQ4gg;!}Y}bLMoXPA}S*yd5p6y6Vj;7|7}kTDr#!mJgWuy8D8gz znBooV$BeM7szN-FWa@|gDsXILpM2XN*!#vHiw;6*3sWa1*b}BZ_ZWL(NgMxow}Hod zZL*|Hkxuc0*LD~NRBEh09v_)Uen~|cM`@ly8OH%ysN9H5_D+SnUt)-%TincvF_!m4 zWX^TIm!BS$R?0j{pV@Nze}LFNAiH{96vr?AcS4$G0@3@G{&bGnaqk0b2vk8G%E=Ng zrr3Z0;4xbKe)Z7uFgu95$lsF`5(sIm4v|1D^Nm(esno4a6Z_2ZEGhvpZLA;SFk zYhol6Y${1Paf$#)$4L;0B*2k zj7Y~M_pFtasljdx4kE3sL_mmgGsKxu=98AL2d+f+_6Ksgxd17!xu`&rA95iqdw>jjN3#( z3ygVXsRT~Rp1d@5ZF6Br>R&T`Lo7OaqxfF86f5%PtCj3aN@MWBmHMuwf;Wtcs;5G;HqPls|i!Tp!D@e!N3C7f!J?=W!Rt;1(D9udI%w73`# z>)yAdJyY$(2;jOI>i1r;%=2x701b;gT7?m^pMUy7M}?Z0*@fiqejEtTsF@ih)7v4M z0c7@{`P_?3x+z`^iYR_ZT;t_ij>~^k1|*c^d+pk_kEhAC`07@Hoafnt2*CmHvdXgR z@h&csI$-cwZWNY6ZD!`rqN+TXM4}sx{zv^g^`4dvM~rAu*yzxoXHH2`uTP|LIcJjO zP+dF8si#Xk-L3}e@rzL{ac)R60$~Zkmw<7!(nd;3lYkLieekQ|eqJ7*;te~0MSJ<+ zGth<)Fp_{T%ay-wyK}J>-I@#~|0&U$Aj zZ0UzbD+rRleNMjX<+oFmk(-^u@~8!D#a-#&kF5m;lHvxrb}NR;$5Fh+QLmGm{1lC% zWl>tz$@`ySy;)Sv1*;YA;ABisGa>BOajAw@4u4I#6YBJ5fI0^Gga~_G;J`eqz7CW* zb%L*sdI;l*{mP|r_l7%6JV1aR3aS3rex$9Jku;r`Ae&B1Zsf;tzYv^b<52-l?KC$K zWw(4JvD3-lKQ@rZppZe>07-16pSd{zw*}8zhmat=-95gTHsM7 zlHr04sFZd-yso=eE$WdMcYX@85H6YjkXl^M)GA6^x?#p_aXVHpH2bF^Gw;90 z=_k6NpZq5|RSW0wHVven4_o`T-Z;60W$~tF)AH13?;^$Z52ML?P5PIgt_Tno~jBnV5<%N_tatza&%_}Y!ez!YqUin-Pk(18c;g4 ztPwv;*=id-PT6!$_Q8oc(>*&d$XJ$AkK=Ude{ukWy&j1T5P_P)3njHVITXRqL%bW1E*zz!!0@ zc-xxBeD8bw>GI^Ty}A4G*?w||1ui*VX8$vTu(gu~cuSA)_0frVi4>zO3`ade zb&Kd7f9n%(FuqkL-Pm9+e!THwapGytr0jJlVL@r|JWZP z9lZp>dlTd(Ja`}5v2c0x7)R($=c4Hc>>quGdluacxiP=K<%KEIs#~QM$Uj|;y8~FO zYgwzzPuTD?2L?%}0>pytQy94|kFL8A%Vd86VJy_=ryIgQV2C72k%A*mGuHkDP_Zv~ zQ4(8r|4!Z)cxislwXty;^(T{@iZATkb3R%dw06g8*v7LN8%$opiW^#JpyHGF5Lhp8 zLvaYwFDu7UH>3N#x=O6C6=MEmm5kZ*gLZ$0!+pzk3=wSn%;D!`;Obj;s3b72?5!ZM z_v?uVb$AdI{FAU)DZlXn4Vy-Y<fay5Vn-H(OSldpD&jX|Gziy_JQ##{UB^?r zEo|RRQlLsqp&zaFO09D;Z`?i72vk3J=yVLqnV@gtZ_y$w7*o#k_n#_t9$Pkpl+;h& z-shOGL&m#KdLp~n6IkeO{gC zj&Vi$=i!go%10ja3*j2ueVjL315-E4)Km#!7}vR zaWG?_pG}OOsRCzt>$WB3OI0m7s~4}1>Wcuy3nUHVL5M95ga~V)Rev#~sOW?J>3g+u z`X`^FrYW=M_2JXJ5GVof0SPptb(=eU2pW9}VGoz%ITF%1pJOSS-EMk%ULX1Y76r@B z@TqeYUIbh(j;IXV5IJsR2jrIaf|1)<=&Ea-vuS;+llz@|KqQwb7C0PDr7};$Su)&{+(13A{+_rrKFpPw*63+Tm>&7DR z!6fvlmFH^udUr&daG_$rReTX;Y0x{=qg-GNGK zS`;5vPYU|H<^_hp|Ni}3njM2T`2RxJs0DW-_ltuXNS09(aJm0IK?~RKp)i7bD)FGLQ2(` z**{clT8+a$8xzu~=-jmg!#a`)LqXL}(iAd%e?1GzfwCi#@VL`JY+8;E1+cOb`=t5N z^9LWcP6`OYI+|S&PYOHoAtN^_f_s!nw-{(ZvhWF<;>DS&+MPDP`R8+XwhJpq=Mh-1 z=a^UNB+$2mMqoQ9TKAdMM^xvki78s`Z0B{gbRObLCvIO7B3jmy*sq`#H8JqG53pW1 zc!)MTPrRS4=b=XlX~jzPheN=dRJN40^zV$*K$!>=7$>T1)>kwG2eFMe+WAbzOIvTW zaOO!PhDc+tL9V#HXJKW>jFvMKQ3Q6!tHaAM0opg;VBd;F@-6Z&=rUTkVCGMgE_fzB``k z?|=NHuMVW z+zVwzAE>Q+NAbTTi*ZLx3ne6IO&C1irClah4rLQY^vsO+8sC3g4q5umZ{~v(74x78 zWIc;8;==iBbX|9%&bEYL1l26L61DEr0->Cr#UL|)R36bZ|yrSD~4{Xb?oL0K*+x+l>TECUS3VX;&#m@b({>EY`JjOK*2P8K{wb6>_TRPN>fF1$w_Xk;i|i zz>R|Q5hP3MV&vyjE1zkP>|M?6c-z=@IiTM1slZa`$jIpK0h1DhCd-%(bKQ^*HV`l) z++S(62vrm&=&|1!g&c6s@bc_oYf}l0hyHXogR3ty$6)JicvV|7cMbm|a>yDC@mW_O zVqpMDi3S$dWX}b0eZQ|Qo{+R>n#i0U z?B*LM;NEitfykjeWh1l3O2TvoCD(4uEolFq6gC#^38R|~&vbL^v`r~2lbFM6;I`pb zNKHMh>)zfjPlgh_TwP$ft@3m%)#18sY;aIQ;4k6(uA5=s-aKv4WzHKzynHF0*R?I0kG^_W@qe2HeJ?P4_g-+ip zL4xk>+bPTE3b&98;?Fk-6Leh6 zBjM){8jbp2bw{S3vH*k&lBdy>418*^xe!9;d>$qQ3X_tPg=AGtOe7~^0!GUnts{|{ z0-`^BMdUDougHi5@U)T;YO3F27s=m$qq*K4{p?0ma8AOBqVy^YvdQN$6pj8{1Xj?q z7kVEk%w@tyq^#F}0k$zYSI9Xl<=wHBTNjjK7}bs_zC1lpSn$^bXM7ZT#)lR%Uv7c> z={JbbEzp^DqREJ?tYIY|3_2ok(v^;_&muM0q9|8 zW+#YUk6c`W=8yiC?#Z-9xrVOfV@7aB{dY%dtw``JAIkq@11MhKs0|nz8n(rahi4Le z9yQlCa?NzRWWtJD=!1SG8>9i;KqFZEL@KllH~fa09X6k%KsJs8Db zTzXSha(;iin(+V6eb$128yx)o87G%V57c(4_KP{wIr|M`xgaZxf{*C zxn~SJhm>OL>+9+FkEN7BbdGM%CHhqwWwu{L98VWUB;XPFviv+<-zN#xUkUfdxQi!2 zOla2nX=elXr}GFE%?qmT$eTBBsy=!Yye`ID_2dc9*@!8TrNb~Cv<2`VhS~Auv5AV) z^=RlnA(fX@h5wleN5mf?1!0OCFU??)`*(o+^43LIHqo*=8&d!sBGb&BSTY#R=>0wR z%4f_IK>%eo=mEGo+;|T2DRbJTt8HrQ4%EWq#>`L!Ez>)!&s{?Mv}*lv=C}%c1#>?< zkBe}~C}lQ>Y!fpu@oaH)<`LtvlybhQ0t3ip11Bsvsfs}8;kz~j2A&}XduA*(WnCgR zUlc+8Yt8@6dz%I~+YYl1*PillAudAKrw=Tf_s@(^5#ZK#^7;hN_PD!}n=?Nq(MXG4 zHthbhGA!8CdQC2W{YR52ftR`_4^6^jIuJoj5jo*@-hr7$&rJNod4oVdg=?z#1Nsuq z9%7t_#3?OGHh8mTFZ-ldeiPLzqr`e5&tpK~j5L9_?}}dEd&Mwc=Y0F0A+2mopJ4_~ z2a+uZ{`>CrccLyJ3LIt*3kj# zQ84Jb^~MR|`}swLp3lXLzKKES{ ze?%@0=P5sua0zh3hshXELK*H!cL|?F?psO_DEk%_ta-Fn^$P;n@Z|(hs!P(GPiw(2 zgq8~~EG_+{Ky6(?o^Q2Na|n77`3*lkm8H>Zn7xDy`>;A8UCn_&az0GBBUBsRXPd!P zHBQ{CdEfk<)D0D~jQNhKz1zfseHr6Ap+m4+98G() z?Rn?woBjhI^z}t|e<(TLV6ZQIy;1hI?(N}0RslguV<|hq@a||`^Yl!b?~`!94k}%I zz5_)2@3bu1rW4Abf%*cYRlmL82G-SG2L7`)nlL;`liO2gAxK0qWO_gICG1`hA`5X2 zJM%dLxD2;~WRS|%`8A;fEhh>@I1^E>O{V4VHX}z9)L()Y`^Y?~(0}7S7J?h`N(u=$ z&9_@q_bmyO*{XJyrvnD`i|m+MAMldV+q>0MIdDJCDd~?#PhIuzw_G_FFO#sI7;o_Y zalolC`b7sVqE|;X@5>)iH82}`!(gZkQ)v3UxHj**9y6>sS+&f z9{KFEgGL&X*hfklphwM|cjMRQm7n^>Mysj)OL?mIh6|Wb>jKLyKk4bEiu3FxM!x0= zjpODI~eMsCqajYe|=9Jf8Gbb$#um2va z*Fn7h?1~)xF=_K%@(xJQU|q{ryoazgV;}=BSXP~*UVUCXQT#a^@229nm_M`eN%PN< z|7jTCho$lbphWlE6RTJYy_5r*< z?=$?w9OQ;*(-#}y+Dd?qZ!zl?j!mYO&7LMnF*!ug=jOmRA@Ggnsj$)Rv%A#7Xx<0V z(VPizJ&ZR4e3;OUo2-@3N14_IJW6SLW$i{;Atg2c&`+u8r`HN~$R%C3>7FwK3lyU4 zYgBNAiHS)wIS2lhq%0`L9Yz{f%`v znH48PJ7ottUNHVcdD-(K%Zi5Vi&30B#TPm9cI8`sSYPtV-9NhyH&eB``NowKQQ!Y2&uy4#Utm5On z*&x(sm7lDTd%Vok>w-f{*b@FKK^7Bhr4wNUTwuKho+sQxZ4wQ$eZ|zA=7j|I@T)0A zk-AXa^j;ju;YGDQbpMq#ME&ea+INS^ntEdN6WyTA>|V1hArNd^gnisVhLcDrrKzd3yY#d(85$+`u+S@0PjvxRaDwV7GAli}?rxRkOK3syJkEBcdj}5^qU$Cf z3da^Bk}^}zWUeS^@MaMJdIbC7qs(eQx;O3m&jZglWo4?@@74H{Tl{j}MCW)0-gczR zQc$S1dI4*m$*;?PWEeu37$xiMq~%gKSEH2bIUy9^;?uZrL!v50dhe zA3eBS4nMyT+c^bn^}}v@kBobTVjpXDy^hsOjkj&;rw-c;+SLDcMBj}>KUo*o-D!3D z{qeOP0^nNdnIbJ8HXDLYEuepGGt&pdJ??T>;^}N=>k__+_HTUl14y|E@nObFa4uJ+ zmiTY=?`Ndn1Lk#y#NED*P9a*$#k9J9DVWPS9R#UA33lz;TfN8#{QUex5lljSlnnwI zY@I#mR+dV_iAItQ4L|o5xMkGp_FnbNQJIdHs9NinkjAzkaQ$1x1B6%wW<~>A6paDcYLU0m zSB(ssoM0Z0kW&1^@zy1L_fL*qv3QzbYP@0c<9)eWo0qYm*FEK4h*Hkj(k+mjni|H4 ziz_8da`;)vv{6xBa-P2Y?ORgmum!0VrrOEL>_5AwVPIMB+ZZx{h75R{$!7E|*4!2? zN7~Na&CB^oAJcJjf;r6?*uw=c2$Z^F9L6^cQX%RPxmP{HSlp$MT&X8sleO+G2hE(* z{7^%D$l46j>{?dlwIB#m*Y%TB3?A+q5@#KhS-_VR1=t@(RR8Y0j$SBI-RKKs1g~!{ zHi6@oxnlME*zP*Qr21~QP^MS6Bq8!s`yIv7cK1&4|7nU66aU(@e-p^e(ZHM0d-r!b zo`jSSn46m?fza&DBh4<`B}1Q#OoW$}m6fn!z`wvxY07BKS@% z{O36lBPcO(kwed_PU~-^SMmax)$QFigWHDusCID@xuZgEI`=mYFC2V!p>+{q(!&@H zFdi<3lc9f2)=?4g?ML)lwJXeH9|y9&m($Cww@cTShVm=vbDCIsCekxl&kTZp$f<1P)M@N)7p( zD-mBJwJ$?(kgQmW)HRI9(piBH`-(cmasK#Pf?Q-!R?r;hOw|hy^5fywd(MC255mM( zY`f*+t#e#KkBU-kr~UQ4_qDDxn;BA8QLHH_mc;lAcgPqspM5T?H;?%RZ!sEM?msDB!FwU&)r2fR~%sbqcH0kPR1>rR^`X={J*? zc*Qzsdh6CLgH3$Fgb_$9k}0g2a)C$vj+d*A8EseYeJ*sU=bFe#inon@5+MiGFCxJ~ z%JW-wZ%Ur!8CU|Pq&G> ztJE%b+F9#5;m0{FVSzaQ4o^lNbWS*BKaLe?QI(Aplx=*JFnB8J8<}*yJSUw2l8NNl zcWo5w`OQz--w9&FieKa`re0G)gh_;_KbH4UNz0aBZKmlZMqe1Vm)8;ib zH3Nv53LmzvdGs&8elw@JkFlb!;%CzX@Nb}j@x7F}`K(tG+^yn4Z;l75SdgKMii*VJ zkp}z+^BU|=uV~M&u!Bbt6{l3a`<&fM5s(ae+9hFEbcaX#Z`FqRT#Ve-2jiY8NYCxS zCA;mUJ*{ppT~kl?u4;UpjCljOY-1xUKGQPZ7~IVe$L>n6e|YnYNZH57$CCf6{hnX% zsFy3%nEH`GR-W?W@KBwAIE7CEP%Zz^Bw8NVlzdi0id?9%UN zu?(VJ2eG0l@w0Dp|HJP!y@#rR4oqn9@9ybYjwK>F7-CO|ai8_z@nJHy={x57c<|*a zO&p84{?G(u-D^l?se>5jbh)hh_YS40$wsV1TO1omzNsM{k&hEgB8hO`506y}kz!C? zpeXA=cCrIPS?Y^Oa&HdL*b-Y94?qN2$Z%EtFB?uvdVHI;h!Y;>D?{DPfSgS+8={)SRlUHt6n;!=#`?5_B2*KRngtA7Eo{dgW0zZgIU4~M?>1j~MhKGB)Av$K9f)avUB$>cYWqD4{}fZm)e5HO%Z>*|F? z&lBOU4#;0UH^ZKJ%F4xSRku#{-fM7TNL;-mC_?M% zJS4^Oq-e!d#n_&QYhx*k!%D#SIbi|D-NTJZA!H+z;sGZIeQs-h{>N8Qj;5qwSmLN= z)W(0lDti6zW7qP|@Zo`kcuxB>&%sh`5g#?zWMz|_I!_0FZVJLCoewcae!rNiV0$~! zhypOD{eUQ_g3bC!V~DzA-E~vhpf>(bQ$2w#O%uW>`|$JU&sG-KHq8<5;ptCB%*e1u z2wNh`qxtmYT40;%3X}b}CKBkT6v@q=#@}TC$yAsT(;trxNi2n6_JNKxgb0Vu$k8&1 ztI4qzM5&l8Y2KC%cc+O_D+{|k1`OC9eg5<*+k1z=N*J6O6>PG-zp_duGOfYF<4`Tr z_mlIGct>1OmsqlJYP=npyP2l1Z~bWlv<+7=$%jfFiYEjjj8MzhoL&L`=?`e>XJ76q zaKLpe^0~#1@ET2jIWzpiqzQ__{YY8Z^UczRZ}SntHhnR{Xf@U&OvF&pqji_zKcy9u z6{h@eP2pE9#&QBQ7JSUWmz(#otzv^$yKj~KTOgDfeWc@kekOAv?t9q43B;8jIg!(8 zt8|6Uf=>f6+R@e~B;=%3JNUgOoZr#h^+cK`M^_??p8be#@jp2&*~mA(QW0%#Vt?@j z%Eh0dve^~_>G4LZq8ZRFQ=pYoJwlj7|%rUEj?oqQ+& zN=+c6@3h4C+%__|q2U09tttKSLi=JdC}OxmE>U*oiJT|-CYSrOmDz3h(idcakqBel zOS)cb^EFY0qxGtzLZ5)S;%3-1!V~no8{$NI4Xid9gneXPVaoP;fAx;jL#=9%z3_J> zVu36w*+^eI3dkFQn-a?VWGk#D>8g>BU-_3M#m`>sZL5a6x%1l4_wS!iA&O(*i(&O> z&Q)C>O<9teMA)y}+`=LUu_XvcJ=(CTBKD)G!Z-wk*9!e9j<||f%KXlKNY^h3e3Na; z%xkpWCZ`AGjluf&hG8RZ1!BUYlWPacZ{CsT>~~}hiObI`=hMn;1`E?+ML8$EM&_iH z4;3h8UZjfJY`hN2EDjywPV5oXE^!}{dE*;=m>pzb;UDfxK5*>|r?ln96Sh1^Rv{^5 z{`90v`r_vy&iI8A2q1a;J}oF1k_ms70Yb~)HM9DEudtMjEao8zui=)ym}&veZ3zKc zw{y50t*C41OQdLc!BPslyM*yE*uu8p6-~yZG`qLRKMyUFeK`%g!@M0&Ie6|nu_nk( zJ|r8KxK}#JA5aFs*-eSCi#XRI8NPZbAX^nLesH4NjpwqgdR+8FFVWqtZlYMJcGFOc z2N%#b&RD#PY=?>b!SLybvHm^b&xdsAnLpgS=jd|@tes15Un|#M%AF~B_of3|7iuCKxzurF1bOyrRkop%q3l!H9t$VSGNP@* z%%8m^O5WX*+}zxF9odfUfJ5FXi9SQjNO9W~sO8@cOOX8fb-zcrPOEz>^R5%s6$|p=n%T%l>pBZ3!pz|r+f*+ozdr!K$%Eo zLl64;`W|3LB8Fs+-_aEVW@cuu{{<6fF(0T`&eaaRmS}8jF&xv0iezWvmNP$J_%vLj_r?C-1D%(pG%19V&-(Hvp8S-T{`V`*ZJX6NC{ zHvI($|BnY*Kp1~kM6>HgrcC|fHo;40Q8Kb{3SXvNPd&zv+se+Q#R_o)to zSY2CtiUI@v7F-u|0`GFG1|KSwZ4BBzKgW-y*6+eNuy(bhk-ws_Sgg%UN<(rRMtCW4 zqZ)iC!?EauhUA(&L}W^MDwZ`Ko%_q(p14g+mhopq)N@BVf_7F61oJ;wC-59q;?Zzv2!c zOfqu$RW+cv_T0nx`c?=G&Js26%Aq~AmN-1G9TdLw`dJBs;sEQQ%><|&cQ1b{_Wvjm1W{djjHZvM`tm}lK0sX0#w*E* zp~;(+Lrem#pI+2pAsd~AtkeD^(YGlnB^7GO|1)+ctyeLYL8JqdY7Ik3#&1Ey)X9gf zG|rhGJmNYO^WQVNn-t?Q!vRamau0t^#aadZwF{Hyue|i47(v`+bF`A&`kK@dVyfxk zuS0g76rlz>T;Gsck3!h-a)H4OF%K8LHP-&NO(HbnxpACF=DS8aR>@^kGsDN7PB~{k z2%!1=x!q=4{TdPC2oQdxLIkVGKA}aL{WBNl@UlHKXeIV4@@4a$f`Q6YohknYUve8J zU5r@fj(O3>ZasBLA zHJg%>qI?=leiy=9ZZMP)(+QlK>!Lt4tPEyH!Oci);2lifmAnLJo~ z&%EmLp!0g{*$?9Q14n@CfZ}o4FOE6X-^@hZFbEMQnxPdI7H*Rhb5OM<127%v<8+PH zn#?xVm!bUJoWk#BpZ?D4j5Y$Oc4^98a-1hj4NHIbj4B`t&;EdD-tAXh|5ioi*)kk? z+V=6$WoVV~M%vg|b*^%)B`>4ge=}A!R8(x6V@AwZgcjm>*(R9&`_#pmrDg_BUn6_` z>!&Gw93^McKZ~?UrdlDv^7;ykDDmGoMxyqDf~$@3i_YlK-Ca$d-*LX@iitiz^#|{T zYeYpxrXXjCx6x+aZ3p$X+nqz=!Q5GWwqk29*pCEWwXFy|rhUe`QProZd$8?^)hL7S%z*-AKSVDpFw=TxXx-^M;oc-_Utg_$g>-5&(d=VUN>P$6F0}TFyh&!a^wx@!O;*IkfCs0oq|QQDlJ0NeyuvEp z3J7}j5-rUnk@Y9Wt6oht)DGcdh;89Sb?BaM5E{XNBCMz;6u2?2yQW%upYK=nuYi#C zn!{vJ%h$^j=%>cdMJ$=Vu|#Jm9VFe>R$z)z4;4anxL+~_Kv{zMIdb0>dRFz_qn-)z zGjc~%e#$}18lfr7A3O6}?&LPg%Z%w`R9sI|6EzEY>YfEHP2%nenwA|4V*RvEb@rM* zr;2o5bb`s`c7ICWzgikVO!0eI_5-lQOcEkFrr%bO{0zEftDc2En*0;UvlE<+<>i|y z;F8q(JYHs}TgojtenuxNqLM6wH|j`~^w)03sG>liQYjW2a`yElxnq+`sL-2X=ywt1 z00Sd3rQ`Kg!Saq3r%YkEs`muz;T3P!&=;&5rmP#hf!NnK9RrPxhtqs7XkCJb@y;xE zgXM+;&~{vl%5lF_XDu5pin{r*jfUx@M3s5Tr#`3o5;f^lj~}(}7UjMdoG;k`fPsmbP#?or&?*v6qCm}6er$w@jWB{}` zhl43_!eG3iyx0Bv%Rj!DLP2ZLmYvlsaZZe-|2JcQv3_8m39IO~U{*V$`{mM$M-Y zxrK~T0e#=}75PwYb#tg6JudJh2bJ`W_}_d4#KS-@ALjP;g2B|nhyV&QG{1VmAmb|| zJ7BgVL>RoF#{RLFj6u753rm1fh_^IFq?H~%&{{@O?!7eqnQXLogDY_f6A?g7hIWWn z=bD5b19B!X`y)fv6_(BBZ2=m0PrF>+n49TWB@Q&n$MFND%>0(N)w4p}@!q4o3%cg~ zyBdj_JeN@&rP`}vxxo;QzUR-M`)QYy>o`@!PE!uZ9CXOsX}*s*l$#u!o(SFF`}|4J z;Fj@=)x(K5B{@&i56$51;|n)eb(xi?(?WLe_db0@evLVJD-DD(e7I^O7d0N51Je}_ z>n@}%^WgnI>|^iDjLT|H-}CH;6=MM&SeuozfPf_uqb>tm1D(Z?UW_nv@reiAb< zvx-fR$+xY%CPwawdgU6mpiKJoG!63T@eTgnLg)0bOIhurcfbNC^K-=pcnKR@hsK!m~|I>pUQB*5>x<^P>Ct1Wdjj*2LlOi?gj2s=0| zZ9BR9R#4FPnplqYEwkB)m1n;{t+vOKyRJGF6xm6A`Xq>PXz4DWI!0N)7OdV;#3TwaGx@sP@K95;|U7u7Be_7%~OpgnZ=*cDh_ z+3fadm6h-#UhsN5*a=0n)DF9gf=s9ZN5sR!oVUxZLojwsNl8*3)C` zxHS=ekFmA0ZFagfrTv5soNpKN_|fRMwl<^^9!`Yr`#8Jxnn@JNpyQN>e*M-|<;Qt3 z)lI8URX@A&Pm@LFy_ASLGx7|UYtKT?6%Lh;NE`y{?@TLe>r;2Yp4_k6CN))>8`{kA zM(&K#iKF)dHfq$;N{QhC@yA!rDEy1}=g*%x8>y1I4sSmircs224x5y_+sK;(*U6+P}NuzuCAs=mNkp8V>S6@6^yLoE{i zOG3cX5nA!7=DFtWCj)Aa#KNS@7>t0LilrS*8q`m%q4C zFr7?k^cFTO;$wd9(YfD<{gmdNYk@ndok(SvrICY4u`*Sc#ah&zQsTa9 z^NS>Ka!ng)pXdm@Y79R*YKbuhY<2L(4|?;p%fJUyb%DCiAjfER79PEMNvYc1MGam+ zpKlUjNjO7twqeJaZXhz(H+=-}cR_m@^GeWkigZRCI1B|wM;9dwnumRWFkc>)pwf!U zTX{f=b2?-3L_4O-=-9K_b;s{9b)`daK8T>6IL31WMcT8H>ie58T@9*z*|-D(`$|k! zwWp3xAo&$X$H(`nF(Y*#QwS16Td#QZ&=`u((U8g;F;>J@#eIoGdp^2Ga@<~F)dfSX zgNITXEostWVe{vdm0>46N6hG^csgYo<6i#~8<04w5LGz_(|@7}Ge0vH!W z^La^hwOWWQ^eJ7thP$R^3@Su!>BY*CsZuBq@F0(nL(qjz==EjhogvVqdWme?X z7j(=pBQM+A+jRnWs4m9?!tbkJOGU4e7o5lagtPWYTa#=#4@Bl`vm&_#)xBKbP(K4V)1=2@KiN#K(@{nVg6~u_JGK^fTuLiL=3&lv?=F;_ zmHZ3a6QnCZt~2&dMSg8%rFVqUst<6~TH?%iU^dZKP=Kd1T62On8W1aD3+_VTe%D!t zz(W&(n)s(6afw_2ldV@gtnV>di#3%cKOlg)_etufxEy2}jHKQ?+3wOOg3uG4y)5H+ zuWCZ0X7mL}<39VBuPZhOibRWZy4&J)B0Gfg^`?`*lclgR!)<51${a6BxinI$3 zgcYvVWcXDle6os~GHMACz=V4QcAm~(2sAWuJsE($YR*{&8ZNdE7c2cZ>-E%V^&xgw z4R{dd7G9-3A4H){i*_8A(7?1Ctk@!y?IAn|+9f2Hi%1r=mpHu*mC#Oz;2#ow)7nva zLmjZG#6RT2wwIUC`p9}pR{C7qA#iHNzuO0EBTG{5-z2zD(b_Cz;CFJ@rT%Gm0q2i^H&kj*1D5); zQhYh`3n~D|z(0J$2u<-_aw7@u7Z8BJ>vEFJT*8=CjXr8}PFEXx933A;1P(s6>`lo@ zr+)rXQe#atLku`qZkh~Lg3z}$9x&XQl;~qyQC7bSF%}F%rUCdT6W10RobF5yXy7K9 zxdkRGC*0zK{`QvN0R|l3A)i-WdHr9vnBsLWTJ)n?O*$b0U_D|Urq90{!q%atfw-4DAlVF=P+{bZU23S7=4Z(O3EueLu;h#t zCGk4wu$d;w)w^b1!i3zK2Ik_S$s4Y~dfu>6{QwHk-Ir(F@z{<@C)tS6J~(+s6{MmS z&XY Date: Wed, 28 Jun 2023 15:57:12 +0000 Subject: [PATCH 129/144] Create template UI with tailwind --- .gitignore | 7 +- package.json | 8 + src/FOSSDB/settings.py | 21 +- src/FOSSDB/urls.py | 4 +- src/{FOSSDB => }/apps/account/__init__.py | 0 src/{FOSSDB => }/apps/account/admin.py | 0 src/{FOSSDB => }/apps/account/apps.py | 0 src/{FOSSDB => }/apps/account/forms.py | 0 .../apps/account/migrations/0001_initial.py | 0 .../apps/account/migrations/__init__.py | 0 src/{FOSSDB => }/apps/account/models.py | 0 src/{FOSSDB => }/apps/account/tests.py | 0 src/{FOSSDB => }/apps/account/urls.py | 0 src/{FOSSDB => }/apps/account/views.py | 0 src/{FOSSDB => }/apps/fossdb/__init__.py | 0 src/{FOSSDB => }/apps/fossdb/admin.py | 0 src/{FOSSDB => }/apps/fossdb/apps.py | 0 src/{FOSSDB => }/apps/fossdb/filters.py | 0 src/{FOSSDB => }/apps/fossdb/forms.py | 0 .../apps/fossdb/hosting_platform/forms.py | 0 .../apps/fossdb/hosting_platform/models.py | 0 .../apps/fossdb/license/models.py | 0 .../apps/fossdb/migrations/0001_initial.py | 0 .../fossdb/migrations/0002_alter_tag_icon.py | 0 ...r_projectprogramminglanguage_percentage.py | 0 .../apps/fossdb/migrations/__init__.py | 0 src/{FOSSDB => }/apps/fossdb/models.py | 0 .../apps/fossdb/operating_system/models.py | 0 .../apps/fossdb/programming_language/forms.py | 0 .../fossdb/programming_language/models.py | 0 src/{FOSSDB => }/apps/fossdb/star/models.py | 0 src/{FOSSDB => }/apps/fossdb/tag/models.py | 0 src/{FOSSDB => }/apps/fossdb/tests.py | 0 src/{FOSSDB => }/apps/fossdb/urls.py | 0 src/{FOSSDB => }/apps/fossdb/views.py | 0 src/static/css/fossdb-ui.css | 775 ++++++++++++++++++ src/static/img/icons/logo.svg | 111 +++ src/static/tailwind/tailwind-input.css | 16 + src/templates/layout.html | 60 +- tailwind.config.js | 48 ++ 40 files changed, 1029 insertions(+), 21 deletions(-) create mode 100644 package.json rename src/{FOSSDB => }/apps/account/__init__.py (100%) rename src/{FOSSDB => }/apps/account/admin.py (100%) rename src/{FOSSDB => }/apps/account/apps.py (100%) rename src/{FOSSDB => }/apps/account/forms.py (100%) rename src/{FOSSDB => }/apps/account/migrations/0001_initial.py (100%) rename src/{FOSSDB => }/apps/account/migrations/__init__.py (100%) rename src/{FOSSDB => }/apps/account/models.py (100%) rename src/{FOSSDB => }/apps/account/tests.py (100%) rename src/{FOSSDB => }/apps/account/urls.py (100%) rename src/{FOSSDB => }/apps/account/views.py (100%) rename src/{FOSSDB => }/apps/fossdb/__init__.py (100%) rename src/{FOSSDB => }/apps/fossdb/admin.py (100%) rename src/{FOSSDB => }/apps/fossdb/apps.py (100%) rename src/{FOSSDB => }/apps/fossdb/filters.py (100%) rename src/{FOSSDB => }/apps/fossdb/forms.py (100%) rename src/{FOSSDB => }/apps/fossdb/hosting_platform/forms.py (100%) rename src/{FOSSDB => }/apps/fossdb/hosting_platform/models.py (100%) rename src/{FOSSDB => }/apps/fossdb/license/models.py (100%) rename src/{FOSSDB => }/apps/fossdb/migrations/0001_initial.py (100%) rename src/{FOSSDB => }/apps/fossdb/migrations/0002_alter_tag_icon.py (100%) rename src/{FOSSDB => }/apps/fossdb/migrations/0003_alter_projectprogramminglanguage_percentage.py (100%) rename src/{FOSSDB => }/apps/fossdb/migrations/__init__.py (100%) rename src/{FOSSDB => }/apps/fossdb/models.py (100%) rename src/{FOSSDB => }/apps/fossdb/operating_system/models.py (100%) rename src/{FOSSDB => }/apps/fossdb/programming_language/forms.py (100%) rename src/{FOSSDB => }/apps/fossdb/programming_language/models.py (100%) rename src/{FOSSDB => }/apps/fossdb/star/models.py (100%) rename src/{FOSSDB => }/apps/fossdb/tag/models.py (100%) rename src/{FOSSDB => }/apps/fossdb/tests.py (100%) rename src/{FOSSDB => }/apps/fossdb/urls.py (100%) rename src/{FOSSDB => }/apps/fossdb/views.py (100%) create mode 100644 src/static/css/fossdb-ui.css create mode 100644 src/static/img/icons/logo.svg create mode 100644 src/static/tailwind/tailwind-input.css create mode 100644 tailwind.config.js diff --git a/.gitignore b/.gitignore index a4081bc..40d4e71 100644 --- a/.gitignore +++ b/.gitignore @@ -132,8 +132,7 @@ dmypy.json config.json debug -/static/admin/ -/static/fontawesomefree/ +local-cdn/ config.json -/media/profile_pics/* -!/media/profile_pics/default.jpg +node_modules/ +package-lock.json diff --git a/package.json b/package.json new file mode 100644 index 0000000..f4f889f --- /dev/null +++ b/package.json @@ -0,0 +1,8 @@ +{ + "scripts": { + "dev": "tailwindcss -i src/static/tailwind/tailwind-input.css -o src/static/css/fossdb-ui.css -w" + }, + "devDependencies": { + "tailwindcss": "^3.3.2" + } +} diff --git a/src/FOSSDB/settings.py b/src/FOSSDB/settings.py index 23c7b7e..98a71b3 100644 --- a/src/FOSSDB/settings.py +++ b/src/FOSSDB/settings.py @@ -15,13 +15,13 @@ import sys from pathlib import Path # Build paths inside the project like this: BASE_DIR / "subdir". -BASE_PATH = Path(__file__).resolve().parent.parent -sys.path.insert(0, str(BASE_PATH.joinpath("FOSSDB", "apps"))) +BASE_DIR = Path(__file__).resolve().parent.parent +sys.path.insert(0, str(BASE_DIR / "apps")) # Quick-start development settings - unsuitable for production # See https://docs.djangoproject.com/en/4.0/howto/deployment/checklist/ -with open(BASE_PATH.parent / "config.json", "r", encoding="UTF-8") as config_file: +with open(BASE_DIR.parent / "config.json", "r", encoding="UTF-8") as config_file: config = json.load(config_file) # SECURITY WARNING: keep the secret key used in production secret! @@ -38,6 +38,7 @@ INSTALLED_APPS = [ "account", "fossdb", "django_filters", + "fontawesomefree", "django.contrib.admin", "django.contrib.auth", "django.contrib.contenttypes", @@ -62,7 +63,7 @@ TEMPLATES = [ { "BACKEND": "django.template.backends.django.DjangoTemplates", "DIRS": [ - BASE_PATH / "templates", + BASE_DIR / "templates", ], "APP_DIRS": True, "OPTIONS": { @@ -130,17 +131,17 @@ USE_TZ = True # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/4.0/howto/static-files/ -STATIC_URL = "static/" -STATICFILE_DIRS = [ - BASE_PATH / "static", +STATIC_URL = "/static/" +STATICFILES_DIRS = [ + BASE_DIR / "static", ] -STATIC_ROOT = BASE_PATH.parent / "local-cdn" / "static" +STATIC_ROOT = BASE_DIR.parent / "local-cdn" / "static" MEDIA_URL = "media/" MEDIAFILES_DIRS = [ - BASE_PATH / "media", + BASE_DIR / "media", ] -MEDIA_ROOT = BASE_PATH.parent / "local-cdn" / "media" +MEDIA_ROOT = BASE_DIR.parent / "local-cdn" / "media" # Default primary key field type # https://docs.djangoproject.com/en/4.0/ref/settings/#default-auto-field diff --git a/src/FOSSDB/urls.py b/src/FOSSDB/urls.py index 9310a1d..dbe31f6 100644 --- a/src/FOSSDB/urls.py +++ b/src/FOSSDB/urls.py @@ -1,7 +1,7 @@ """FOSSDB URL Configuration The `urlpatterns` list routes URLs to views. For more information please see: - https://docs.djangoproject.com/en/4.0/topics/http/urls/ + https://docs.djangoproject.com/en/4.2/topics/http/urls/ Examples: Function views 1. Add an import: from my_app import views @@ -19,8 +19,8 @@ from django.urls import include, path urlpatterns = [ path("admin/", admin.site.urls), - path("", include("fossdb.urls")), path("", include("account.urls")), + path("", include("fossdb.urls")), path("", include("django.contrib.auth.urls")), ] if settings.DEBUG: diff --git a/src/FOSSDB/apps/account/__init__.py b/src/apps/account/__init__.py similarity index 100% rename from src/FOSSDB/apps/account/__init__.py rename to src/apps/account/__init__.py diff --git a/src/FOSSDB/apps/account/admin.py b/src/apps/account/admin.py similarity index 100% rename from src/FOSSDB/apps/account/admin.py rename to src/apps/account/admin.py diff --git a/src/FOSSDB/apps/account/apps.py b/src/apps/account/apps.py similarity index 100% rename from src/FOSSDB/apps/account/apps.py rename to src/apps/account/apps.py diff --git a/src/FOSSDB/apps/account/forms.py b/src/apps/account/forms.py similarity index 100% rename from src/FOSSDB/apps/account/forms.py rename to src/apps/account/forms.py diff --git a/src/FOSSDB/apps/account/migrations/0001_initial.py b/src/apps/account/migrations/0001_initial.py similarity index 100% rename from src/FOSSDB/apps/account/migrations/0001_initial.py rename to src/apps/account/migrations/0001_initial.py diff --git a/src/FOSSDB/apps/account/migrations/__init__.py b/src/apps/account/migrations/__init__.py similarity index 100% rename from src/FOSSDB/apps/account/migrations/__init__.py rename to src/apps/account/migrations/__init__.py diff --git a/src/FOSSDB/apps/account/models.py b/src/apps/account/models.py similarity index 100% rename from src/FOSSDB/apps/account/models.py rename to src/apps/account/models.py diff --git a/src/FOSSDB/apps/account/tests.py b/src/apps/account/tests.py similarity index 100% rename from src/FOSSDB/apps/account/tests.py rename to src/apps/account/tests.py diff --git a/src/FOSSDB/apps/account/urls.py b/src/apps/account/urls.py similarity index 100% rename from src/FOSSDB/apps/account/urls.py rename to src/apps/account/urls.py diff --git a/src/FOSSDB/apps/account/views.py b/src/apps/account/views.py similarity index 100% rename from src/FOSSDB/apps/account/views.py rename to src/apps/account/views.py diff --git a/src/FOSSDB/apps/fossdb/__init__.py b/src/apps/fossdb/__init__.py similarity index 100% rename from src/FOSSDB/apps/fossdb/__init__.py rename to src/apps/fossdb/__init__.py diff --git a/src/FOSSDB/apps/fossdb/admin.py b/src/apps/fossdb/admin.py similarity index 100% rename from src/FOSSDB/apps/fossdb/admin.py rename to src/apps/fossdb/admin.py diff --git a/src/FOSSDB/apps/fossdb/apps.py b/src/apps/fossdb/apps.py similarity index 100% rename from src/FOSSDB/apps/fossdb/apps.py rename to src/apps/fossdb/apps.py diff --git a/src/FOSSDB/apps/fossdb/filters.py b/src/apps/fossdb/filters.py similarity index 100% rename from src/FOSSDB/apps/fossdb/filters.py rename to src/apps/fossdb/filters.py diff --git a/src/FOSSDB/apps/fossdb/forms.py b/src/apps/fossdb/forms.py similarity index 100% rename from src/FOSSDB/apps/fossdb/forms.py rename to src/apps/fossdb/forms.py diff --git a/src/FOSSDB/apps/fossdb/hosting_platform/forms.py b/src/apps/fossdb/hosting_platform/forms.py similarity index 100% rename from src/FOSSDB/apps/fossdb/hosting_platform/forms.py rename to src/apps/fossdb/hosting_platform/forms.py diff --git a/src/FOSSDB/apps/fossdb/hosting_platform/models.py b/src/apps/fossdb/hosting_platform/models.py similarity index 100% rename from src/FOSSDB/apps/fossdb/hosting_platform/models.py rename to src/apps/fossdb/hosting_platform/models.py diff --git a/src/FOSSDB/apps/fossdb/license/models.py b/src/apps/fossdb/license/models.py similarity index 100% rename from src/FOSSDB/apps/fossdb/license/models.py rename to src/apps/fossdb/license/models.py diff --git a/src/FOSSDB/apps/fossdb/migrations/0001_initial.py b/src/apps/fossdb/migrations/0001_initial.py similarity index 100% rename from src/FOSSDB/apps/fossdb/migrations/0001_initial.py rename to src/apps/fossdb/migrations/0001_initial.py diff --git a/src/FOSSDB/apps/fossdb/migrations/0002_alter_tag_icon.py b/src/apps/fossdb/migrations/0002_alter_tag_icon.py similarity index 100% rename from src/FOSSDB/apps/fossdb/migrations/0002_alter_tag_icon.py rename to src/apps/fossdb/migrations/0002_alter_tag_icon.py diff --git a/src/FOSSDB/apps/fossdb/migrations/0003_alter_projectprogramminglanguage_percentage.py b/src/apps/fossdb/migrations/0003_alter_projectprogramminglanguage_percentage.py similarity index 100% rename from src/FOSSDB/apps/fossdb/migrations/0003_alter_projectprogramminglanguage_percentage.py rename to src/apps/fossdb/migrations/0003_alter_projectprogramminglanguage_percentage.py diff --git a/src/FOSSDB/apps/fossdb/migrations/__init__.py b/src/apps/fossdb/migrations/__init__.py similarity index 100% rename from src/FOSSDB/apps/fossdb/migrations/__init__.py rename to src/apps/fossdb/migrations/__init__.py diff --git a/src/FOSSDB/apps/fossdb/models.py b/src/apps/fossdb/models.py similarity index 100% rename from src/FOSSDB/apps/fossdb/models.py rename to src/apps/fossdb/models.py diff --git a/src/FOSSDB/apps/fossdb/operating_system/models.py b/src/apps/fossdb/operating_system/models.py similarity index 100% rename from src/FOSSDB/apps/fossdb/operating_system/models.py rename to src/apps/fossdb/operating_system/models.py diff --git a/src/FOSSDB/apps/fossdb/programming_language/forms.py b/src/apps/fossdb/programming_language/forms.py similarity index 100% rename from src/FOSSDB/apps/fossdb/programming_language/forms.py rename to src/apps/fossdb/programming_language/forms.py diff --git a/src/FOSSDB/apps/fossdb/programming_language/models.py b/src/apps/fossdb/programming_language/models.py similarity index 100% rename from src/FOSSDB/apps/fossdb/programming_language/models.py rename to src/apps/fossdb/programming_language/models.py diff --git a/src/FOSSDB/apps/fossdb/star/models.py b/src/apps/fossdb/star/models.py similarity index 100% rename from src/FOSSDB/apps/fossdb/star/models.py rename to src/apps/fossdb/star/models.py diff --git a/src/FOSSDB/apps/fossdb/tag/models.py b/src/apps/fossdb/tag/models.py similarity index 100% rename from src/FOSSDB/apps/fossdb/tag/models.py rename to src/apps/fossdb/tag/models.py diff --git a/src/FOSSDB/apps/fossdb/tests.py b/src/apps/fossdb/tests.py similarity index 100% rename from src/FOSSDB/apps/fossdb/tests.py rename to src/apps/fossdb/tests.py diff --git a/src/FOSSDB/apps/fossdb/urls.py b/src/apps/fossdb/urls.py similarity index 100% rename from src/FOSSDB/apps/fossdb/urls.py rename to src/apps/fossdb/urls.py diff --git a/src/FOSSDB/apps/fossdb/views.py b/src/apps/fossdb/views.py similarity index 100% rename from src/FOSSDB/apps/fossdb/views.py rename to src/apps/fossdb/views.py diff --git a/src/static/css/fossdb-ui.css b/src/static/css/fossdb-ui.css new file mode 100644 index 0000000..efe24a7 --- /dev/null +++ b/src/static/css/fossdb-ui.css @@ -0,0 +1,775 @@ +/* +! tailwindcss v3.3.2 | MIT License | https://tailwindcss.com +*/ + +/* +1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4) +2. Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116) +*/ + +*, +::before, +::after { + box-sizing: border-box; + /* 1 */ + border-width: 0; + /* 2 */ + border-style: solid; + /* 2 */ + border-color: #15161e; + /* 2 */ +} + +::before, +::after { + --tw-content: ''; +} + +/* +1. Use a consistent sensible line-height in all browsers. +2. Prevent adjustments of font size after orientation changes in iOS. +3. Use a more readable tab size. +4. Use the user's configured `sans` font-family by default. +5. Use the user's configured `sans` font-feature-settings by default. +6. Use the user's configured `sans` font-variation-settings by default. +*/ + +html { + line-height: 1.5; + /* 1 */ + -webkit-text-size-adjust: 100%; + /* 2 */ + -moz-tab-size: 4; + /* 3 */ + -o-tab-size: 4; + tab-size: 4; + /* 3 */ + font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; + /* 4 */ + font-feature-settings: normal; + /* 5 */ + font-variation-settings: normal; + /* 6 */ +} + +/* +1. Remove the margin in all browsers. +2. Inherit line-height from `html` so users can set them as a class directly on the `html` element. +*/ + +body { + margin: 0; + /* 1 */ + line-height: inherit; + /* 2 */ +} + +/* +1. Add the correct height in Firefox. +2. Correct the inheritance of border color in Firefox. (https://bugzilla.mozilla.org/show_bug.cgi?id=190655) +3. Ensure horizontal rules are visible by default. +*/ + +hr { + height: 0; + /* 1 */ + color: inherit; + /* 2 */ + border-top-width: 1px; + /* 3 */ +} + +/* +Add the correct text decoration in Chrome, Edge, and Safari. +*/ + +abbr:where([title]) { + -webkit-text-decoration: underline dotted; + text-decoration: underline dotted; +} + +/* +Remove the default font size and weight for headings. +*/ + +h1, +h2, +h3, +h4, +h5, +h6 { + font-size: inherit; + font-weight: inherit; +} + +/* +Reset links to optimize for opt-in styling instead of opt-out. +*/ + +a { + color: inherit; + text-decoration: inherit; +} + +/* +Add the correct font weight in Edge and Safari. +*/ + +b, +strong { + font-weight: bolder; +} + +/* +1. Use the user's configured `mono` font family by default. +2. Correct the odd `em` font sizing in all browsers. +*/ + +code, +kbd, +samp, +pre { + font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; + /* 1 */ + font-size: 1em; + /* 2 */ +} + +/* +Add the correct font size in all browsers. +*/ + +small { + font-size: 80%; +} + +/* +Prevent `sub` and `sup` elements from affecting the line height in all browsers. +*/ + +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sub { + bottom: -0.25em; +} + +sup { + top: -0.5em; +} + +/* +1. Remove text indentation from table contents in Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=999088, https://bugs.webkit.org/show_bug.cgi?id=201297) +2. Correct table border color inheritance in all Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=935729, https://bugs.webkit.org/show_bug.cgi?id=195016) +3. Remove gaps between table borders by default. +*/ + +table { + text-indent: 0; + /* 1 */ + border-color: inherit; + /* 2 */ + border-collapse: collapse; + /* 3 */ +} + +/* +1. Change the font styles in all browsers. +2. Remove the margin in Firefox and Safari. +3. Remove default padding in all browsers. +*/ + +button, +input, +optgroup, +select, +textarea { + font-family: inherit; + /* 1 */ + font-size: 100%; + /* 1 */ + font-weight: inherit; + /* 1 */ + line-height: inherit; + /* 1 */ + color: inherit; + /* 1 */ + margin: 0; + /* 2 */ + padding: 0; + /* 3 */ +} + +/* +Remove the inheritance of text transform in Edge and Firefox. +*/ + +button, +select { + text-transform: none; +} + +/* +1. Correct the inability to style clickable types in iOS and Safari. +2. Remove default button styles. +*/ + +button, +[type='button'], +[type='reset'], +[type='submit'] { + -webkit-appearance: button; + /* 1 */ + background-color: transparent; + /* 2 */ + background-image: none; + /* 2 */ +} + +/* +Use the modern Firefox focus style for all focusable elements. +*/ + +:-moz-focusring { + outline: auto; +} + +/* +Remove the additional `:invalid` styles in Firefox. (https://github.com/mozilla/gecko-dev/blob/2f9eacd9d3d995c937b4251a5557d95d494c9be1/layout/style/res/forms.css#L728-L737) +*/ + +:-moz-ui-invalid { + box-shadow: none; +} + +/* +Add the correct vertical alignment in Chrome and Firefox. +*/ + +progress { + vertical-align: baseline; +} + +/* +Correct the cursor style of increment and decrement buttons in Safari. +*/ + +::-webkit-inner-spin-button, +::-webkit-outer-spin-button { + height: auto; +} + +/* +1. Correct the odd appearance in Chrome and Safari. +2. Correct the outline style in Safari. +*/ + +[type='search'] { + -webkit-appearance: textfield; + /* 1 */ + outline-offset: -2px; + /* 2 */ +} + +/* +Remove the inner padding in Chrome and Safari on macOS. +*/ + +::-webkit-search-decoration { + -webkit-appearance: none; +} + +/* +1. Correct the inability to style clickable types in iOS and Safari. +2. Change font properties to `inherit` in Safari. +*/ + +::-webkit-file-upload-button { + -webkit-appearance: button; + /* 1 */ + font: inherit; + /* 2 */ +} + +/* +Add the correct display in Chrome and Safari. +*/ + +summary { + display: list-item; +} + +/* +Removes the default spacing and border for appropriate elements. +*/ + +blockquote, +dl, +dd, +h1, +h2, +h3, +h4, +h5, +h6, +hr, +figure, +p, +pre { + margin: 0; +} + +fieldset { + margin: 0; + padding: 0; +} + +legend { + padding: 0; +} + +ol, +ul, +menu { + list-style: none; + margin: 0; + padding: 0; +} + +/* +Prevent resizing textareas horizontally by default. +*/ + +textarea { + resize: vertical; +} + +/* +1. Reset the default placeholder opacity in Firefox. (https://github.com/tailwindlabs/tailwindcss/issues/3300) +2. Set the default placeholder color to the user's configured gray 400 color. +*/ + +input::-moz-placeholder, textarea::-moz-placeholder { + opacity: 1; + /* 1 */ + color: #9ca3af; + /* 2 */ +} + +input::placeholder, +textarea::placeholder { + opacity: 1; + /* 1 */ + color: #9ca3af; + /* 2 */ +} + +/* +Set the default cursor for buttons. +*/ + +button, +[role="button"] { + cursor: pointer; +} + +/* +Make sure disabled buttons don't get the pointer cursor. +*/ + +:disabled { + cursor: default; +} + +/* +1. Make replaced elements `display: block` by default. (https://github.com/mozdevs/cssremedy/issues/14) +2. Add `vertical-align: middle` to align replaced elements more sensibly by default. (https://github.com/jensimmons/cssremedy/issues/14#issuecomment-634934210) + This can trigger a poorly considered lint error in some tools but is included by design. +*/ + +img, +svg, +video, +canvas, +audio, +iframe, +embed, +object { + display: block; + /* 1 */ + vertical-align: middle; + /* 2 */ +} + +/* +Constrain images and videos to the parent width and preserve their intrinsic aspect ratio. (https://github.com/mozdevs/cssremedy/issues/14) +*/ + +img, +video { + max-width: 100%; + height: auto; +} + +/* Make elements with the HTML hidden attribute stay hidden by default */ + +[hidden] { + display: none; +} + +*, ::before, ::after { + --tw-border-spacing-x: 0; + --tw-border-spacing-y: 0; + --tw-translate-x: 0; + --tw-translate-y: 0; + --tw-rotate: 0; + --tw-skew-x: 0; + --tw-skew-y: 0; + --tw-scale-x: 1; + --tw-scale-y: 1; + --tw-pan-x: ; + --tw-pan-y: ; + --tw-pinch-zoom: ; + --tw-scroll-snap-strictness: proximity; + --tw-gradient-from-position: ; + --tw-gradient-via-position: ; + --tw-gradient-to-position: ; + --tw-ordinal: ; + --tw-slashed-zero: ; + --tw-numeric-figure: ; + --tw-numeric-spacing: ; + --tw-numeric-fraction: ; + --tw-ring-inset: ; + --tw-ring-offset-width: 0px; + --tw-ring-offset-color: #fff; + --tw-ring-color: rgb(59 130 246 / 0.5); + --tw-ring-offset-shadow: 0 0 #0000; + --tw-ring-shadow: 0 0 #0000; + --tw-shadow: 0 0 #0000; + --tw-shadow-colored: 0 0 #0000; + --tw-blur: ; + --tw-brightness: ; + --tw-contrast: ; + --tw-grayscale: ; + --tw-hue-rotate: ; + --tw-invert: ; + --tw-saturate: ; + --tw-sepia: ; + --tw-drop-shadow: ; + --tw-backdrop-blur: ; + --tw-backdrop-brightness: ; + --tw-backdrop-contrast: ; + --tw-backdrop-grayscale: ; + --tw-backdrop-hue-rotate: ; + --tw-backdrop-invert: ; + --tw-backdrop-opacity: ; + --tw-backdrop-saturate: ; + --tw-backdrop-sepia: ; +} + +::backdrop { + --tw-border-spacing-x: 0; + --tw-border-spacing-y: 0; + --tw-translate-x: 0; + --tw-translate-y: 0; + --tw-rotate: 0; + --tw-skew-x: 0; + --tw-skew-y: 0; + --tw-scale-x: 1; + --tw-scale-y: 1; + --tw-pan-x: ; + --tw-pan-y: ; + --tw-pinch-zoom: ; + --tw-scroll-snap-strictness: proximity; + --tw-gradient-from-position: ; + --tw-gradient-via-position: ; + --tw-gradient-to-position: ; + --tw-ordinal: ; + --tw-slashed-zero: ; + --tw-numeric-figure: ; + --tw-numeric-spacing: ; + --tw-numeric-fraction: ; + --tw-ring-inset: ; + --tw-ring-offset-width: 0px; + --tw-ring-offset-color: #fff; + --tw-ring-color: rgb(59 130 246 / 0.5); + --tw-ring-offset-shadow: 0 0 #0000; + --tw-ring-shadow: 0 0 #0000; + --tw-shadow: 0 0 #0000; + --tw-shadow-colored: 0 0 #0000; + --tw-blur: ; + --tw-brightness: ; + --tw-contrast: ; + --tw-grayscale: ; + --tw-hue-rotate: ; + --tw-invert: ; + --tw-saturate: ; + --tw-sepia: ; + --tw-drop-shadow: ; + --tw-backdrop-blur: ; + --tw-backdrop-brightness: ; + --tw-backdrop-contrast: ; + --tw-backdrop-grayscale: ; + --tw-backdrop-hue-rotate: ; + --tw-backdrop-invert: ; + --tw-backdrop-opacity: ; + --tw-backdrop-saturate: ; + --tw-backdrop-sepia: ; +} + +.container { + width: 100%; +} + +@media (min-width: 640px) { + .container { + max-width: 640px; + } +} + +@media (min-width: 768px) { + .container { + max-width: 768px; + } +} + +@media (min-width: 1024px) { + .container { + max-width: 1024px; + } +} + +@media (min-width: 1280px) { + .container { + max-width: 1280px; + } +} + +@media (min-width: 1536px) { + .container { + max-width: 1536px; + } +} + +.static { + position: static; +} + +.relative { + position: relative; +} + +.mx-4 { + margin-left: 1rem; + margin-right: 1rem; +} + +.mb-1 { + margin-bottom: 0.25rem; +} + +.ml-4 { + margin-left: 1rem; +} + +.mt-4 { + margin-top: 1rem; +} + +.block { + display: block; +} + +.flex { + display: flex; +} + +.h-32 { + height: 8rem; +} + +.min-h-screen { + min-height: 100vh; +} + +.max-w-\[10rem\] { + max-width: 10rem; +} + +.flex-grow { + flex-grow: 1; +} + +.transform { + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + +.flex-col { + flex-direction: column; +} + +.items-center { + align-items: center; +} + +.justify-between { + justify-content: space-between; +} + +.gap-x-6 { + -moz-column-gap: 1.5rem; + column-gap: 1.5rem; +} + +.space-y-4 > :not([hidden]) ~ :not([hidden]) { + --tw-space-y-reverse: 0; + margin-top: calc(1rem * calc(1 - var(--tw-space-y-reverse))); + margin-bottom: calc(1rem * var(--tw-space-y-reverse)); +} + +.border { + border-width: 1px; +} + +.border-b-lightsteelblue-100 { + --tw-border-opacity: 1; + border-bottom-color: rgb(192 202 245 / var(--tw-border-opacity)); +} + +.bg-gray-100 { + --tw-bg-opacity: 1; + background-color: rgb(26 27 38 / var(--tw-bg-opacity)); +} + +.bg-gray-200 { + --tw-bg-opacity: 1; + background-color: rgb(21 22 30 / var(--tw-bg-opacity)); +} + +.p-8 { + padding: 2rem; +} + +.px-6 { + padding-left: 1.5rem; + padding-right: 1.5rem; +} + +.py-2 { + padding-top: 0.5rem; + padding-bottom: 0.5rem; +} + +.text-left { + text-align: left; +} + +.font-abel { + font-family: Abel, Roboto, Helvetica, Arial, sans-serif; +} + +.font-condensed { + font-family: Roboto Condensed, Roboto, Helvetica, Arial, sans-serif; +} + +.font-rationale { + font-family: Rationale, Roboto, Helvetica, Arial, sans-serif; +} + +.font-roboto { + font-family: Roboto, Helvetica, Arial, sans-serif; +} + +.text-4xl { + font-size: 4rem; +} + +.text-xl { + font-size: 1.25rem; +} + +.uppercase { + text-transform: uppercase; +} + +.text-lightsteelblue-100 { + --tw-text-opacity: 1; + color: rgb(192 202 245 / var(--tw-text-opacity)); +} + +.text-skyblue { + --tw-text-opacity: 1; + color: rgb(13 185 215 / var(--tw-text-opacity)); +} + +.text-slategray { + --tw-text-opacity: 1; + color: rgb(115 122 162 / var(--tw-text-opacity)); +} + +.underline { + text-decoration-line: underline; +} + +.filter { + filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow); +} + +.transition { + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, -webkit-backdrop-filter; + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter; + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter, -webkit-backdrop-filter; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; +} + +.duration-200 { + transition-duration: 200ms; +} + +.duration-300 { + transition-duration: 300ms; +} + +.ease-in-out { + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); +} + +body { + margin: 0px; + line-height: normal; +} + +*, +::before, +::after { + border-width: 0; +} + +.hover\:border-b-2:hover { + border-bottom-width: 2px; +} + +.hover\:text-skyblue:hover { + --tw-text-opacity: 1; + color: rgb(13 185 215 / var(--tw-text-opacity)); +} + +.focus\:border-b-2:focus { + border-bottom-width: 2px; +} + +.focus\:border-b-skyblue:focus { + --tw-border-opacity: 1; + border-bottom-color: rgb(13 185 215 / var(--tw-border-opacity)); +} + +.focus\:outline-none:focus { + outline: 2px solid transparent; + outline-offset: 2px; +} diff --git a/src/static/img/icons/logo.svg b/src/static/img/icons/logo.svg new file mode 100644 index 0000000..9825f3c --- /dev/null +++ b/src/static/img/icons/logo.svg @@ -0,0 +1,111 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/static/tailwind/tailwind-input.css b/src/static/tailwind/tailwind-input.css new file mode 100644 index 0000000..72ebe4e --- /dev/null +++ b/src/static/tailwind/tailwind-input.css @@ -0,0 +1,16 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +@import url("https://fonts.googleapis.com/css2?family=Abel&display=swap"); +@import url("https://fonts.googleapis.com/css2?family=Rationale&display=swap"); +@import url("https://fonts.googleapis.com/css2?family=Roboto+Condensed:ital,wght@0,300;0,400;0,700;1,300;1,400;1,700&display=swap"); + +body { + @apply leading-[normal] m-0; +} +*, +::before, +::after { + border-width: 0; +} diff --git a/src/templates/layout.html b/src/templates/layout.html index 08fe90d..62c5c25 100644 --- a/src/templates/layout.html +++ b/src/templates/layout.html @@ -1,15 +1,65 @@ {% load static %} - + - - + + + + {% block title %}{% endblock %} {% block meta %}{% endblock %} - - {% block content %}{% endblock %} + +
+
+ +
+ logo + fossdb +
+ +
+ +
+ + +
+
+ + +
+
+
+
+
+
+
+

+ FOSSDB is a passion project of @kristoferssolo and a dedicated community of reporters. +

+ +

This site uses data from GitHub as well as data...

+

This site has no affiliation with GitHub or any other hosting platform.

+
+
+
+
diff --git a/tailwind.config.js b/tailwind.config.js new file mode 100644 index 0000000..0de8c37 --- /dev/null +++ b/tailwind.config.js @@ -0,0 +1,48 @@ +/** @type {import('tailwindcss').Config} */ +module.exports = { + content: ["./src/**/*.{html,js}"], + theme: { + colors: { + gray: { + 100: "#1a1b26", + 200: "#15161e", + 300: "#16161e", + }, + indianred: "#db4b4b", + burlywood: "#e0af68", + + lightsteelblue: { + 100: "#c0caf5", + 200: "#a9b1d6", + }, + skyblue: "#0db9d7", + crimson: "#f52a65", + slategray: "#737aa2", + }, + fontFamily: { + rationale: [ + "Rationale", + "Roboto", + "Helvetica", + "Arial", + "sans-serif", + ], + abel: ["Abel", "Roboto", "Helvetica", "Arial", "sans-serif"], + condensed: [ + "Roboto Condensed", + "Roboto", + "Helvetica", + "Arial", + "sans-serif", + ], + roboto: ["Roboto", "Helvetica", "Arial", "sans-serif"], + }, + fontSize: { + base: "1rem", + xl: "1.25rem", + "4xl": "4rem", + }, + extend: {}, + }, + plugins: [], +} From 6ea8e2c3c3e8a3db4da718180c64a22c0b26b418 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Wed, 28 Jun 2023 16:19:40 +0000 Subject: [PATCH 130/144] Combined all fossdb models into 1 file --- .../0002_alter_user_profile_picture.py | 19 ++++ src/apps/fossdb/admin.py | 17 ++-- src/apps/fossdb/forms.py | 36 +++++++- src/apps/fossdb/hosting_platform/forms.py | 17 ---- src/apps/fossdb/hosting_platform/models.py | 17 ---- src/apps/fossdb/license/models.py | 11 --- .../migrations/0004_alter_tag_icon_star.py | 29 ++++++ src/apps/fossdb/models.py | 88 ++++++++++++++++++- src/apps/fossdb/operating_system/models.py | 30 ------- src/apps/fossdb/programming_language/forms.py | 23 ----- .../fossdb/programming_language/models.py | 17 ---- src/apps/fossdb/star/models.py | 7 -- src/apps/fossdb/tag/models.py | 10 --- src/apps/fossdb/urls.py | 2 +- src/apps/fossdb/views.py | 9 +- 15 files changed, 182 insertions(+), 150 deletions(-) create mode 100644 src/apps/account/migrations/0002_alter_user_profile_picture.py delete mode 100644 src/apps/fossdb/hosting_platform/forms.py delete mode 100644 src/apps/fossdb/hosting_platform/models.py delete mode 100644 src/apps/fossdb/license/models.py create mode 100644 src/apps/fossdb/migrations/0004_alter_tag_icon_star.py delete mode 100644 src/apps/fossdb/operating_system/models.py delete mode 100644 src/apps/fossdb/programming_language/forms.py delete mode 100644 src/apps/fossdb/programming_language/models.py delete mode 100644 src/apps/fossdb/star/models.py delete mode 100644 src/apps/fossdb/tag/models.py diff --git a/src/apps/account/migrations/0002_alter_user_profile_picture.py b/src/apps/account/migrations/0002_alter_user_profile_picture.py new file mode 100644 index 0000000..f1e877e --- /dev/null +++ b/src/apps/account/migrations/0002_alter_user_profile_picture.py @@ -0,0 +1,19 @@ +# Generated by Django 4.2.2 on 2023-06-28 16:17 + +import account.models +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('account', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='user', + name='profile_picture', + field=models.ImageField(default='profile-pics/default.jpg', upload_to=account.models.get_profile_pic_path), + ), + ] diff --git a/src/apps/fossdb/admin.py b/src/apps/fossdb/admin.py index 9fd82e2..89647d1 100644 --- a/src/apps/fossdb/admin.py +++ b/src/apps/fossdb/admin.py @@ -1,11 +1,16 @@ from django.contrib import admin -from .hosting_platform.models import HostingPlatform, ProjectHostingPlatform -from .license.models import License -from .models import Project -from .operating_system.models import OperatingSystem, OperatingSystemVersion -from .programming_language.models import ProgrammingLanguage, ProjectProgrammingLanguage -from .tag.models import Tag +from .models import ( + HostingPlatform, + License, + OperatingSystem, + OperatingSystemVersion, + ProgrammingLanguage, + Project, + ProjectHostingPlatform, + ProjectProgrammingLanguage, + Tag, +) class ProjectProgrammingLanguageInline(admin.TabularInline): diff --git a/src/apps/fossdb/forms.py b/src/apps/fossdb/forms.py index 8416109..ab183df 100644 --- a/src/apps/fossdb/forms.py +++ b/src/apps/fossdb/forms.py @@ -1,6 +1,40 @@ from django import forms -from .models import Project +from .models import HostingPlatform, ProgrammingLanguage, Project, ProjectHostingPlatform, ProjectProgrammingLanguage + + +class HostingPlatformForm(forms.ModelForm): + class Meta: + model = ProjectHostingPlatform + fields = ( + "url", + "hosting_platform", + ) + widgets = { + "hosting_platform": forms.Select( + choices=HostingPlatform.objects.all(), + ) + } + + +class ProgrammingLanguageForm(forms.ModelForm): + class Meta: + model = ProjectProgrammingLanguage + fields = ( + "programming_language", + "percentage", + ) + widgets = { + "programming_language": forms.Select( + choices=ProgrammingLanguage.objects.all(), + ), + "percentage": forms.NumberInput( + attrs={ + "min": "0", + "max": "100", + } + ), + } class ProjectForm(forms.ModelForm): diff --git a/src/apps/fossdb/hosting_platform/forms.py b/src/apps/fossdb/hosting_platform/forms.py deleted file mode 100644 index 2f69d24..0000000 --- a/src/apps/fossdb/hosting_platform/forms.py +++ /dev/null @@ -1,17 +0,0 @@ -from django import forms - -from .models import HostingPlatform, ProjectHostingPlatform - - -class HostingPlatformForm(forms.ModelForm): - class Meta: - model = ProjectHostingPlatform - fields = ( - "url", - "hosting_platform", - ) - widgets = { - "hosting_platform": forms.Select( - choices=HostingPlatform.objects.all(), - ) - } diff --git a/src/apps/fossdb/hosting_platform/models.py b/src/apps/fossdb/hosting_platform/models.py deleted file mode 100644 index 62874e5..0000000 --- a/src/apps/fossdb/hosting_platform/models.py +++ /dev/null @@ -1,17 +0,0 @@ -from django.db import models - - -class HostingPlatform(models.Model): - name = models.CharField(max_length=100, unique=True) - - def __str__(self): - return self.name - - -class ProjectHostingPlatform(models.Model): - hosting_platform = models.ForeignKey(HostingPlatform, on_delete=models.CASCADE) - project = models.OneToOneField("Project", on_delete=models.CASCADE) - url = models.URLField(unique=True) - - def __str__(self): - return self.url diff --git a/src/apps/fossdb/license/models.py b/src/apps/fossdb/license/models.py deleted file mode 100644 index c66a21b..0000000 --- a/src/apps/fossdb/license/models.py +++ /dev/null @@ -1,11 +0,0 @@ -from django.db import models - - -class License(models.Model): - short_name = models.CharField(max_length=50, unique=True) - full_name = models.CharField(max_length=100, unique=True) - url = models.URLField(blank=True, default="") - text = models.TextField(blank=True, default="") - - def __str__(self): - return self.short_name diff --git a/src/apps/fossdb/migrations/0004_alter_tag_icon_star.py b/src/apps/fossdb/migrations/0004_alter_tag_icon_star.py new file mode 100644 index 0000000..0ef0640 --- /dev/null +++ b/src/apps/fossdb/migrations/0004_alter_tag_icon_star.py @@ -0,0 +1,29 @@ +# Generated by Django 4.2.2 on 2023-06-28 16:17 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('fossdb', '0003_alter_projectprogramminglanguage_percentage'), + ] + + operations = [ + migrations.AlterField( + model_name='tag', + name='icon', + field=models.ImageField(blank=True, null=True, upload_to='tags/icons/'), + ), + migrations.CreateModel( + name='Star', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('project', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='fossdb.project')), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ], + ), + ] diff --git a/src/apps/fossdb/models.py b/src/apps/fossdb/models.py index fef774f..c776012 100644 --- a/src/apps/fossdb/models.py +++ b/src/apps/fossdb/models.py @@ -4,10 +4,60 @@ from django.conf import settings from django.db import models -from .license.models import License -from .operating_system.models import OperatingSystemVersion -from .programming_language.models import ProgrammingLanguage -from .tag.models import Tag + +class License(models.Model): + short_name = models.CharField(max_length=50, unique=True) + full_name = models.CharField(max_length=100, unique=True) + url = models.URLField(blank=True, default="") + text = models.TextField(blank=True, default="") + + def __str__(self): + return self.short_name + + +class OperatingSystem(models.Model): + name = models.CharField(max_length=100, unique=True) + description = models.TextField(blank=True, default="") + + def __str__(self): + return self.name + + +class OperatingSystemVersion(models.Model): + operating_system = models.ForeignKey(OperatingSystem, on_delete=models.CASCADE) + version = models.CharField(max_length=50, blank=True, default="") + codename = models.CharField(max_length=100, blank=True, default="") + is_lts = models.BooleanField(blank=True, default=False) + + def __str__(self): + return f"{self.operating_system.name} {self.version} {'LTS' if self.is_lts else ''}" + + class Meta: + constraints = ( + models.UniqueConstraint( + fields=( + "operating_system", + "version", + ), + name="unique_os_version", + ), + ) + + +class Tag(models.Model): + name = models.CharField(max_length=100, unique=True, db_index=True) + description = models.TextField(blank=True, default="") + icon = models.ImageField(upload_to="tags/icons/", null=True, blank=True) + + def __str__(self): + return self.name + + +class ProgrammingLanguage(models.Model): + name = models.CharField(max_length=100, unique=True) + + def __str__(self): + return self.name class Project(models.Model): @@ -41,3 +91,33 @@ class Project(models.Model): name="unique_owner_name", ), ) + + +class ProjectProgrammingLanguage(models.Model): + project = models.ForeignKey(Project, on_delete=models.CASCADE) + programming_language = models.ForeignKey(ProgrammingLanguage, on_delete=models.CASCADE) + percentage = models.PositiveIntegerField(blank=True, null=True) + + def __str__(self): + return f"{self.project.owner}/{self.project.name} | {self.programming_language} | {self.percentage}%" + + +class HostingPlatform(models.Model): + name = models.CharField(max_length=100, unique=True) + + def __str__(self): + return self.name + + +class ProjectHostingPlatform(models.Model): + hosting_platform = models.ForeignKey(HostingPlatform, on_delete=models.CASCADE) + project = models.OneToOneField(Project, on_delete=models.CASCADE) + url = models.URLField(unique=True) + + def __str__(self): + return self.url + + +class Star(models.Model): + user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE) + project = models.ForeignKey(Project, on_delete=models.CASCADE) diff --git a/src/apps/fossdb/operating_system/models.py b/src/apps/fossdb/operating_system/models.py deleted file mode 100644 index 911d8fd..0000000 --- a/src/apps/fossdb/operating_system/models.py +++ /dev/null @@ -1,30 +0,0 @@ -from django.db import models - - -class OperatingSystem(models.Model): - name = models.CharField(max_length=100, unique=True) - description = models.TextField(blank=True, default="") - - def __str__(self): - return self.name - - -class OperatingSystemVersion(models.Model): - operating_system = models.ForeignKey(OperatingSystem, on_delete=models.CASCADE) - version = models.CharField(max_length=50, blank=True, default="") - codename = models.CharField(max_length=100, blank=True, default="") - is_lts = models.BooleanField(blank=True, default=False) - - def __str__(self): - return f"{self.operating_system.name} {self.version} {'LTS' if self.is_lts else ''}" - - class Meta: - constraints = ( - models.UniqueConstraint( - fields=( - "operating_system", - "version", - ), - name="unique_os_version", - ), - ) diff --git a/src/apps/fossdb/programming_language/forms.py b/src/apps/fossdb/programming_language/forms.py deleted file mode 100644 index 4d29eb5..0000000 --- a/src/apps/fossdb/programming_language/forms.py +++ /dev/null @@ -1,23 +0,0 @@ -from django import forms - -from .models import ProgrammingLanguage, ProjectProgrammingLanguage - - -class ProgrammingLanguageForm(forms.ModelForm): - class Meta: - model = ProjectProgrammingLanguage - fields = ( - "programming_language", - "percentage", - ) - widgets = { - "programming_language": forms.Select( - choices=ProgrammingLanguage.objects.all(), - ), - "percentage": forms.NumberInput( - attrs={ - "min": "0", - "max": "100", - } - ), - } diff --git a/src/apps/fossdb/programming_language/models.py b/src/apps/fossdb/programming_language/models.py deleted file mode 100644 index d2357d3..0000000 --- a/src/apps/fossdb/programming_language/models.py +++ /dev/null @@ -1,17 +0,0 @@ -from django.db import models - - -class ProgrammingLanguage(models.Model): - name = models.CharField(max_length=100, unique=True) - - def __str__(self): - return self.name - - -class ProjectProgrammingLanguage(models.Model): - project = models.ForeignKey("Project", on_delete=models.CASCADE) - programming_language = models.ForeignKey(ProgrammingLanguage, on_delete=models.CASCADE) - percentage = models.PositiveIntegerField(blank=True, null=True) - - def __str__(self): - return f"{self.project.owner}/{self.project.name} | {self.programming_language} | {self.percentage}%" diff --git a/src/apps/fossdb/star/models.py b/src/apps/fossdb/star/models.py deleted file mode 100644 index cfa2034..0000000 --- a/src/apps/fossdb/star/models.py +++ /dev/null @@ -1,7 +0,0 @@ -from django.conf import settings -from django.db import models - - -class Star(models.Model): - user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE) - project = models.ForeignKey("Project", on_delete=models.CASCADE, related_name="stars") diff --git a/src/apps/fossdb/tag/models.py b/src/apps/fossdb/tag/models.py deleted file mode 100644 index 21908a6..0000000 --- a/src/apps/fossdb/tag/models.py +++ /dev/null @@ -1,10 +0,0 @@ -from django.db import models - - -class Tag(models.Model): - name = models.CharField(max_length=100, unique=True, db_index=True) - description = models.TextField(blank=True, default="") - icon = models.ImageField(upload_to="types/icons/", null=True, blank=True) - - def __str__(self): - return self.name diff --git a/src/apps/fossdb/urls.py b/src/apps/fossdb/urls.py index a831e57..1d4b5d0 100644 --- a/src/apps/fossdb/urls.py +++ b/src/apps/fossdb/urls.py @@ -3,7 +3,7 @@ from django.urls import path from . import views urlpatterns = [ - path("", views.ProjectListView.as_view(), name="index"), + path("explore/", views.ProjectListView.as_view(), name="explore"), path("add/", views.ProjectCreateView.as_view(), name="add-project"), path("//", views.ProjectDetailView.as_view(), name="project-detail"), path("//edit/", views.ProjectUpdateView.as_view(), name="project-update"), diff --git a/src/apps/fossdb/views.py b/src/apps/fossdb/views.py index 71668a5..13ec9d4 100644 --- a/src/apps/fossdb/views.py +++ b/src/apps/fossdb/views.py @@ -7,11 +7,8 @@ from django_filters.views import FilterView from .filters import ProjectFilter -from .forms import ProjectForm -from .hosting_platform.forms import HostingPlatformForm -from .models import Project -from .programming_language.forms import ProgrammingLanguageForm -from .programming_language.models import ProjectProgrammingLanguage +from .forms import HostingPlatformForm, ProgrammingLanguageForm, ProjectForm +from .models import Project, ProjectProgrammingLanguage ProgrammingLanguageInlineFormset = inlineformset_factory( Project, @@ -23,7 +20,7 @@ ProgrammingLanguageInlineFormset = inlineformset_factory( class ProjectListView(FilterView): model = Project - template_name = "fossdb/index.html" + template_name = "fossdb/explore.html" filterset_class = ProjectFilter context_object_name = "projects" paginate_by = 10 # optional 10 projects a page From a77bf0eb5b961cae5ce47f550c6d19ad0764f661 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Wed, 28 Jun 2023 16:19:54 +0000 Subject: [PATCH 131/144] Created main app --- src/FOSSDB/settings.py | 1 + src/FOSSDB/urls.py | 1 + src/apps/main/__init__.py | 0 src/apps/main/admin.py | 3 +++ src/apps/main/apps.py | 6 ++++++ src/apps/main/migrations/__init__.py | 0 src/apps/main/models.py | 3 +++ src/apps/main/tests.py | 3 +++ src/apps/main/urls.py | 11 ++++++++++ src/apps/main/views.py | 21 +++++++++++++++++++ .../fossdb/{index.html => explore.html} | 0 src/templates/layout.html | 19 +++++++++++------ src/templates/main/homepage.html | 5 +++++ 13 files changed, 67 insertions(+), 6 deletions(-) create mode 100644 src/apps/main/__init__.py create mode 100644 src/apps/main/admin.py create mode 100644 src/apps/main/apps.py create mode 100644 src/apps/main/migrations/__init__.py create mode 100644 src/apps/main/models.py create mode 100644 src/apps/main/tests.py create mode 100644 src/apps/main/urls.py create mode 100644 src/apps/main/views.py rename src/templates/fossdb/{index.html => explore.html} (100%) create mode 100644 src/templates/main/homepage.html diff --git a/src/FOSSDB/settings.py b/src/FOSSDB/settings.py index 98a71b3..c28334f 100644 --- a/src/FOSSDB/settings.py +++ b/src/FOSSDB/settings.py @@ -35,6 +35,7 @@ DEBUG = config["DEBUG"] # Application definition INSTALLED_APPS = [ + "main", "account", "fossdb", "django_filters", diff --git a/src/FOSSDB/urls.py b/src/FOSSDB/urls.py index dbe31f6..1c03965 100644 --- a/src/FOSSDB/urls.py +++ b/src/FOSSDB/urls.py @@ -21,6 +21,7 @@ urlpatterns = [ path("admin/", admin.site.urls), path("", include("account.urls")), path("", include("fossdb.urls")), + path("", include("main.urls")), path("", include("django.contrib.auth.urls")), ] if settings.DEBUG: diff --git a/src/apps/main/__init__.py b/src/apps/main/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/apps/main/admin.py b/src/apps/main/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/src/apps/main/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/src/apps/main/apps.py b/src/apps/main/apps.py new file mode 100644 index 0000000..167f044 --- /dev/null +++ b/src/apps/main/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class MainConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'main' diff --git a/src/apps/main/migrations/__init__.py b/src/apps/main/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/apps/main/models.py b/src/apps/main/models.py new file mode 100644 index 0000000..71a8362 --- /dev/null +++ b/src/apps/main/models.py @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. diff --git a/src/apps/main/tests.py b/src/apps/main/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/src/apps/main/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/src/apps/main/urls.py b/src/apps/main/urls.py new file mode 100644 index 0000000..2b187ec --- /dev/null +++ b/src/apps/main/urls.py @@ -0,0 +1,11 @@ +from django.urls import path + +from . import views + +urlpatterns = [ + path("", views.homepage, name="homepage"), + path("contribute/", views.contribute, name="contribute"), + path("news/", views.news, name="news"), + path("dashboard/", views.dashboard, name="dashboard"), + path("help/", views.help, name="help"), +] diff --git a/src/apps/main/views.py b/src/apps/main/views.py new file mode 100644 index 0000000..bc0578d --- /dev/null +++ b/src/apps/main/views.py @@ -0,0 +1,21 @@ +from django.shortcuts import render + + +def homepage(request): + return render(request, "main/homepage.html", {"title": "FOSSDB"}) + + +def contribute(request): + return render(request, "main/contribute.html", {"title": "FOSSDB | Contribute"}) + + +def news(request): + return render(request, "main/news.html", {"title": "FOSSDB | News"}) + + +def dashboard(request): + return render(request, "main/dashboard.html", {"title": "FOSSDB | Dashboard"}) + + +def help(request): + return render(request, "main/help.html", {"title": "FOSSDB | Help"}) diff --git a/src/templates/fossdb/index.html b/src/templates/fossdb/explore.html similarity index 100% rename from src/templates/fossdb/index.html rename to src/templates/fossdb/explore.html diff --git a/src/templates/layout.html b/src/templates/layout.html index 62c5c25..63e09ce 100644 --- a/src/templates/layout.html +++ b/src/templates/layout.html @@ -21,7 +21,8 @@ width="40" src="{% static 'img/icons/logo.svg' %}" alt="logo" /> - fossdb + fossdb
@@ -31,11 +32,16 @@
@@ -45,6 +51,7 @@
+ {% block content %}{% endblock %}