diff --git a/accounts/views/edit.py b/accounts/views/edit.py
index 7741e3f..c62a201 100644
--- a/accounts/views/edit.py
+++ b/accounts/views/edit.py
@@ -13,7 +13,7 @@ class EditView(APIView):
authentication_classes = (SessionAuthentication,)
def get(self, request: HttpRequest):
- return Response({"username": request.user.username})
+ return Response({"username": request.user.username, "id": request.user.pk})
def patch(self, request: HttpRequest):
data: dict = request.data
diff --git a/accounts/views/logged.py b/accounts/views/logged.py
index 3956cd2..8e2fecb 100644
--- a/accounts/views/logged.py
+++ b/accounts/views/logged.py
@@ -13,4 +13,6 @@ class LoggedView(APIView):
authentication_classes = (SessionAuthentication,)
def get(self, request: HttpRequest):
- return Response(str(request.user.is_authenticated), status=status.HTTP_200_OK)
\ No newline at end of file
+ if (request.user.is_authenticated):
+ return Response({'id': request.user.pk}, status=status.HTTP_200_OK)
+ return Response('false', status=status.HTTP_200_OK)
\ No newline at end of file
diff --git a/accounts/views/login.py b/accounts/views/login.py
index 1ee192f..490f79b 100644
--- a/accounts/views/login.py
+++ b/accounts/views/login.py
@@ -20,4 +20,4 @@ class LoginView(APIView):
if user is None:
return Response({'user': ['Username or password wrong.']}, status.HTTP_200_OK)
login(request, user)
- return Response('user connected', status=status.HTTP_200_OK)
\ No newline at end of file
+ return Response({'id': user.pk}, status=status.HTTP_200_OK)
\ No newline at end of file
diff --git a/frontend/static/js/api/client.js b/frontend/static/js/api/client.js
index 4469896..537a99e 100644
--- a/frontend/static/js/api/client.js
+++ b/frontend/static/js/api/client.js
@@ -1,4 +1,5 @@
import { Account } from "./account.js";
+import { Profile } from "./profile.js";
function getCookie(name)
{
@@ -73,12 +74,26 @@ class Client
return response;
}
+ async _patch_file(uri, file)
+ {
+ let response = await fetch(this._url + uri, {
+ method: "PATCH",
+ headers: {
+ "X-CSRFToken": getCookie("csrftoken"),
+ },
+ body: file,
+ });
+ return response;
+ }
+
async login(username, password)
{
let response = await this._post("/api/accounts/login", {username: username, password: password})
let data = await response.json();
- if (data == "user connected")
+ if (data.id != undefined)
{
+ this.me = new Profile(this)
+ await this.me.init(data.id)
this.logged = true;
return null;
}
@@ -95,7 +110,13 @@ class Client
{
let response = await this._get("/api/accounts/logged");
let data = await response.json();
- return data === "True";
+
+ if (data.id !== undefined)
+ {
+ this.me = new Profile(this)
+ await this.me.init(data.id)
+ }
+ return data.id !== undefined;
}
}
diff --git a/frontend/static/js/api/profile.js b/frontend/static/js/api/profile.js
new file mode 100644
index 0000000..e5ed1a5
--- /dev/null
+++ b/frontend/static/js/api/profile.js
@@ -0,0 +1,34 @@
+class Profile
+{
+ constructor (client)
+ {
+ this.client = client;
+ this.username = undefined;
+ this.avatar_url = undefined
+ }
+
+ async init(id)
+ {
+ let response = await this.client._get(`/api/profiles/${id}`);
+ let response_data = await response.json();
+
+ this.id = id;
+ this.username = response_data.username;
+ this.avatar_url = response_data.avatar_url;
+ }
+
+ async change_avatar(form_data)
+ {
+ let response = await this.client._patch_file(`/api/profiles/${this.id}`, form_data);
+ let response_data = await response.json()
+
+ return response_data;
+ }
+
+ async setData (data)
+ {
+
+ }
+}
+
+export {Profile}
\ No newline at end of file
diff --git a/frontend/static/js/views/MeView.js b/frontend/static/js/views/MeView.js
index ce5c600..8ae6378 100644
--- a/frontend/static/js/views/MeView.js
+++ b/frontend/static/js/views/MeView.js
@@ -91,18 +91,31 @@ export default class extends AbstractAuthentificateView
if (error_display != null)
error_display.innerHTML = response_data[error_field];
});
+ let avatar = document.getElementById("avatar");
+
+ if (avatar.files[0] !== undefined)
+ {
+ let form_data = new FormData();
+ form_data.append("file", avatar.files[0]);
+ await client.me.change_avatar(form_data)
+ }
}
async getHtml()
{
return `
ME
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
diff --git a/profiles/models.py b/profiles/models.py
index f34eb29..3c12017 100644
--- a/profiles/models.py
+++ b/profiles/models.py
@@ -3,11 +3,15 @@ from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.dispatch import receiver
+from django.conf import settings
+
+def upload_to(instance, filename: str):
+ return f"./profiles/static/avatars/{instance.pk}.{filename.split('.')[1]}"
# Create your models here.
class ProfileModel(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
- title = models.CharField(max_length=40)
+ avatar_url = models.ImageField(upload_to=upload_to, default="../static/avatars/default.avif") #blank=True, null=True)
@receiver(post_save, sender=User)
def on_user_created(sender, instance, created, **kwargs):
diff --git a/profiles/serializers.py b/profiles/serializers.py
new file mode 100644
index 0000000..15dde29
--- /dev/null
+++ b/profiles/serializers.py
@@ -0,0 +1,12 @@
+from rest_framework import serializers
+from .models import ProfileModel
+
+class ProfileSerializer(serializers.ModelSerializer):
+
+ username = serializers.ReadOnlyField(source='user.username')
+ #creator_id = serializers.ReadOnlyField(source='user.pk')
+ avatar_url = serializers.ImageField(required=False)
+
+ class Meta:
+ model = ProfileModel
+ fields = ["username", "avatar_url"]
\ No newline at end of file
diff --git a/profiles/static/avatars/1.JPG b/profiles/static/avatars/1.JPG
new file mode 100644
index 0000000..a4bc4b8
Binary files /dev/null and b/profiles/static/avatars/1.JPG differ
diff --git a/profiles/static/avatars/default.avif b/profiles/static/avatars/default.avif
new file mode 100644
index 0000000..d7f1413
Binary files /dev/null and b/profiles/static/avatars/default.avif differ
diff --git a/profiles/status_code.py b/profiles/status_code.py
deleted file mode 100644
index 187f78f..0000000
--- a/profiles/status_code.py
+++ /dev/null
@@ -1 +0,0 @@
-PROFILE_NOT_FOUND = "Profile Not Found"
\ No newline at end of file
diff --git a/profiles/urls.py b/profiles/urls.py
index 9dc15a8..5b92202 100644
--- a/profiles/urls.py
+++ b/profiles/urls.py
@@ -1,7 +1,10 @@
from django.urls import path
+from django.conf import settings
+from django.conf.urls.static import static
-from . import views
+from . import viewsets
urlpatterns = [
- path("", views.ProfileView.as_view(), name="profile_page"),
-]
\ No newline at end of file
+ path("", viewsets.ProfileViewSet.as_view({'get': 'retrieve', 'patch': 'partial_update'}), name="profile_page"),
+ #path("me", viewsets.ProfileViewSet.as_view(), name="my_profile_page"),
+] + static("/static/avatars/", document_root="./avatars")
\ No newline at end of file
diff --git a/profiles/views.py b/profiles/views.py
deleted file mode 100644
index 2a67b8e..0000000
--- a/profiles/views.py
+++ /dev/null
@@ -1,19 +0,0 @@
-from django.http import HttpRequest
-from rest_framework.views import APIView
-from rest_framework.response import Response
-from rest_framework import permissions, status
-
-from .models import ProfileModel
-
-# Create your views here.
-class ProfileView(APIView):
- permission_classes = (permissions.AllowAny,)
-
- def get(self, request: HttpRequest, pk: int):
-
- profile: ProfileModel = ProfileModel.objects.get(pk=pk)
- if (profile is None):
- return Response(status=status.HTTP_404_NOT_FOUND)
-
- return Response(status=status.HTTP_200_OK, data={'name': profile.user.username,
- 'title': profile.title})
\ No newline at end of file
diff --git a/profiles/viewsets.py b/profiles/viewsets.py
new file mode 100644
index 0000000..c9f7584
--- /dev/null
+++ b/profiles/viewsets.py
@@ -0,0 +1,33 @@
+from rest_framework import permissions
+from rest_framework.parsers import MultiPartParser, FormParser
+from rest_framework import permissions, status
+from rest_framework import viewsets
+from rest_framework.response import Response
+
+
+from django.db.models import QuerySet
+
+from .serializers import ProfileSerializer
+from .models import ProfileModel
+
+class ProfileViewSet(viewsets.ModelViewSet):
+ queryset = ProfileModel.objects.order_by('-pk')
+ serializer_class = ProfileSerializer
+ parser_classes = (MultiPartParser, FormParser)
+ permission_classes = (permissions.IsAuthenticatedOrReadOnly,)
+
+ def perform_create(self, serializer):
+ serializer.save(user=self.request.user)
+
+ def perform_update(self, serializer):
+ query: QuerySet = ProfileModel.objects.filter(pk=self.request.user.pk)
+ if (not query.exists()):
+ return Response("profile not found", status=status.HTTP_400_BAD_REQUEST)
+ profile: ProfileModel = ProfileModel.objects.get(pk=self.request.user.pk)
+ avatar = self.request.data.get("file", None)
+ if (avatar is not None):
+ print(profile.avatar_url.name)
+ if (profile.avatar_url.name != "default.avif"):
+ profile.avatar_url.storage.delete(profile.avatar_url.name)
+ profile.avatar_url = avatar
+ profile.save()
\ No newline at end of file
diff --git a/trancendence/settings.py b/trancendence/settings.py
index e6f29dd..4e89778 100644
--- a/trancendence/settings.py
+++ b/trancendence/settings.py
@@ -10,6 +10,8 @@ For the full list of settings and their values, see
https://docs.djangoproject.com/en/4.2/ref/settings/
"""
+import os
+
from pathlib import Path
# Build paths inside the project like this: BASE_DIR / 'subdir'.
@@ -146,4 +148,4 @@ 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'
\ No newline at end of file
diff --git a/trancendence/urls.py b/trancendence/urls.py
index 4623fa9..0f136f1 100644
--- a/trancendence/urls.py
+++ b/trancendence/urls.py
@@ -22,4 +22,4 @@ urlpatterns = [
path('api/profiles/', include('profiles.urls')),
path('api/accounts/', include('accounts.urls')),
path('', include('frontend.urls')),
-]
+]
\ No newline at end of file