from django.db import models from django.contrib.auth.models import AbstractUser from django.utils import timezone import secrets import string from django.contrib.contenttypes.fields import GenericForeignKey from django.contrib.contenttypes.models import ContentType from django.conf import settings # Create your models here. # Ta klasa reprezentuje użytkownika w systemie. Dziedziczy po AbstractUser, co pozwala na rozszerzenie domyślnej funkcjonalności użytkownika Django. class User(AbstractUser): ROLES = ( ('admin', 'Admin'), ('moderator', 'Moderator'), ('user', 'User'), ) role = models.CharField(max_length=10, choices=ROLES, default='user') avatar_image = models.ImageField(upload_to='avatars/', null=True, blank=True) username = models.CharField(max_length=150, unique=True) bio = models.TextField(blank=True, default='') token_version = models.IntegerField(default=0) # Add related_name to resolve clashes groups = models.ManyToManyField( 'auth.Group', related_name='custom_user_set', blank=True, help_text='The groups this user belongs to.', verbose_name='groups', ) user_permissions = models.ManyToManyField( 'auth.Permission', related_name='custom_user_set', blank=True, help_text='Specific permissions for this user.', verbose_name='user permissions', ) def __str__(self): return self.username # Ta klasa obsługuje tokeny resetowania hasła, które są używane do weryfikacji użytkowników podczas procesu resetowania hasła. class PasswordResetToken(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE) token = models.CharField(max_length=100, unique=True) created_at = models.DateTimeField(auto_now_add=True) expires_at = models.DateTimeField() used = models.BooleanField(default=False) def save(self, *args, **kwargs): if not self.token: # Generate a random token alphabet = string.ascii_letters + string.digits self.token = ''.join(secrets.choice(alphabet) for _ in range(64)) super().save(*args, **kwargs) #Ta funkcja sprawdza, czy token jest ważny. Token jest ważny, jeśli nie został użyty i nie wygasł. def is_valid(self): return ( not self.used and self.expires_at > timezone.now() ) class Meta: verbose_name = 'Password Reset Token' verbose_name_plural = 'Password Reset Tokens' class EmailChangeToken(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE) new_email = models.EmailField() token = models.CharField(max_length=100, unique=True) created_at = models.DateTimeField(auto_now_add=True) expires_at = models.DateTimeField() used = models.BooleanField(default=False) def save(self, *args, **kwargs): if not self.token: import secrets, string alphabet = string.ascii_letters + string.digits self.token = ''.join(secrets.choice(alphabet) for _ in range(64)) super().save(*args, **kwargs) def is_valid(self): from django.utils import timezone return (not self.used) and (self.expires_at > timezone.now()) class Favorite(models.Model): user = models.ForeignKey( settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='favorites' ) content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE) object_id = models.PositiveIntegerField() content_object = GenericForeignKey('content_type', 'object_id') created_at = models.DateTimeField(auto_now_add=True) class Meta: constraints = [ models.UniqueConstraint( fields=['user', 'content_type', 'object_id'], name='uniq_favorite_per_user_object' ) ] indexes = [ models.Index(fields=['user', 'content_type']), models.Index(fields=['content_type', 'object_id']), ] def __str__(self): return f'{self.user} ♥ {self.content_type.app_label}.{self.content_type.model}:{self.object_id}'