Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# Python
__pycache__/
*.py[cod]
*.sqlite3
*.env
*.log
*.pot
*.pyc
*.pyo
*.pyd
.Python
env/
venv/
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
*.egg-info/
.installed.cfg
*.egg

# Django
*.db
*.sqlite3
/static/
/media/

# Node
node_modules/
dist/
build/
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# VSCode
.vscode/

# Mac
.DS_Store

# Windows
Thumbs.db

# Others
*.swp
*.swo
.idea/
*.iml
*.bak
*.tmp
Binary file modified backend/config/__pycache__/__init__.cpython-311.pyc
Binary file not shown.
Binary file modified backend/config/__pycache__/settings.cpython-311.pyc
Binary file not shown.
Binary file modified backend/config/__pycache__/urls.cpython-311.pyc
Binary file not shown.
27 changes: 20 additions & 7 deletions backend/config/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

BASE_DIR = Path(__file__).resolve().parent.parent
env = environ.Env(DEBUG=(bool, False))
environ.Env.read_env(BASE_DIR / ".env") # 读取 .env
environ.Env.read_env(BASE_DIR / ".env") # 读取 .env

DEBUG = env("DEBUG")
SECRET_KEY = env("SECRET_KEY")
Expand All @@ -24,6 +24,7 @@
"rest_framework",
"rest_framework.authtoken", # 若要 session 认证
"drf_spectacular",
"corsheaders", # <-- Added for CORS
# 本地
"users",
]
Expand All @@ -37,26 +38,28 @@
}

MIDDLEWARE = [
"corsheaders.middleware.CorsMiddleware", # <-- Added for CORS (should be at the top)
"django.middleware.security.SecurityMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware", # ★ 必须
"django.contrib.sessions.middleware.SessionMiddleware", # ★ 必须
"django.middleware.common.CommonMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware", # ★ 必须
"django.contrib.messages.middleware.MessageMiddleware", # ★ 必须
"django.contrib.auth.middleware.AuthenticationMiddleware", # ★ 必须
"django.contrib.messages.middleware.MessageMiddleware", # ★ 必须
"django.middleware.clickjacking.XFrameOptionsMiddleware",
]

# ------------------------------------------------------------------
# TEMPLATES —— 必须有 DjangoTemplates 后端
# ------------------------------------------------------------------
from pathlib import Path

BASE_DIR = Path(__file__).resolve().parent.parent

