Spaces:
Build error
Build error
File size: 2,730 Bytes
877587b |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
from django.contrib.auth.models import AbstractUser
from django.core.validators import MinValueValidator, MaxValueValidator
from django.db import models
from django.db.models import Avg
class User(AbstractUser):
"""
Custom user model with phone-based authentication.
Phone number is unique and serves as the primary identifier.
"""
phone = models.CharField(max_length=15, unique=True, db_index=True)
name = models.CharField(max_length=255)
# Username is not used but required by AbstractUser
# We'll make it optional by setting blank=True
username = models.CharField(max_length=150, blank=True, null=True)
USERNAME_FIELD = 'phone'
REQUIRED_FIELDS = ['name']
class Meta:
db_table = 'users'
verbose_name = 'User'
verbose_name_plural = 'Users'
def __str__(self):
return f"{self.name} ({self.phone})"
class Place(models.Model):
"""
Represents a place that can be reviewed.
Unique constraint on (name, address) ensures no duplicates.
"""
name = models.CharField(max_length=255, db_index=True)
address = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
db_table = 'places'
unique_together = [['name', 'address']]
verbose_name = 'Place'
verbose_name_plural = 'Places'
indexes = [
models.Index(fields=['name']),
]
def __str__(self):
return f"{self.name} - {self.address[:50]}"
@property
def average_rating(self):
"""Calculate average rating from all reviews."""
avg = self.reviews.aggregate(avg_rating=Avg('rating'))['avg_rating']
return round(avg, 2) if avg is not None else None
class Review(models.Model):
"""
Review left by a user for a place.
Rating must be between 1-5.
One review per user per place.
"""
user = models.ForeignKey(
User,
on_delete=models.CASCADE,
related_name='reviews'
)
place = models.ForeignKey(
Place,
on_delete=models.CASCADE,
related_name='reviews'
)
rating = models.IntegerField(
validators=[MinValueValidator(1), MaxValueValidator(5)]
)
text = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
db_table = 'reviews'
unique_together = [['user', 'place']]
verbose_name = 'Review'
verbose_name_plural = 'Reviews'
ordering = ['-created_at']
indexes = [
models.Index(fields=['-created_at']),
]
def __str__(self):
return f"{self.user.name} - {self.place.name} ({self.rating}/5)"
|