Files

149 lines
5.2 KiB
Python

import uuid
from django.contrib.auth.models import AbstractUser, BaseUserManager
from django.core.validators import RegexValidator
from django.db import models, IntegrityError
from django.conf import settings
from django.db.models.signals import post_save
from django.dispatch import receiver
class CustomUserManager(BaseUserManager):
def create_user(self, email=None, phone=None, password=None, **extra_fields):
if not email and not phone:
raise ValueError("User must have an email or a phone number.")
if email:
email = self.normalize_email(email)
try:
user = self.model(email=email, phone=phone, **extra_fields)
if not password:
raise ValueError("Password must be provided.")
user.set_password(password)
user.save(using=self._db)
return user
except IntegrityError as e:
# Handle unique constraints more clearly
if "unique" in str(e).lower():
if email and self.model.objects.filter(email=email).exists():
raise ValueError("A user with this email already exists.")
if phone and self.model.objects.filter(phone=phone).exists():
raise ValueError("A user with this phone number already exists.")
raise
def create_superuser(self, email=None, phone=None, password=None, **extra_fields):
extra_fields.setdefault("is_staff", True)
extra_fields.setdefault("is_superuser", True)
extra_fields.setdefault("is_admin", True)
extra_fields.setdefault("is_active", True)
if not password:
raise ValueError("Superuser must have a password.")
if not email:
raise ValueError("Superuser must have an email address.")
return self.create_user(
email=email, phone=phone, password=password, **extra_fields
)
class User(AbstractUser):
username = None
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
email = models.EmailField(unique=True)
phone = models.CharField(
max_length=10,
unique=True,
null=True,
blank=True,
validators=[
RegexValidator(
regex=r"^\d{10}$",
message="Phone number must be 10 digits.",
)
],
)
is_active = models.BooleanField(default=False)
is_alumni = models.BooleanField(default=True)
is_staff_member = models.BooleanField(default=False)
is_admin = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
last_active = models.DateTimeField(null=True, blank=True)
USERNAME_FIELD = "email"
REQUIRED_FIELDS = ["first_name", "last_name", "phone"]
objects = CustomUserManager()
def __str__(self):
return f"{self.first_name} {self.last_name} ({self.email})"
class Meta:
indexes = [
models.Index(fields=["email"], name="user_email_idx"),
models.Index(fields=["phone"], name="user_phone_idx"),
models.Index(fields=["first_name", "last_name"], name="user_name_idx"),
]
class UserProfile(models.Model):
user = models.OneToOneField(
settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="profile"
)
avatar = models.ImageField(upload_to="avatars/", null=True, blank=True)
bio = models.TextField(max_length=500, blank=True)
location = models.CharField(max_length=100, blank=True)
graduation_year = models.PositiveIntegerField(null=True, blank=True)
degree = models.CharField(max_length=100, blank=True)
major = models.CharField(max_length=100, blank=True)
current_company = models.CharField(max_length=100, blank=True)
current_position = models.CharField(max_length=100, blank=True)
linkedin_url = models.URLField(blank=True)
website_url = models.URLField(blank=True)
privacy_level = models.CharField(
max_length=20,
choices=[
("public", "Public"),
("alumni_only", "Alumni Only"),
("private", "Private"),
],
default="alumni_only",
)
notification_preferences = models.JSONField(default=dict)
is_mentor_available = models.BooleanField(default=False)
mentor_skills = models.JSONField(default=list)
is_job_seeking = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return f"{self.user.get_full_name()} - Profile"
class Meta:
indexes = [
models.Index(fields=["graduation_year"], name="profile_grad_year_idx"),
models.Index(fields=["current_company"], name="profile_company_idx"),
models.Index(fields=["is_mentor_available"], name="profile_mentor_idx"),
models.Index(fields=["is_job_seeking"], name="profile_jobseek_idx"),
]
verbose_name = "User Profile"
verbose_name_plural = "User Profiles"
@receiver(post_save, sender=settings.AUTH_USER_MODEL)
def create_user_profile(sender, instance, created, **kwargs):
if created:
UserProfile.objects.create(user=instance)