diff --git a/.gitignore b/.gitignore index d3cebda..941deef 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ .env settings.py __pycache__/ -db.sqlite3 \ No newline at end of file +db.sqlite3 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..18556b8 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,19 @@ +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v2.3.0 + hooks: + - id: check-yaml + - id: end-of-file-fixer + - id: trailing-whitespace + - repo: https://github.com/psf/black + rev: 22.10.0 + hooks: + - id: black + #- repo: https://github.com/thibaudcolas/curlylint + # rev: v0.13.1 + # hooks: + # - id: curlylint + - repo: https://github.com/pre-commit/mirrors-prettier + rev: v3.0.2 + hooks: + - id: prettier diff --git a/README.md b/README.md index cb93f00..641a213 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,3 @@ # code-spark + Code Spark: A dating-style app for programmers to find project partners. And love? diff --git a/TODO.md b/TODO.md new file mode 100644 index 0000000..bdaec3e --- /dev/null +++ b/TODO.md @@ -0,0 +1,12 @@ +# Todo + +- [x] login feature +- [x] see another profile, selected randomly + - [x] design necessary data + - [x] mvp of seeing another user from the database + - [x] randomize it +- [ ] Let a user to request a match or decline + - [x] Send a form response to /match + - [x] Receive the form and create a MatchRequest object + - [x] Handle the case on the home page when there are no matches available + - [ ] Handle the case when user requests a match and a match reqeust object exists with current user as the target diff --git a/code_spark/app/apps.py b/code_spark/app/apps.py index ed327d2..bcfe39b 100644 --- a/code_spark/app/apps.py +++ b/code_spark/app/apps.py @@ -2,5 +2,5 @@ class AppConfig(AppConfig): - default_auto_field = 'django.db.models.BigAutoField' - name = 'app' + default_auto_field = "django.db.models.BigAutoField" + name = "app" diff --git a/code_spark/app/migrations/0001_initial.py b/code_spark/app/migrations/0001_initial.py index 46f0c1c..ba14608 100644 --- a/code_spark/app/migrations/0001_initial.py +++ b/code_spark/app/migrations/0001_initial.py @@ -8,26 +8,55 @@ class Migration(migrations.Migration): initial = True - dependencies = [ - ] + dependencies = [] operations = [ migrations.CreateModel( - name='UserAccount', + name="UserAccount", fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('github_profile_name', models.CharField(max_length=255, unique=True)), + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("github_profile_name", models.CharField(max_length=255, unique=True)), ], ), migrations.CreateModel( - name='MatchRequest', + name="MatchRequest", fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('match_request_status', models.IntegerField()), - ('created_date', models.DateTimeField(auto_now_add=True)), - ('accepted_date', models.DateTimeField(blank=True, null=True)), - ('match_request_receiver', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='received_requests', to='app.useraccount')), - ('match_request_sender', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='sent_requests', to='app.useraccount')), + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("match_request_status", models.IntegerField()), + ("created_date", models.DateTimeField(auto_now_add=True)), + ("accepted_date", models.DateTimeField(blank=True, null=True)), + ( + "match_request_receiver", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="received_requests", + to="app.useraccount", + ), + ), + ( + "match_request_sender", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="sent_requests", + to="app.useraccount", + ), + ), ], ), ] diff --git a/code_spark/app/migrations/0002_alter_matchrequest_match_request_receiver_and_more.py b/code_spark/app/migrations/0002_alter_matchrequest_match_request_receiver_and_more.py new file mode 100644 index 0000000..9776814 --- /dev/null +++ b/code_spark/app/migrations/0002_alter_matchrequest_match_request_receiver_and_more.py @@ -0,0 +1,37 @@ +# Generated by Django 4.2.4 on 2023-08-17 15:45 + +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), + ("app", "0001_initial"), + ] + + operations = [ + migrations.AlterField( + model_name="matchrequest", + name="match_request_receiver", + field=models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="received_requests", + to=settings.AUTH_USER_MODEL, + ), + ), + migrations.AlterField( + model_name="matchrequest", + name="match_request_sender", + field=models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="sent_requests", + to=settings.AUTH_USER_MODEL, + ), + ), + migrations.DeleteModel( + name="UserAccount", + ), + ] diff --git a/code_spark/app/models.py b/code_spark/app/models.py index 86f1c27..a4b73cb 100644 --- a/code_spark/app/models.py +++ b/code_spark/app/models.py @@ -3,9 +3,15 @@ class MatchRequest(models.Model): - match_request_sender = models.ForeignKey(User, related_name='sent_requests', on_delete=models.CASCADE) - match_request_receiver = models.ForeignKey(User, related_name='received_requests', on_delete=models.CASCADE) - match_request_status = models.IntegerField() + match_request_sender = models.ForeignKey( + User, related_name="sent_requests", on_delete=models.CASCADE + ) + match_request_receiver = models.ForeignKey( + User, related_name="received_requests", on_delete=models.CASCADE + ) + match_request_status = ( + models.IntegerField() + ) # 1 is request_match sent, -1 is sender declined, 2 is receiver accepted, -2 is receiver declined. created_date = models.DateTimeField(auto_now_add=True) accepted_date = models.DateTimeField(null=True, blank=True) diff --git a/code_spark/app/templates/base.html b/code_spark/app/templates/base.html index 9c4361b..268d3c7 100644 --- a/code_spark/app/templates/base.html +++ b/code_spark/app/templates/base.html @@ -1,26 +1,25 @@ {% load static %} - + - - - - - - - DJANGO SOCIAL AUTH - - -
-
-

