Spaces:
Build error
Build error
| 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]}" | |
| 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)" | |