TEMPLATES = [
{
"BACKEND": "django.template.backends.django.DjangoTemplates", # ★ 必须
"DIRS": [BASE_DIR / "templates"], # 没有模板文件也保留即可
"APP_DIRS": True, # 让 admin 自己的模板可被发现
"DIRS": [BASE_DIR / "templates"], # 没有模板文件也保留即可
"APP_DIRS": True, # 让 admin 自己的模板可被发现
"OPTIONS": {
"context_processors": [
"django.template.context_processors.debug",
Expand All @@ -77,12 +80,15 @@
"DEFAULT_AUTHENTICATION_CLASSES": (
"rest_framework_simplejwt.authentication.JWTAuthentication",
),
"DEFAULT_PERMISSION_CLASSES": ("rest_framework.permissions.IsAuthenticatedOrReadOnly",),
"DEFAULT_PERMISSION_CLASSES": (
"rest_framework.permissions.IsAuthenticatedOrReadOnly",
),
"DEFAULT_SCHEMA_CLASS": "drf_spectacular.openapi.AutoSchema",
}

# -- Simple JWT --
from datetime import timedelta

SIMPLE_JWT = {
"ACCESS_TOKEN_LIFETIME": timedelta(minutes=15),
"REFRESH_TOKEN_LIFETIME": timedelta(days=7),
Expand All @@ -98,3 +104,10 @@
# -- 静态文件 --
STATIC_URL = "/static/"
STATIC_ROOT = BASE_DIR / "staticfiles"

# CORS settings
CORS_ALLOW_ALL_ORIGINS = True # For development only; restrict in production
# If you want to restrict:
# CORS_ALLOWED_ORIGINS = [
# "http://localhost:8080",
# ]
Binary file modified backend/db.sqlite3
Binary file not shown.
Binary file modified backend/users/__pycache__/__init__.cpython-311.pyc
Binary file not shown.
Binary file modified backend/users/__pycache__/admin.cpython-311.pyc
Binary file not shown.
Binary file modified backend/users/__pycache__/apps.cpython-311.pyc
Binary file not shown.
Binary file modified backend/users/__pycache__/models.cpython-311.pyc
Binary file not shown.
Binary file modified backend/users/__pycache__/serializers.cpython-311.pyc
Binary file not shown.
Binary file modified backend/users/__pycache__/urls.cpython-311.pyc
Binary file not shown.
Binary file modified backend/users/__pycache__/views.cpython-311.pyc
Binary file not shown.
36 changes: 31 additions & 5 deletions backend/users/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,39 @@
from django.contrib.auth.admin import UserAdmin
from .models import CustomUser, UserConnection


@admin.register(CustomUser)
class CustomUserAdmin(UserAdmin):
model = CustomUser
list_display = ("id", "username", "email", "job", "mental_health", "wellness")
list_display = (
"id",
"username",
"email",
"job",
"mental_health",
"wellness",
"profile_pic",
"tags",
"phone",
)
fieldsets = UserAdmin.fieldsets + (
("Extra", {"fields": ("job", "mental_health", "wellness", "engage",
"location", "gender", "age", "description", "hobby")}),
(
"Extra",
{
"fields": (
"job",
"mental_health",
"wellness",
"engage",
"location",
"gender",
"age",
"description",
"hobby",
"profile_pic",
"tags",
"phone",
)
},
),
)

admin.site.register(UserConnection)
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Generated by Django 5.2.1 on 2025-06-04 04:08

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('users', '0001_initial'),
]

operations = [
migrations.AddField(
model_name='customuser',
name='phone',
field=models.CharField(blank=True, max_length=20, null=True),
),
migrations.AddField(
model_name='customuser',
name='profile_pic',
field=models.TextField(blank=True, null=True),
),
migrations.AddField(
model_name='customuser',
name='tags',
field=models.CharField(blank=True, max_length=255, null=True),
),
]
Binary file not shown.
Binary file modified backend/users/migrations/__pycache__/__init__.cpython-311.pyc
Binary file not shown.
4 changes: 4 additions & 0 deletions backend/users/models.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from django.contrib.auth.models import AbstractUser
from django.db import models


class CustomUser(AbstractUser):
job = models.CharField(max_length=100, null=True, blank=True)
mental_health = models.PositiveSmallIntegerField(null=True, blank=True)
Expand All @@ -11,6 +12,9 @@ class CustomUser(AbstractUser):
age = models.PositiveSmallIntegerField(null=True, blank=True)
description = models.TextField(null=True, blank=True)
hobby = models.CharField(max_length=120, null=True, blank=True)
profile_pic = models.TextField(null=True, blank=True) # base64 or URL
tags = models.CharField(max_length=255, null=True, blank=True) # comma-separated
phone = models.CharField(max_length=20, null=True, blank=True)

def __str__(self):
return self.username
Expand Down
68 changes: 65 additions & 3 deletions backend/users/serializers.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,85 @@
from rest_framework import serializers
from .models import CustomUser, UserConnection


class UserSerializer(serializers.ModelSerializer):
first_name = serializers.CharField(required=False, allow_blank=True)
last_name = serializers.CharField(required=False, allow_blank=True)
# Add new fields
profile_pic = serializers.CharField(required=False, allow_blank=True)
tags = serializers.CharField(required=False, allow_blank=True)
phone = serializers.CharField(required=False, allow_blank=True)

class Meta:
model = CustomUser
exclude = ("password", "is_staff", "is_superuser", "groups", "user_permissions")
fields = (
"id",
"username",
"email",
"first_name",
"last_name",
"job",
"mental_health",
"wellness",
"engage",
"location",
"gender",
"age",
"description",
"hobby",
"profile_pic",
"tags",
"phone",
)
# Add more fields if you extend the model


class ConnectionSerializer(serializers.ModelSerializer):
class Meta:
model = UserConnection
fields = ("id", "connected_user", "created_at")
read_only_fields = ("id", "created_at")


class RegisterSerializer(serializers.ModelSerializer):
password = serializers.CharField(write_only=True, min_length=6)
first_name = serializers.CharField(required=False, allow_blank=True)
last_name = serializers.CharField(required=False, allow_blank=True)
job = serializers.CharField(required=False, allow_blank=True)
mental_health = serializers.IntegerField(required=False, allow_null=True)
wellness = serializers.IntegerField(required=False, allow_null=True)
engage = serializers.IntegerField(required=False, allow_null=True)
location = serializers.CharField(required=False, allow_blank=True)
gender = serializers.CharField(required=False, allow_blank=True)
age = serializers.IntegerField(required=False, allow_null=True)
description = serializers.CharField(required=False, allow_blank=True)
hobby = serializers.CharField(required=False, allow_blank=True)
profile_pic = serializers.CharField(required=False, allow_blank=True)
tags = serializers.CharField(required=False, allow_blank=True)
phone = serializers.CharField(required=False, allow_blank=True)

class Meta:
model = CustomUser
fields = ("id", "username", "email", "password")
fields = (
"id",
"username",
"email",
"password",
"first_name",
"last_name",
"job",
"mental_health",
"wellness",
"engage",
"location",
"gender",
"age",
"description",
"hobby",
"profile_pic",
"tags",
"phone",
)

def create(self, validated_data):
return CustomUser.objects.create_user(**validated_data)
return CustomUser.objects.create_user(**validated_data)
Loading