Business Directory Models
Business Directory Models (English fallback)
Aug. 16, 2025
Posted by admin
|
from django.db import models from django.contrib.auth.models import User from django.urls import reverse from django.core.validators import MaxValueValidator, MinValueValidator
|
Listing |
class BusinessListing(models.Model): """Business listing model""" SUBSCRIPTION_CHOICES = [ ('free', 'Free Listing'), ('basic', 'Basic Listing'), ('premium', 'Premium Listing'), ('featured', 'Featured Listing'), ]
STATUS_CHOICES = [ ('draft', 'Draft'), ('pending', 'Pending Approval'), ('approved', 'Approved'), ('rejected', 'Rejected'), ('suspended', 'Suspended'), ]
TRANSLATION_STATUS_CHOICES = [ ('pending', 'Pending Translation'), ('translated', 'Translated'), ('reviewed', 'Reviewed'), ]
# Basic Information business_name = models.CharField(max_length=200) business_name_vi = models.CharField(max_length=200, blank=True, verbose_name="Vietnamese Business Name") slug = models.SlugField(max_length=200, unique=True) category = models.ForeignKey(BusinessCategory, on_delete=models.CASCADE, related_name='businesses') owner = models.ForeignKey(User, on_delete=models.CASCADE, related_name='businesses')
# Description description = models.TextField() description_vi = models.TextField(blank=True, verbose_name="Vietnamese Description") short_description = models.CharField(max_length=300, help_text="Brief description for listings") short_description_vi = models.CharField(max_length=300, blank=True, verbose_name="Vietnamese Short Description")
# Contact Information phone = models.CharField(max_length=20) email = models.EmailField() website = models.URLField(blank=True)
# Address street_address = models.CharField(max_length=200) city = models.CharField(max_length=100) state = models.CharField(max_length=100) postal_code = models.CharField(max_length=20) country = models.CharField(max_length=100, default='Vietnam') latitude = models.DecimalField(max_digits=10, decimal_places=8, null=True, blank=True) longitude = models.DecimalField(max_digits=11, decimal_places=8, null=True, blank=True)
# Business Hours monday_hours = models.CharField(max_length=50, blank=True, help_text="e.g., 9:00 AM - 5:00 PM") tuesday_hours = models.CharField(max_length=50, blank=True) wednesday_hours = models.CharField(max_length=50, blank=True) thursday_hours = models.CharField(max_length=50, blank=True) friday_hours = models.CharField(max_length=50, blank=True) saturday_hours = models.CharField(max_length=50, blank=True) sunday_hours = models.CharField(max_length=50, blank=True)
# Social Media facebook_url = models.URLField(blank=True) twitter_url = models.URLField(blank=True) instagram_url = models.URLField(blank=True) linkedin_url = models.URLField(blank=True)
# Features/Amenities accepts_credit_cards = models.BooleanField(default=False) parking_available = models.BooleanField(default=False) wheelchair_accessible = models.BooleanField(default=False) wifi_available = models.BooleanField(default=False) outdoor_seating = models.BooleanField(default=False) delivery_available = models.BooleanField(default=False)
# Subscription & Status subscription_type = models.CharField(max_length=20, choices=SUBSCRIPTION_CHOICES, default='free') status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='draft') is_verified = models.BooleanField(default=False) is_featured = models.BooleanField(default=False)
# SEO Fields meta_title = models.CharField(max_length=60, blank=True) meta_description = models.CharField(max_length=160, blank=True) keywords = models.CharField(max_length=200, blank=True, help_text="Comma-separated keywords")
# Analytics views_count = models.PositiveIntegerField(default=0) phone_clicks = models.PositiveIntegerField(default=0) website_clicks = models.PositiveIntegerField(default=0)
# Timestamps created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) featured_until = models.DateTimeField(null=True, blank=True) subscription_expires = models.DateTimeField(null=True, blank=True)
# Vietnamese translation fields translation_status = models.CharField( max_length=20, choices=TRANSLATION_STATUS_CHOICES, default='pending', help_text="Status of Vietnamese translation" ) translated_by = models.CharField(max_length=100, blank=True, help_text="Name of translator") translated_at = models.DateTimeField(null=True, blank=True, help_text="When translation was completed")
class Meta: ordering = ['-is_featured', '-created_at']
def __str__(self): return self.business_name
def get_display_name(self, language='en'): """Get business name in specified language""" if language == 'vi' and self.business_name_vi: return self.business_name_vi return self.business_name
def get_display_description(self, language='en'): """Get business description in specified language""" if language == 'vi' and self.description_vi: return self.description_vi return self.description
def get_display_short_description(self, language='en'): """Get business short description in specified language""" if language == 'vi' and self.short_description_vi: return self.short_description_vi return self.short_description
def is_translated(self): """Check if business has Vietnamese translation""" return bool(self.business_name_vi and self.description_vi and self.short_description_vi)
def get_absolute_url(self): return reverse('business_directory:detail', kwargs={'slug': self.slug})
def get_full_address(self): """Get formatted full address""" parts = [self.street_address, self.city, self.state, self.postal_code, self.country] return ', '.join(filter(None, parts))
|
Listing Category |
class BusinessCategory(models.Model): """Categories for business listings""" TRANSLATION_STATUS_CHOICES = [ ('pending', 'Pending Translation'), ('translated', 'Translated'), ('reviewed', 'Reviewed'), ]
name = models.CharField(max_length=100, unique=True) name_vi = models.CharField(max_length=100, blank=True, verbose_name="Vietnamese Name") slug = models.SlugField(max_length=100, unique=True) description = models.TextField(blank=True) description_vi = models.TextField(blank=True, verbose_name="Vietnamese Description") icon = models.CharField(max_length=50, default='fas fa-building') parent = models.ForeignKey('self', on_delete=models.CASCADE, null=True, blank=True, related_name='subcategories') is_active = models.BooleanField(default=True) sort_order = models.PositiveIntegerField(default=0) created_at = models.DateTimeField(auto_now_add=True)
# Vietnamese translation fields translation_status = models.CharField( max_length=20, choices=TRANSLATION_STATUS_CHOICES, default='pending', help_text="Status of Vietnamese translation" ) translated_by = models.CharField(max_length=100, blank=True, help_text="Name of translator") translated_at = models.DateTimeField(null=True, blank=True, help_text="When translation was completed")
class Meta: verbose_name_plural = "Business Categories" ordering = ['sort_order', 'name']
def __str__(self): return self.name
def get_display_name(self, language='en'): """Get category name in specified language""" if language == 'vi' and self.name_vi: return self.name_vi return self.name
def get_display_description(self, language='en'): """Get category description in specified language""" if language == 'vi' and self.description_vi: return self.description_vi return self.description
def is_translated(self): """Check if category has Vietnamese translation""" return bool(self.name_vi and self.description_vi)
def get_absolute_url(self): return reverse('business_directory:category', kwargs={'slug': self.slug})
def get_business_count(self): """Get count of approved businesses in this category""" return self.businesses.filter(status='approved').count()
|
Listing Image |
class BusinessImage(models.Model): """Images for business listings""" business = models.ForeignKey(BusinessListing, on_delete=models.CASCADE, related_name='images') image = models.ImageField(upload_to='business_images/') caption = models.CharField(max_length=200, blank=True) is_primary = models.BooleanField(default=False) sort_order = models.PositiveIntegerField(default=0) uploaded_at = models.DateTimeField(auto_now_add=True)
class Meta: ordering = ['sort_order', 'uploaded_at']
def __str__(self): return f"Image for {self.business.business_name}"
|
Listing Review |
class BusinessReview(models.Model): """Reviews for business listings""" business = models.ForeignKey(BusinessListing, on_delete=models.CASCADE, related_name='reviews') reviewer = models.ForeignKey(User, on_delete=models.CASCADE, related_name='business_reviews') rating = models.PositiveIntegerField( validators=[MinValueValidator(1), MaxValueValidator(5)], help_text="Rating from 1 to 5 stars" ) title = models.CharField(max_length=200) review_text = models.TextField() is_verified = models.BooleanField(default=False) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True)
class Meta: unique_together = ['business', 'reviewer'] ordering = ['-created_at']
def __str__(self): return f"{self.title} - {self.rating} stars"
|
Liting Claim |
class BusinessClaim(models.Model): """Business claim requests""" business = models.ForeignKey(BusinessListing, on_delete=models.CASCADE, related_name='claims') claimant = models.ForeignKey(User, on_delete=models.CASCADE, related_name='business_claims') claim_reason = models.TextField(help_text="Reason for claiming this business") verification_document = models.FileField(upload_to='claim_documents/', blank=True) status = models.CharField(max_length=20, choices=[ ('pending', 'Pending Review'), ('approved', 'Approved'), ('rejected', 'Rejected'), ], default='pending') created_at = models.DateTimeField(auto_now_add=True) reviewed_at = models.DateTimeField(null=True, blank=True)
class Meta: ordering = ['-created_at']
def __str__(self): return f"Claim for {self.business.business_name} by {self.claimant.username}"
|
|
from django.db import models from django.contrib.auth.models import User from django.urls import reverse from django.core.validators import MaxValueValidator, MinValueValidator
|
Listing |
class BusinessListing(models.Model): """Business listing model""" SUBSCRIPTION_CHOICES = [ ('free', 'Free Listing'), ('basic', 'Basic Listing'), ('premium', 'Premium Listing'), ('featured', 'Featured Listing'), ]
STATUS_CHOICES = [ ('draft', 'Draft'), ('pending', 'Pending Approval'), ('approved', 'Approved'), ('rejected', 'Rejected'), ('suspended', 'Suspended'), ]
TRANSLATION_STATUS_CHOICES = [ ('pending', 'Pending Translation'), ('translated', 'Translated'), ('reviewed', 'Reviewed'), ]
# Basic Information business_name = models.CharField(max_length=200) business_name_vi = models.CharField(max_length=200, blank=True, verbose_name="Vietnamese Business Name") slug = models.SlugField(max_length=200, unique=True) category = models.ForeignKey(BusinessCategory, on_delete=models.CASCADE, related_name='businesses') owner = models.ForeignKey(User, on_delete=models.CASCADE, related_name='businesses')
# Description description = models.TextField() description_vi = models.TextField(blank=True, verbose_name="Vietnamese Description") short_description = models.CharField(max_length=300, help_text="Brief description for listings") short_description_vi = models.CharField(max_length=300, blank=True, verbose_name="Vietnamese Short Description")
# Contact Information phone = models.CharField(max_length=20) email = models.EmailField() website = models.URLField(blank=True)
# Address street_address = models.CharField(max_length=200) city = models.CharField(max_length=100) state = models.CharField(max_length=100) postal_code = models.CharField(max_length=20) country = models.CharField(max_length=100, default='Vietnam') latitude = models.DecimalField(max_digits=10, decimal_places=8, null=True, blank=True) longitude = models.DecimalField(max_digits=11, decimal_places=8, null=True, blank=True)
# Business Hours monday_hours = models.CharField(max_length=50, blank=True, help_text="e.g., 9:00 AM - 5:00 PM") tuesday_hours = models.CharField(max_length=50, blank=True) wednesday_hours = models.CharField(max_length=50, blank=True) thursday_hours = models.CharField(max_length=50, blank=True) friday_hours = models.CharField(max_length=50, blank=True) saturday_hours = models.CharField(max_length=50, blank=True) sunday_hours = models.CharField(max_length=50, blank=True)
# Social Media facebook_url = models.URLField(blank=True) twitter_url = models.URLField(blank=True) instagram_url = models.URLField(blank=True) linkedin_url = models.URLField(blank=True)
# Features/Amenities accepts_credit_cards = models.BooleanField(default=False) parking_available = models.BooleanField(default=False) wheelchair_accessible = models.BooleanField(default=False) wifi_available = models.BooleanField(default=False) outdoor_seating = models.BooleanField(default=False) delivery_available = models.BooleanField(default=False)
# Subscription & Status subscription_type = models.CharField(max_length=20, choices=SUBSCRIPTION_CHOICES, default='free') status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='draft') is_verified = models.BooleanField(default=False) is_featured = models.BooleanField(default=False)
# SEO Fields meta_title = models.CharField(max_length=60, blank=True) meta_description = models.CharField(max_length=160, blank=True) keywords = models.CharField(max_length=200, blank=True, help_text="Comma-separated keywords")
# Analytics views_count = models.PositiveIntegerField(default=0) phone_clicks = models.PositiveIntegerField(default=0) website_clicks = models.PositiveIntegerField(default=0)
# Timestamps created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) featured_until = models.DateTimeField(null=True, blank=True) subscription_expires = models.DateTimeField(null=True, blank=True)
# Vietnamese translation fields translation_status = models.CharField( max_length=20, choices=TRANSLATION_STATUS_CHOICES, default='pending', help_text="Status of Vietnamese translation" ) translated_by = models.CharField(max_length=100, blank=True, help_text="Name of translator") translated_at = models.DateTimeField(null=True, blank=True, help_text="When translation was completed")
class Meta: ordering = ['-is_featured', '-created_at']
def __str__(self): return self.business_name
def get_display_name(self, language='en'): """Get business name in specified language""" if language == 'vi' and self.business_name_vi: return self.business_name_vi return self.business_name
def get_display_description(self, language='en'): """Get business description in specified language""" if language == 'vi' and self.description_vi: return self.description_vi return self.description
def get_display_short_description(self, language='en'): """Get business short description in specified language""" if language == 'vi' and self.short_description_vi: return self.short_description_vi return self.short_description
def is_translated(self): """Check if business has Vietnamese translation""" return bool(self.business_name_vi and self.description_vi and self.short_description_vi)
def get_absolute_url(self): return reverse('business_directory:detail', kwargs={'slug': self.slug})
def get_full_address(self): """Get formatted full address""" parts = [self.street_address, self.city, self.state, self.postal_code, self.country] return ', '.join(filter(None, parts))
|
Listing Category |
class BusinessCategory(models.Model): """Categories for business listings""" TRANSLATION_STATUS_CHOICES = [ ('pending', 'Pending Translation'), ('translated', 'Translated'), ('reviewed', 'Reviewed'), ]
name = models.CharField(max_length=100, unique=True) name_vi = models.CharField(max_length=100, blank=True, verbose_name="Vietnamese Name") slug = models.SlugField(max_length=100, unique=True) description = models.TextField(blank=True) description_vi = models.TextField(blank=True, verbose_name="Vietnamese Description") icon = models.CharField(max_length=50, default='fas fa-building') parent = models.ForeignKey('self', on_delete=models.CASCADE, null=True, blank=True, related_name='subcategories') is_active = models.BooleanField(default=True) sort_order = models.PositiveIntegerField(default=0) created_at = models.DateTimeField(auto_now_add=True)
# Vietnamese translation fields translation_status = models.CharField( max_length=20, choices=TRANSLATION_STATUS_CHOICES, default='pending', help_text="Status of Vietnamese translation" ) translated_by = models.CharField(max_length=100, blank=True, help_text="Name of translator") translated_at = models.DateTimeField(null=True, blank=True, help_text="When translation was completed")
class Meta: verbose_name_plural = "Business Categories" ordering = ['sort_order', 'name']
def __str__(self): return self.name
def get_display_name(self, language='en'): """Get category name in specified language""" if language == 'vi' and self.name_vi: return self.name_vi return self.name
def get_display_description(self, language='en'): """Get category description in specified language""" if language == 'vi' and self.description_vi: return self.description_vi return self.description
def is_translated(self): """Check if category has Vietnamese translation""" return bool(self.name_vi and self.description_vi)
def get_absolute_url(self): return reverse('business_directory:category', kwargs={'slug': self.slug})
def get_business_count(self): """Get count of approved businesses in this category""" return self.businesses.filter(status='approved').count()
|
Listing Image |
class BusinessImage(models.Model): """Images for business listings""" business = models.ForeignKey(BusinessListing, on_delete=models.CASCADE, related_name='images') image = models.ImageField(upload_to='business_images/') caption = models.CharField(max_length=200, blank=True) is_primary = models.BooleanField(default=False) sort_order = models.PositiveIntegerField(default=0) uploaded_at = models.DateTimeField(auto_now_add=True)
class Meta: ordering = ['sort_order', 'uploaded_at']
def __str__(self): return f"Image for {self.business.business_name}"
|
Listing Review |
class BusinessReview(models.Model): """Reviews for business listings""" business = models.ForeignKey(BusinessListing, on_delete=models.CASCADE, related_name='reviews') reviewer = models.ForeignKey(User, on_delete=models.CASCADE, related_name='business_reviews') rating = models.PositiveIntegerField( validators=[MinValueValidator(1), MaxValueValidator(5)], help_text="Rating from 1 to 5 stars" ) title = models.CharField(max_length=200) review_text = models.TextField() is_verified = models.BooleanField(default=False) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True)
class Meta: unique_together = ['business', 'reviewer'] ordering = ['-created_at']
def __str__(self): return f"{self.title} - {self.rating} stars"
|
Liting Claim |
class BusinessClaim(models.Model): """Business claim requests""" business = models.ForeignKey(BusinessListing, on_delete=models.CASCADE, related_name='claims') claimant = models.ForeignKey(User, on_delete=models.CASCADE, related_name='business_claims') claim_reason = models.TextField(help_text="Reason for claiming this business") verification_document = models.FileField(upload_to='claim_documents/', blank=True) status = models.CharField(max_length=20, choices=[ ('pending', 'Pending Review'), ('approved', 'Approved'), ('rejected', 'Rejected'), ], default='pending') created_at = models.DateTimeField(auto_now_add=True) reviewed_at = models.DateTimeField(null=True, blank=True)
class Meta: ordering = ['-created_at']
def __str__(self): return f"Claim for {self.business.business_name} by {self.claimant.username}"
|
Attached Files
You are viewing this article in public mode. Some features may be limited.