from django.contrib import admin
from django.utils.html import format_html
from unfold.admin import ModelAdmin
from unfold.decorators import display
from .models import Review, ReviewHelpfulVote
@admin.register(Review)
class ReviewAdmin(ModelAdmin):
list_display = [
'id',
'user_link',
'entity_type',
'entity_link',
'rating_display',
'title',
'moderation_status_badge',
'helpful_score',
'created',
]
list_filter = [
'moderation_status',
'rating',
'created',
'content_type',
]
search_fields = [
'title',
'content',
'user__username',
'user__email',
]
readonly_fields = [
'user',
'content_type',
'object_id',
'content_object',
'helpful_votes',
'total_votes',
'helpful_percentage',
'created',
'modified',
]
fieldsets = (
('Review Information', {
'fields': (
'user',
'content_type',
'object_id',
'content_object',
'title',
'content',
'rating',
)
}),
('Visit Details', {
'fields': (
'visit_date',
'wait_time_minutes',
)
}),
('Voting Statistics', {
'fields': (
'helpful_votes',
'total_votes',
'helpful_percentage',
)
}),
('Moderation', {
'fields': (
'moderation_status',
'moderation_notes',
'moderated_by',
'moderated_at',
)
}),
('Timestamps', {
'fields': (
'created',
'modified',
)
}),
)
list_per_page = 50
@display(description='User', ordering='user__username')
def user_link(self, obj):
from django.urls import reverse
url = reverse('admin:users_user_change', args=[obj.user.pk])
return format_html('{}', url, obj.user.username)
@display(description='Entity Type', ordering='content_type')
def entity_type(self, obj):
return obj.content_type.model.title()
@display(description='Entity')
def entity_link(self, obj):
if obj.content_object:
from django.urls import reverse
model_name = obj.content_type.model
url = reverse(f'admin:entities_{model_name}_change', args=[obj.object_id])
return format_html('{}', url, str(obj.content_object))
return f"ID: {obj.object_id}"
@display(description='Rating', ordering='rating')
def rating_display(self, obj):
stars = '⭐' * obj.rating
return format_html('{}', obj.rating, stars)
@display(description='Status', ordering='moderation_status')
def moderation_status_badge(self, obj):
colors = {
'pending': '#FFA500',
'approved': '#28A745',
'rejected': '#DC3545',
}
color = colors.get(obj.moderation_status, '#6C757D')
return format_html(
'{}',
color,
obj.get_moderation_status_display()
)
@display(description='Helpful Score')
def helpful_score(self, obj):
if obj.total_votes == 0:
return "No votes yet"
percentage = obj.helpful_percentage
return f"{obj.helpful_votes}/{obj.total_votes} ({percentage:.0f}%)"
def has_add_permission(self, request):
# Reviews should only be created by users via API
return False
def has_delete_permission(self, request, obj=None):
# Only superusers can delete reviews
return request.user.is_superuser
actions = ['approve_reviews', 'reject_reviews']
@admin.action(description='Approve selected reviews')
def approve_reviews(self, request, queryset):
count = 0
for review in queryset.filter(moderation_status='pending'):
review.approve(request.user, 'Bulk approved from admin')
count += 1
self.message_user(request, f'{count} reviews approved.')
@admin.action(description='Reject selected reviews')
def reject_reviews(self, request, queryset):
count = 0
for review in queryset.filter(moderation_status='pending'):
review.reject(request.user, 'Bulk rejected from admin')
count += 1
self.message_user(request, f'{count} reviews rejected.')
@admin.register(ReviewHelpfulVote)
class ReviewHelpfulVoteAdmin(ModelAdmin):
list_display = [
'id',
'review_link',
'user_link',
'vote_type',
'created',
]
list_filter = [
'is_helpful',
'created',
]
search_fields = [
'review__title',
'user__username',
'user__email',
]
readonly_fields = [
'review',
'user',
'is_helpful',
'created',
'modified',
]
list_per_page = 50
@display(description='Review', ordering='review__title')
def review_link(self, obj):
from django.urls import reverse
url = reverse('admin:reviews_review_change', args=[obj.review.pk])
return format_html('{}', url, obj.review.title)
@display(description='User', ordering='user__username')
def user_link(self, obj):
from django.urls import reverse
url = reverse('admin:users_user_change', args=[obj.user.pk])
return format_html('{}', url, obj.user.username)
@display(description='Vote', ordering='is_helpful')
def vote_type(self, obj):
if obj.is_helpful:
return format_html('👍 Helpful')
else:
return format_html('👎 Not Helpful')
def has_add_permission(self, request):
# Votes should only be created by users via API
return False
def has_change_permission(self, request, obj=None):
# Votes should not be changed after creation
return False
def has_delete_permission(self, request, obj=None):
# Only superusers can delete votes
return request.user.is_superuser