- {% block title %} - {% endblock %} -

-
- {% block content %} - {% endblock %} -
-
-
- - \ No newline at end of file + + + + + + + DJANGO SOCIAL AUTH + + +
+
+

{% block title %} {% endblock %}

+
{% block content %} {% endblock %}
+
+
+ + diff --git a/code_spark/app/templates/home.html b/code_spark/app/templates/home.html index 861121b..d972e5e 100644 --- a/code_spark/app/templates/home.html +++ b/code_spark/app/templates/home.html @@ -1,9 +1,30 @@ -{% extends 'base.html' %} -{% block title %}HOME{% endblock %} -{% block content %} -
-
-

Welcome {{ user.username }}

-
+{% extends 'base.html' %} {% block title %}HOME{% endblock %} {% block content%} +
+
+

Welcome {{ user.username }}

+

{{ potential_match_message }}

+ {% if potential_match %} +

Would you like to request a match?

+
+
+ + +
+ +
+ + +
-{% endblock %} \ No newline at end of file + {% endif %} +
+
+{% endblock %} diff --git a/code_spark/app/templates/login.html b/code_spark/app/templates/login.html index 51bbe3a..9b020cb 100644 --- a/code_spark/app/templates/login.html +++ b/code_spark/app/templates/login.html @@ -1,13 +1,10 @@ -{% extends 'base.html' %} -{% block title %}Sign in{% endblock %} -{% block content %} -
- -
-{% endblock %} \ No newline at end of file +{% extends 'base.html' %} {% block title %}Sign in{% endblock %} {% block +content %} +
+ +
+{% endblock %} diff --git a/code_spark/app/views.py b/code_spark/app/views.py index 6efe501..d077c86 100644 --- a/code_spark/app/views.py +++ b/code_spark/app/views.py @@ -1,12 +1,97 @@ from django.shortcuts import render from django.contrib.auth.decorators import login_required +from .models import MatchRequest +from django.http import HttpResponse +from django.contrib.auth.models import User +from django.template import loader +from django.shortcuts import redirect # Create your views here. def login(request): - return render(request, 'login.html') + return render(request, "login.html") + @login_required def home(request): - return render(request, 'home.html') \ No newline at end of file + potential_match = get_potential_match(request.user) + if potential_match: + potential_match_message = "Your potential match is " + potential_match.username + else: + potential_match_message = ( + "No potential matches available. Please check back later" + ) + context = { + "potential_match_message": potential_match_message, + "potential_match": potential_match, + } + template = loader.get_template("home.html") + return HttpResponse(template.render(context, request)) + + +# @login_required +# def match(request, other_requesting_user=None): +# if other_requesting_user: +# match_request = MatchRequest(match_request_sender) + + +@login_required +def request(request): + user = request.user + if MatchRequest.objects.filter(match_request_receiver=user).count() == 1: + pass + # TODO: redirect to match + match_request = MatchRequest( + match_request_sender=user, + match_request_receiver=User.objects.get(username=request.GET["target-user"]), + match_request_status=1, + # do not set created_date or accepted date + ) + match_request.save() + # TODO: check for an existing matching match request_match. If found, will go to match, else go home + return redirect("home") + + +@login_required +def decline(request): + user = request.user + # other_requesting_user = MatchRequest.objects.get(match_request_receiver=user) + # matching_match_request = MatchRequest.objects.get(match_request_receiver=user) + # matching_match_request. + match_request = MatchRequest( + match_request_sender=user, + match_request_receiver=User.objects.get(username=request.GET["target-user"]), + match_request_status=-1, + # do not set created_date or accepted date + ) + match_request.save() + # TODO: check for an existing matching match request_match. If found, will go to match, else go home + return redirect("home") + + +def get_potential_match(user): + """ + Returns a user that the current user has not been seen by and + has not seen. + :param user: + :return: + """ + + from random import choice + + pks = ( + User.objects.exclude( + received_requests__match_request_sender__username=user.username + ) + # .exclude( # TODO: is this needed? + # sent_requests__match_request_receiver__username=user.username + # ) + .exclude(username=user.username).values_list("pk", flat=True) + ) + if len(pks) == 0: + return None + random_pk = choice(pks) + potential_match = User.objects.get(pk=random_pk) + + return potential_match diff --git a/code_spark/code_spark/asgi.py b/code_spark/code_spark/asgi.py index b93097c..6d0b971 100644 --- a/code_spark/code_spark/asgi.py +++ b/code_spark/code_spark/asgi.py @@ -11,6 +11,6 @@ from django.core.asgi import get_asgi_application -os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'code_spark.settings') +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "code_spark.settings") application = get_asgi_application() diff --git a/code_spark/code_spark/example_settings_example.py b/code_spark/code_spark/example_settings_example.py index 9adb4dd..4a2e57b 100644 --- a/code_spark/code_spark/example_settings_example.py +++ b/code_spark/code_spark/example_settings_example.py @@ -31,73 +31,72 @@ # Application definition INSTALLED_APPS = [ - 'django.contrib.admin', - 'django.contrib.auth', - 'django.contrib.contenttypes', - 'django.contrib.sessions', - 'django.contrib.messages', - 'django.contrib.staticfiles', - 'app', # add - 'social_django', # add - + "django.contrib.admin", + "django.contrib.auth", + "django.contrib.contenttypes", + "django.contrib.sessions", + "django.contrib.messages", + "django.contrib.staticfiles", + "app", # add + "social_django", # add ] MIDDLEWARE = [ - 'django.middleware.security.SecurityMiddleware', - 'django.contrib.sessions.middleware.SessionMiddleware', - 'django.middleware.common.CommonMiddleware', - 'django.middleware.csrf.CsrfViewMiddleware', - 'django.contrib.auth.middleware.AuthenticationMiddleware', - 'django.contrib.messages.middleware.MessageMiddleware', - 'django.middleware.clickjacking.XFrameOptionsMiddleware', - 'social_django.middleware.SocialAuthExceptionMiddleware', #add this + "django.middleware.security.SecurityMiddleware", + "django.contrib.sessions.middleware.SessionMiddleware", + "django.middleware.common.CommonMiddleware", + "django.middleware.csrf.CsrfViewMiddleware", + "django.contrib.auth.middleware.AuthenticationMiddleware", + "django.contrib.messages.middleware.MessageMiddleware", + "django.middleware.clickjacking.XFrameOptionsMiddleware", + "social_django.middleware.SocialAuthExceptionMiddleware", # add this ] SITE_ID = 1 -ROOT_URLCONF = 'code_spark.urls' +ROOT_URLCONF = "code_spark.urls" TEMPLATES = [ { - 'BACKEND': 'django.template.backends.django.DjangoTemplates', - 'DIRS': [], - 'APP_DIRS': True, - 'OPTIONS': { - 'context_processors': [ - 'django.template.context_processors.debug', - 'django.template.context_processors.request', - 'django.contrib.auth.context_processors.auth', - 'django.contrib.messages.context_processors.messages', - 'social_django.context_processors.backends', #add this + "BACKEND": "django.template.backends.django.DjangoTemplates", + "DIRS": [], + "APP_DIRS": True, + "OPTIONS": { + "context_processors": [ + "django.template.context_processors.debug", + "django.template.context_processors.request", + "django.contrib.auth.context_processors.auth", + "django.contrib.messages.context_processors.messages", + "social_django.context_processors.backends", # add this ], }, }, ] AUTHENTICATION_BACKENDS = ( - 'allauth.account.auth_backends.AuthenticationBackend', - 'social_core.backends.github.GithubOAuth2', + "allauth.account.auth_backends.AuthenticationBackend", + "social_core.backends.github.GithubOAuth2", ) -SOCIAL_AUTH_GITHUB_KEY = 'cHaNgEmE' -SOCIAL_AUTH_GITHUB_SECRET = 'cHaNgEmE' -LOGIN_URL = 'login' -LOGIN_REDIRECT_URL = '/' -LOGOUT_URL = 'logout' -LOGOUT_REDIRECT_URL = 'login' -SOCIAL_AUTH_GITHUB_CALLBACK_URL = 'http://127.0.0.1:8000/social-auth/complete/github/' +SOCIAL_AUTH_GITHUB_KEY = "cHaNgEmE" +SOCIAL_AUTH_GITHUB_SECRET = "cHaNgEmE" +LOGIN_URL = "login" +LOGIN_REDIRECT_URL = "/" +LOGOUT_URL = "logout" +LOGOUT_REDIRECT_URL = "login" +SOCIAL_AUTH_GITHUB_CALLBACK_URL = "http://127.0.0.1:8000/social-auth/complete/github/" -WSGI_APPLICATION = 'code_spark.wsgi.application' +WSGI_APPLICATION = "code_spark.wsgi.application" # Database # https://docs.djangoproject.com/en/4.2/ref/settings/#databases DATABASES = { - 'default': { - 'ENGINE': 'django.db.backends.sqlite3', - 'NAME': BASE_DIR / 'db.sqlite3', + "default": { + "ENGINE": "django.db.backends.sqlite3", + "NAME": BASE_DIR / "db.sqlite3", } } @@ -105,9 +104,9 @@ # Internationalization # https://docs.djangoproject.com/en/4.2/topics/i18n/ -LANGUAGE_CODE = 'en-us' +LANGUAGE_CODE = "en-us" -TIME_ZONE = 'UTC' +TIME_ZONE = "UTC" USE_I18N = True @@ -117,10 +116,9 @@ # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/4.2/howto/static-files/ -STATIC_URL = 'static/' +STATIC_URL = "static/" # Default primary key field type # https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field -DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' - +DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField" diff --git a/code_spark/code_spark/urls.py b/code_spark/code_spark/urls.py index 7fe5161..21a0385 100644 --- a/code_spark/code_spark/urls.py +++ b/code_spark/code_spark/urls.py @@ -20,9 +20,11 @@ from app import views urlpatterns = [ - path('admin/', admin.site.urls), - path('login/', views.login, name='login'), - path('logout', auth_views.LogoutView.as_view(), name='logout'), - path('social-auth/', include('social_django.urls', namespace='social')), - path("", views.home, name='home'), -] \ No newline at end of file + path("admin/", admin.site.urls), + path("login/", views.login, name="login"), + path("logout", auth_views.LogoutView.as_view(), name="logout"), + path("social-auth/", include("social_django.urls", namespace="social")), + path("", views.home, name="home"), + path("request", views.request, name="request"), + path("decline", views.decline, name="decline"), +] diff --git a/code_spark/code_spark/wsgi.py b/code_spark/code_spark/wsgi.py index 987055a..d028428 100644 --- a/code_spark/code_spark/wsgi.py +++ b/code_spark/code_spark/wsgi.py @@ -11,6 +11,6 @@ from django.core.wsgi import get_wsgi_application -os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'code_spark.settings') +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "code_spark.settings") application = get_wsgi_application() diff --git a/code_spark/manage.py b/code_spark/manage.py index 10003bb..8a62ce5 100755 --- a/code_spark/manage.py +++ b/code_spark/manage.py @@ -6,7 +6,7 @@ def main(): """Run administrative tasks.""" - os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'code_spark.settings') + os.environ.setdefault("DJANGO_SETTINGS_MODULE", "code_spark.settings") try: from django.core.management import execute_from_command_line except ImportError as exc: @@ -18,5 +18,5 @@ def main(): execute_from_command_line(sys.argv) -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/poetry.lock b/poetry.lock index 25b2ea5..2b6021a 100644 --- a/poetry.lock +++ b/poetry.lock @@ -101,6 +101,17 @@ files = [ [package.dependencies] pycparser = "*" +[[package]] +name = "cfgv" +version = "3.4.0" +description = "Validate configuration and produce human readable error messages." +optional = false +python-versions = ">=3.8" +files = [ + {file = "cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9"}, + {file = "cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560"}, +] + [[package]] name = "charset-normalizer" version = "3.2.0" @@ -241,6 +252,17 @@ files = [ {file = "defusedxml-0.7.1.tar.gz", hash = "sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69"}, ] +[[package]] +name = "distlib" +version = "0.3.7" +description = "Distribution utilities" +optional = false +python-versions = "*" +files = [ + {file = "distlib-0.3.7-py2.py3-none-any.whl", hash = "sha256:2e24928bc811348f0feb63014e97aaae3037f2cf48712d51ae61df7fd6075057"}, + {file = "distlib-0.3.7.tar.gz", hash = "sha256:9dafe54b34a028eafd95039d5e5d4851a13734540f1331060d31c9916e7147a8"}, +] + [[package]] name = "django" version = "4.2.4" @@ -278,6 +300,35 @@ python3-openid = ">=3.0.8" requests = "*" requests-oauthlib = ">=0.3.0" +[[package]] +name = "filelock" +version = "3.12.2" +description = "A platform independent file lock." +optional = false +python-versions = ">=3.7" +files = [ + {file = "filelock-3.12.2-py3-none-any.whl", hash = "sha256:cbb791cdea2a72f23da6ac5b5269ab0a0d161e9ef0100e653b69049a7706d1ec"}, + {file = "filelock-3.12.2.tar.gz", hash = "sha256:002740518d8aa59a26b0c76e10fb8c6e15eae825d34b6fdf670333fd7b938d81"}, +] + +[package.extras] +docs = ["furo (>=2023.5.20)", "sphinx (>=7.0.1)", "sphinx-autodoc-typehints (>=1.23,!=1.23.4)"] +testing = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "diff-cover (>=7.5)", "pytest (>=7.3.1)", "pytest-cov (>=4.1)", "pytest-mock (>=3.10)", "pytest-timeout (>=2.1)"] + +[[package]] +name = "identify" +version = "2.5.26" +description = "File identification library for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "identify-2.5.26-py2.py3-none-any.whl", hash = "sha256:c22a8ead0d4ca11f1edd6c9418c3220669b3b7533ada0a0ffa6cc0ef85cf9b54"}, + {file = "identify-2.5.26.tar.gz", hash = "sha256:7243800bce2f58404ed41b7c002e53d4d22bcf3ae1b7900c2d7aefd95394bf7f"}, +] + +[package.extras] +license = ["ukkonen"] + [[package]] name = "idna" version = "3.4" @@ -289,6 +340,20 @@ files = [ {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"}, ] +[[package]] +name = "nodeenv" +version = "1.8.0" +description = "Node.js virtual environment builder" +optional = false +python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*" +files = [ + {file = "nodeenv-1.8.0-py2.py3-none-any.whl", hash = "sha256:df865724bb3c3adc86b3876fa209771517b0cfe596beff01a92700e0e8be4cec"}, + {file = "nodeenv-1.8.0.tar.gz", hash = "sha256:d51e0c37e64fbf47d017feac3145cdbb58836d7eee8c6f6d3b6880c5456227d2"}, +] + +[package.dependencies] +setuptools = "*" + [[package]] name = "oauthlib" version = "3.2.2" @@ -305,6 +370,39 @@ rsa = ["cryptography (>=3.0.0)"] signals = ["blinker (>=1.4.0)"] signedtoken = ["cryptography (>=3.0.0)", "pyjwt (>=2.0.0,<3)"] +[[package]] +name = "platformdirs" +version = "3.10.0" +description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +optional = false +python-versions = ">=3.7" +files = [ + {file = "platformdirs-3.10.0-py3-none-any.whl", hash = "sha256:d7c24979f292f916dc9cbf8648319032f551ea8c49a4c9bf2fb556a02070ec1d"}, + {file = "platformdirs-3.10.0.tar.gz", hash = "sha256:b45696dab2d7cc691a3226759c0d3b00c47c8b6e293d96f6436f733303f77f6d"}, +] + +[package.extras] +docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.1)", "sphinx-autodoc-typehints (>=1.24)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4)", "pytest-cov (>=4.1)", "pytest-mock (>=3.11.1)"] + +[[package]] +name = "pre-commit" +version = "3.3.3" +description = "A framework for managing and maintaining multi-language pre-commit hooks." +optional = false +python-versions = ">=3.8" +files = [ + {file = "pre_commit-3.3.3-py2.py3-none-any.whl", hash = "sha256:10badb65d6a38caff29703362271d7dca483d01da88f9d7e05d0b97171c136cb"}, + {file = "pre_commit-3.3.3.tar.gz", hash = "sha256:a2256f489cd913d575c145132ae196fe335da32d91a8294b7afe6622335dd023"}, +] + +[package.dependencies] +cfgv = ">=2.0.0" +identify = ">=1.0.0" +nodeenv = ">=0.11.1" +pyyaml = ">=5.1" +virtualenv = ">=20.10.0" + [[package]] name = "pycparser" version = "2.21" @@ -354,6 +452,55 @@ defusedxml = "*" mysql = ["mysql-connector-python"] postgresql = ["psycopg2"] +[[package]] +name = "pyyaml" +version = "6.0.1" +description = "YAML parser and emitter for Python" +optional = false +python-versions = ">=3.6" +files = [ + {file = "PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a"}, + {file = "PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, + {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, + {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, + {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, + {file = "PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, + {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, + {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, + {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd"}, + {file = "PyYAML-6.0.1-cp36-cp36m-win32.whl", hash = "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585"}, + {file = "PyYAML-6.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa"}, + {file = "PyYAML-6.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c"}, + {file = "PyYAML-6.0.1-cp37-cp37m-win32.whl", hash = "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba"}, + {file = "PyYAML-6.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867"}, + {file = "PyYAML-6.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, + {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, + {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, + {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, + {file = "PyYAML-6.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, + {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, + {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, + {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, +] + [[package]] name = "requests" version = "2.31.0" @@ -393,6 +540,22 @@ requests = ">=2.0.0" [package.extras] rsa = ["oauthlib[signedtoken] (>=3.0.0)"] +[[package]] +name = "setuptools" +version = "68.1.0" +description = "Easily download, build, install, upgrade, and uninstall Python packages" +optional = false +python-versions = ">=3.8" +files = [ + {file = "setuptools-68.1.0-py3-none-any.whl", hash = "sha256:e13e1b0bc760e9b0127eda042845999b2f913e12437046e663b833aa96d89715"}, + {file = "setuptools-68.1.0.tar.gz", hash = "sha256:d59c97e7b774979a5ccb96388efc9eb65518004537e85d52e81eaee89ab6dd91"}, +] + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (==0.8.3)", "sphinx-reredirects", "sphinxcontrib-towncrier"] +testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] +testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] + [[package]] name = "social-auth-app-django" version = "5.2.0" @@ -479,7 +642,27 @@ secure = ["certifi", "cryptography (>=1.9)", "idna (>=2.0.0)", "pyopenssl (>=17. socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] zstd = ["zstandard (>=0.18.0)"] +[[package]] +name = "virtualenv" +version = "20.24.3" +description = "Virtual Python Environment builder" +optional = false +python-versions = ">=3.7" +files = [ + {file = "virtualenv-20.24.3-py3-none-any.whl", hash = "sha256:95a6e9398b4967fbcb5fef2acec5efaf9aa4972049d9ae41f95e0972a683fd02"}, + {file = "virtualenv-20.24.3.tar.gz", hash = "sha256:e5c3b4ce817b0b328af041506a2a299418c98747c4b1e68cb7527e74ced23efc"}, +] + +[package.dependencies] +distlib = ">=0.3.7,<1" +filelock = ">=3.12.2,<4" +platformdirs = ">=3.9.1,<4" + +[package.extras] +docs = ["furo (>=2023.5.20)", "proselint (>=0.13)", "sphinx (>=7.0.1)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"] +test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.4)", "pytest-env (>=0.8.2)", "pytest-freezer (>=0.4.8)", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=68)", "time-machine (>=2.10)"] + [metadata] lock-version = "2.0" python-versions = "^3.11" -content-hash = "4da577959b9d0b0af8da4868476292db51eab4e3940f7d11f555284fa395b324" +content-hash = "5a8bd7db4838266521616dcfade1dea5e0df1c62734404ce377b126bf7d9d75e" diff --git a/pyproject.toml b/pyproject.toml index 2e1e6d8..7b0e5eb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -13,6 +13,9 @@ django-allauth = "^0.54.0" social-auth-app-django = "^5.2.0" +[tool.poetry.group.dev.dependencies] +pre-commit = "^3.3.3" + [build-system] requires = ["poetry-core"] build-backend = "poetry.core.masonry.api" diff --git a/sandbox/data_design.md b/sandbox/data_design.md new file mode 100644 index 0000000..5d28e3d --- /dev/null +++ b/sandbox/data_design.md @@ -0,0 +1,42 @@ +# Data Design + +In order to show a user a new profile from another user, the app needs to know: + +- what other users the currently logged in user has already seen (and reacted to) +- What users are signed up for the app overall + +It turns out, the current data design, which I lifted from a tinder clone tutorial website, +is sufficient to hold this information. + +We will just need to do a search of the database model MatchRequest, with +match_request_sender equal to current user or match_request_receiver equal to +current user. +These are the profiles we should not show to the user. +Then we search in the users database, with the condition that username not equal +the usernames found in the previous step. + +Also, here is more commentary on the MatchRequest datatype. + +Currently in the models file: + +```py +match_request_status = models.IntegerField() # 0 is requested, 1 is accepted, -1 is rejected +created_date = models.DateTimeField(auto_now_add=True) +accepted_date = models.DateTimeField(null=True, blank=True) +``` + +I want to adjust the codes in match_request_status +0 would be unseen, except in that case there will be no entry in the database at all +1 will be request sent, it means user who was presented with the potential match first will +have clicked yes or "swiped right" on the other user. +-1 will be rejected. It means the user who was presented with the potential match said no +or "swiped left" on the other user. +(side note: will it be possible to have a record with usera as sender rejecting userb as potential +receiver, and a separate record with userb as sender rejecting user a as a potential receiver. +Let's say no. Becuase if userA rejected userB, let's just not show userA to userB.) +Summary of status codes for match_request_status: 1 is request sent, -1 is sender declined, 2 is receiver accepted, -2 is receiver declined. + +Let's go and update the model code + +side note: do I want a uuid for user IDs, or is it enough to just use the github username. +I think for now, github username will do. But maybe later I will add a uuid. diff --git a/sandbox/database.sql b/sandbox/database.sql index 03000cc..8ff13cd 100644 --- a/sandbox/database.sql +++ b/sandbox/database.sql @@ -19,4 +19,3 @@ CREATE TABLE match_request ( created_date TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP, accepted_date TIMESTAMPTZ ); -