filtering events
This commit is contained in:
@@ -8,6 +8,7 @@ from accounts.models import (
|
||||
IAmPrincipalType,
|
||||
# IAmPrincipalKYCDetails,
|
||||
)
|
||||
from manage_events.models import PrincipalPreference
|
||||
from manage_referrals.models import (
|
||||
ReferralCode,
|
||||
ReferralRecord,
|
||||
@@ -140,6 +141,7 @@ class ProfileSerializer(serializers.ModelSerializer):
|
||||
invite_count = serializers.SerializerMethodField(read_only=True)
|
||||
principal_type_name = serializers.SerializerMethodField(read_only=True)
|
||||
has_active_subscription = serializers.SerializerMethodField(read_only=True)
|
||||
has_preferences = serializers.SerializerMethodField(read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = IAmPrincipal
|
||||
@@ -153,6 +155,7 @@ class ProfileSerializer(serializers.ModelSerializer):
|
||||
"invite_count",
|
||||
"register_complete",
|
||||
"has_active_subscription",
|
||||
"has_preferences",
|
||||
]
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
@@ -171,6 +174,9 @@ class ProfileSerializer(serializers.ModelSerializer):
|
||||
def get_principal_type_name(self, obj):
|
||||
return obj.principal_type.name if obj.principal_type else None
|
||||
|
||||
def get_has_preferences(self, obj):
|
||||
return PrincipalPreference.objects.filter(principal=obj).exists()
|
||||
|
||||
def get_image_url(self, obj, field_name, request):
|
||||
image_field = getattr(obj, field_name)
|
||||
if image_field:
|
||||
|
||||
@@ -3,6 +3,7 @@ from django.conf import settings
|
||||
from django.core.files.uploadedfile import UploadedFile
|
||||
from django.core.mail import EmailMessage
|
||||
from django.utils.html import strip_tags
|
||||
import math
|
||||
from django.template.loader import render_to_string
|
||||
from django.shortcuts import get_object_or_404
|
||||
from smtplib import SMTPException
|
||||
@@ -16,7 +17,12 @@ from manage_referrals.models import (
|
||||
from manage_subscriptions.models import PrincipalSubscription, Subscription
|
||||
from manage_wallets.models import TransactionStatus, Wallet, Transaction
|
||||
from goodtimes.utils import CapacityError, RandomGenerator
|
||||
from manage_events.models import Event, EventPrincipalInteraction
|
||||
from manage_events.models import (
|
||||
Event,
|
||||
EventPrincipalInteraction,
|
||||
PrincipalPreference,
|
||||
Venue,
|
||||
)
|
||||
|
||||
# from twilio.rest import Client
|
||||
from django.db.models import Q, Count
|
||||
@@ -373,3 +379,82 @@ class InteractionCalculator:
|
||||
interaction["interested"] = "Blue Flames"
|
||||
|
||||
return interaction
|
||||
|
||||
|
||||
class EventFilterService:
|
||||
@staticmethod
|
||||
def filter_events(filter_type, principal=None):
|
||||
today = timezone.now().date()
|
||||
events = Event.objects.none()
|
||||
|
||||
current_and_future_events_query = Q(active=True, deleted=False) & (
|
||||
Q(start_date__lte=today, end_date__gte=today) | Q(start_date__gt=today)
|
||||
)
|
||||
|
||||
if filter_type == "expensive":
|
||||
events = Event.objects.filter(current_and_future_events_query).order_by(
|
||||
"-entry_fee"
|
||||
)
|
||||
elif filter_type == "cheap":
|
||||
events = Event.objects.filter(current_and_future_events_query).order_by(
|
||||
"entry_fee"
|
||||
)
|
||||
elif filter_type == "preference" and principal is not None:
|
||||
preferences = PrincipalPreference.objects.get(principal=principal)
|
||||
preferred_categories_ids = preferences.preferred_categories.values_list(
|
||||
"id", flat=True
|
||||
)
|
||||
events = Event.objects.filter(
|
||||
category__in=preferred_categories_ids, end_date__gte=today
|
||||
).distinct()
|
||||
|
||||
return events
|
||||
|
||||
@staticmethod
|
||||
def filter_events_by_category(category_id):
|
||||
today = timezone.now().date()
|
||||
|
||||
current_and_future_events_query = Q(active=True, deleted=False) & (
|
||||
Q(start_date__lte=today, end_date__gte=today) | Q(start_date__gt=today)
|
||||
)
|
||||
|
||||
# Ensure the category_id is valid and within the specified range (1-8)
|
||||
if 1 <= category_id <= 8:
|
||||
events = Event.objects.filter(
|
||||
current_and_future_events_query, category_id=category_id
|
||||
).distinct()
|
||||
else:
|
||||
events = (
|
||||
Event.objects.none()
|
||||
) # Return an empty queryset if the category_id is not valid
|
||||
|
||||
return events
|
||||
|
||||
@staticmethod
|
||||
def filter_events_for_tomorrow():
|
||||
today = timezone.now().date()
|
||||
tomorrow = today + timezone.timedelta(days=1)
|
||||
|
||||
# Events that are starting tomorrow, ending tomorrow, or have an end date greater than tomorrow
|
||||
events_query = (
|
||||
Q(start_date=tomorrow)
|
||||
| Q(end_date=tomorrow)
|
||||
| (Q(start_date__lte=tomorrow) & Q(end_date__gte=tomorrow))
|
||||
)
|
||||
events = Event.objects.filter(
|
||||
events_query, active=True, deleted=False
|
||||
).distinct()
|
||||
|
||||
return events
|
||||
|
||||
@staticmethod
|
||||
def filter_events_for_today():
|
||||
today = timezone.now().date()
|
||||
print("Today: ", today)
|
||||
|
||||
events = Event.objects.filter(
|
||||
Q(active=True) & ~Q(deleted=True),
|
||||
Q(start_date__lte=today) & Q(end_date__gte=today),
|
||||
)
|
||||
|
||||
return events
|
||||
|
||||
@@ -9,11 +9,7 @@ urlpatterns = [
|
||||
views.CreateEventApi.as_view(),
|
||||
name="add_event",
|
||||
),
|
||||
path(
|
||||
"get-events/<str:filter>/",
|
||||
views.EventsAPIView.as_view(),
|
||||
name="get_events",
|
||||
),
|
||||
path("get-events/", views.EventsAPIView.as_view(), name="events"),
|
||||
path(
|
||||
"event/<int:pk>/",
|
||||
views.EventDetailAPIView.as_view(),
|
||||
@@ -29,7 +25,11 @@ urlpatterns = [
|
||||
views.VenueListView.as_view(),
|
||||
name="get_venue",
|
||||
),
|
||||
path("event-master/search/", views.EventMasterSearchAPIView.as_view(), name="event_master_search"),
|
||||
path(
|
||||
"event-master/search/",
|
||||
views.EventMasterSearchAPIView.as_view(),
|
||||
name="event_master_search",
|
||||
),
|
||||
# Others
|
||||
path("geocode/", views.GeocodeAPIView.as_view(), name="geocode_api"),
|
||||
# All Preferences List
|
||||
@@ -56,4 +56,22 @@ urlpatterns = [
|
||||
views.IAmPrincipalLocationAPIView.as_view(),
|
||||
name="add_location",
|
||||
),
|
||||
# Favorites
|
||||
path(
|
||||
"toggle-favorite/<int:event_id>/",
|
||||
views.ToggleFavoriteView.as_view(),
|
||||
name="toggle-favorite",
|
||||
),
|
||||
# Going | Interested
|
||||
path(
|
||||
"event-status/<int:event_id>/",
|
||||
views.EventStatusUpdateAPIView.as_view(),
|
||||
name="event-status-update",
|
||||
),
|
||||
# Events filtered by 10 KM
|
||||
path(
|
||||
"events/filter-by-location/",
|
||||
views.EventFilterByLocationAPIView.as_view(),
|
||||
name="filter-events-by-location",
|
||||
),
|
||||
]
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
from datetime import timedelta
|
||||
from django.db import transaction
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.utils import timezone
|
||||
from rest_framework import status, generics
|
||||
from rest_framework.views import APIView
|
||||
@@ -24,14 +25,19 @@ from manage_events.api.serializers import (
|
||||
VenueSerializer,
|
||||
)
|
||||
from manage_events.models import (
|
||||
EventInteractionType,
|
||||
EventMaster,
|
||||
Event,
|
||||
EventCategory,
|
||||
EventPrincipalInteraction,
|
||||
Favorites,
|
||||
PrincipalPreference,
|
||||
Venue,
|
||||
)
|
||||
import requests
|
||||
|
||||
from manage_events.utils import filter_events_by_location
|
||||
|
||||
|
||||
class CreateEventApi(APIView):
|
||||
authentication_classes = [JWTAuthentication]
|
||||
@@ -56,7 +62,7 @@ class CreateVenueApi(APIView):
|
||||
permission_classes = [IsAuthenticated]
|
||||
|
||||
def post(self, request):
|
||||
serializer = VenueSerializer(data=request.data, context={'request': request})
|
||||
serializer = VenueSerializer(data=request.data, context={"request": request})
|
||||
serializer.is_valid(raise_exception=True)
|
||||
|
||||
serializer.save(created_by=self.request.user, active=True)
|
||||
@@ -73,9 +79,10 @@ class EventsAPIView(APIView):
|
||||
authentication_classes = [JWTAuthentication]
|
||||
permission_classes = [IsAuthenticated]
|
||||
|
||||
def get(self, request, filter, *args, **kwargs):
|
||||
today = timezone.now().date()
|
||||
params = ["expensive", "cheap", "preference", "today", "tomorrow"]
|
||||
def get(self, request, *args, **kwargs):
|
||||
filter = request.query_params.get("filter", None)
|
||||
category_id = request.query_params.get("category_id", None)
|
||||
params = ["expensive", "cheap", "preference", "today", "tomorrow", "category"]
|
||||
if filter not in params:
|
||||
return ApiResponse.error(
|
||||
status=status.HTTP_400_BAD_REQUEST,
|
||||
@@ -84,61 +91,26 @@ class EventsAPIView(APIView):
|
||||
)
|
||||
|
||||
try:
|
||||
|
||||
if filter == "expensive":
|
||||
|
||||
# Constructing a complex query using Q objects
|
||||
current_and_future_events_query = Q(active=True, deleted=False) & (
|
||||
Q(start_date__lte=today, end_date__gte=today)
|
||||
| Q(start_date__gt=today) # Current events # Future events
|
||||
if filter == "today":
|
||||
events = services.EventFilterService.filter_events_for_today()
|
||||
elif filter == "tomorrow":
|
||||
events = services.EventFilterService.filter_events_for_tomorrow()
|
||||
elif filter == "category" and category_id is not None:
|
||||
events = services.EventFilterService.filter_events_by_category(
|
||||
int(category_id)
|
||||
)
|
||||
|
||||
current_and_future_events = Event.objects.filter(
|
||||
current_and_future_events_query
|
||||
).order_by("-entry_fee")
|
||||
serializer = EventDetailSerializer(
|
||||
current_and_future_events, context={"request": request}, many=True
|
||||
else:
|
||||
events = services.EventFilterService.filter_events(
|
||||
filter, principal=request.user
|
||||
)
|
||||
return ApiResponse.success(
|
||||
status=status.HTTP_200_OK,
|
||||
message=constants.SUCCESS,
|
||||
data=serializer.data,
|
||||
)
|
||||
elif filter == "cheap":
|
||||
current_and_future_events_query = Q(active=True, deleted=False) & (
|
||||
Q(start_date__lte=today, end_date__gte=today)
|
||||
| Q(start_date__gt=today) # Current events # Future events
|
||||
)
|
||||
|
||||
current_and_future_events = Event.objects.filter(
|
||||
current_and_future_events_query
|
||||
).order_by("entry_fee")
|
||||
serializer = EventDetailSerializer(
|
||||
current_and_future_events, context={"request": request}, many=True
|
||||
)
|
||||
return ApiResponse.success(
|
||||
status=status.HTTP_200_OK,
|
||||
message=constants.SUCCESS,
|
||||
data=serializer.data,
|
||||
)
|
||||
elif filter == "preference":
|
||||
preferences = PrincipalPreference.objects.get(principal=request.user)
|
||||
preferred_categories_ids = preferences.preferred_categories.values_list(
|
||||
"id", flat=True
|
||||
)
|
||||
# Filter events based on user preferences and that are upcoming or ongoing
|
||||
preference_events = Event.objects.filter(
|
||||
category__in=preferred_categories_ids, end_date__gte=today
|
||||
).distinct()
|
||||
serializer = EventDetailSerializer(
|
||||
preference_events, context={"request": request}, many=True
|
||||
)
|
||||
return ApiResponse.success(
|
||||
status=status.HTTP_200_OK,
|
||||
message=constants.SUCCESS,
|
||||
data=serializer.data,
|
||||
)
|
||||
|
||||
serializer = EventDetailSerializer(
|
||||
events, context={"request": request}, many=True
|
||||
)
|
||||
return ApiResponse.success(
|
||||
status=status.HTTP_200_OK,
|
||||
message=constants.SUCCESS,
|
||||
data=serializer.data,
|
||||
)
|
||||
except Exception as e:
|
||||
return ApiResponse.error(
|
||||
status=status.HTTP_400_BAD_REQUEST,
|
||||
@@ -315,6 +287,7 @@ class IAmPrincipalLocationAPIView(APIView):
|
||||
user_location = IAmPrincipalLocation.objects.filter(
|
||||
principal=request.user
|
||||
).last()
|
||||
print("user_location: ", user_location)
|
||||
serializer = IAmPrincipalLocationSerializer(user_location)
|
||||
return ApiResponse.success(
|
||||
status=status.HTTP_200_OK,
|
||||
@@ -332,6 +305,7 @@ class IAmPrincipalLocationAPIView(APIView):
|
||||
serializer = IAmPrincipalLocationSerializer(
|
||||
data=request.data, context={"request": request}
|
||||
)
|
||||
print("serializer: ", serializer)
|
||||
if serializer.is_valid():
|
||||
serializer.save()
|
||||
return ApiResponse.success(
|
||||
@@ -381,6 +355,9 @@ class PrincipalPreferenceDetailView(generics.RetrieveAPIView):
|
||||
|
||||
|
||||
class EventMasterSearchAPIView(APIView):
|
||||
authentication_classes = [JWTAuthentication]
|
||||
permission_classes = [IsAuthenticated]
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
serializer = EventMasterSearchSerializer(data=request.data)
|
||||
if serializer.is_valid():
|
||||
@@ -406,3 +383,104 @@ class EventMasterSearchAPIView(APIView):
|
||||
errors=serializer.errors,
|
||||
status=status.HTTP_400_BAD_REQUEST,
|
||||
)
|
||||
|
||||
|
||||
class ToggleFavoriteView(APIView):
|
||||
authentication_classes = [JWTAuthentication]
|
||||
permission_classes = [IsAuthenticated]
|
||||
|
||||
def post(self, request, event_id, format=None):
|
||||
principal = request.user
|
||||
event = get_object_or_404(Event, pk=event_id)
|
||||
|
||||
favorite, created = Favorites.objects.get_or_create(
|
||||
principal=principal, event=event
|
||||
)
|
||||
if not created:
|
||||
favorite.delete()
|
||||
return ApiResponse.success(
|
||||
data="removed",
|
||||
message=constants.SUCCESS,
|
||||
status=status.HTTP_200_OK,
|
||||
)
|
||||
|
||||
return ApiResponse.success(
|
||||
data="added",
|
||||
message=constants.SUCCESS,
|
||||
status=status.HTTP_201_CREATED,
|
||||
)
|
||||
|
||||
|
||||
class EventStatusUpdateAPIView(APIView):
|
||||
authentication_classes = [JWTAuthentication]
|
||||
permission_classes = [IsAuthenticated]
|
||||
|
||||
def post(self, request, event_id):
|
||||
principal = (
|
||||
request.user
|
||||
) # Assuming you're using some form of user authentication
|
||||
event = get_object_or_404(Event, pk=event_id)
|
||||
|
||||
status_requested = request.data.get("status") # 'going' or 'interested'
|
||||
if status_requested not in EventInteractionType.values:
|
||||
return ApiResponse.error(
|
||||
message=constants.FAILURE,
|
||||
errors="Invalid status provided.",
|
||||
status=status.HTTP_400_BAD_REQUEST,
|
||||
)
|
||||
|
||||
interaction, created = EventPrincipalInteraction.objects.update_or_create(
|
||||
principal=principal,
|
||||
event=event,
|
||||
defaults={"status": status_requested},
|
||||
)
|
||||
|
||||
if created:
|
||||
return ApiResponse.success(
|
||||
data=status_requested,
|
||||
message=f"Marked as {status_requested}.",
|
||||
status=status.HTTP_201_CREATED,
|
||||
)
|
||||
else:
|
||||
return ApiResponse.success(
|
||||
data=status_requested,
|
||||
message=f"Updated status to {status_requested}.",
|
||||
status=status.HTTP_200_OK,
|
||||
)
|
||||
|
||||
|
||||
class EventFilterByLocationAPIView(APIView):
|
||||
authentication_classes = [JWTAuthentication]
|
||||
permission_classes = [IsAuthenticated]
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
principal = request.user
|
||||
|
||||
# Fetching user location from IAmPrincipalLocation
|
||||
try:
|
||||
user_location = IAmPrincipalLocation.objects.filter(principal=principal).last()
|
||||
user_lat = user_location.latitude
|
||||
user_lon = user_location.longitude
|
||||
except IAmPrincipalLocation.DoesNotExist:
|
||||
return ApiResponse.error(
|
||||
errors=constants.FAILURE,
|
||||
message="User location not set.",
|
||||
status=status.HTTP_400_BAD_REQUEST,
|
||||
)
|
||||
|
||||
# Now filter events based on user location
|
||||
events = filter_events_by_location(user_lat, user_lon)
|
||||
print("events: ", events)
|
||||
# Assuming you only want current and future events
|
||||
today = timezone.now().date()
|
||||
events = events.filter(Q(end_date__gte=today) | Q(start_date__gte=today))
|
||||
|
||||
# Serialize and return the filtered events
|
||||
serializer = EventDetailSerializer(
|
||||
events, context={"request": request}, many=True
|
||||
)
|
||||
return ApiResponse.success(
|
||||
data=serializer.data,
|
||||
message=constants.SUCCESS,
|
||||
status=status.HTTP_200_OK,
|
||||
)
|
||||
|
||||
49
manage_events/migrations/0002_favorites.py
Normal file
49
manage_events/migrations/0002_favorites.py
Normal file
@@ -0,0 +1,49 @@
|
||||
# Generated by Django 5.0.2 on 2024-03-06 16:07
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("manage_events", "0001_initial"),
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name="Favorites",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.BigAutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
(
|
||||
"event",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="favorites",
|
||||
to="manage_events.event",
|
||||
),
|
||||
),
|
||||
(
|
||||
"principal",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="favorited_by",
|
||||
to=settings.AUTH_USER_MODEL,
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
"unique_together": {("principal", "event")},
|
||||
},
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,19 @@
|
||||
# Generated by Django 5.0.2 on 2024-03-06 16:25
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("manage_events", "0002_favorites"),
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterUniqueTogether(
|
||||
name="eventprincipalinteraction",
|
||||
unique_together={("principal", "event")},
|
||||
),
|
||||
]
|
||||
@@ -106,7 +106,7 @@ class EventPrincipalInteraction(models.Model):
|
||||
)
|
||||
|
||||
class Meta:
|
||||
unique_together = ("principal", "event", "status")
|
||||
unique_together = ("principal", "event")
|
||||
|
||||
|
||||
class PrincipalPreference(BaseModel):
|
||||
@@ -120,3 +120,14 @@ class PrincipalPreference(BaseModel):
|
||||
|
||||
class Meta:
|
||||
db_table = "user_preference"
|
||||
|
||||
|
||||
class Favorites(models.Model):
|
||||
principal = models.ForeignKey(IAmPrincipal, on_delete=models.CASCADE, related_name='favorited_by')
|
||||
event = models.ForeignKey(Event, on_delete=models.CASCADE, related_name='favorites')
|
||||
|
||||
class Meta:
|
||||
unique_together = ('principal', 'event')
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.principal}'s favorite: {self.event.title}"
|
||||
|
||||
38
manage_events/utils.py
Normal file
38
manage_events/utils.py
Normal file
@@ -0,0 +1,38 @@
|
||||
import math
|
||||
from manage_events.models import Event, Venue
|
||||
|
||||
|
||||
def haversine(lon1, lat1, lon2, lat2):
|
||||
"""
|
||||
Calculate the great circle distance in kilometers between two points
|
||||
on the earth (specified in decimal degrees)
|
||||
"""
|
||||
# convert decimal degrees to radians
|
||||
lon1, lat1, lon2, lat2 = map(math.radians, [lon1, lat1, lon2, lat2])
|
||||
|
||||
# haversine formula
|
||||
dlon = lon2 - lon1
|
||||
dlat = lat2 - lat1
|
||||
a = (
|
||||
math.sin(dlat / 2) ** 2
|
||||
+ math.cos(lat1) * math.cos(lat2) * math.sin(dlon / 2) ** 2
|
||||
)
|
||||
c = 2 * math.asin(math.sqrt(a))
|
||||
r = 6371 # Radius of earth in kilometers. Use 3956 for miles
|
||||
return c * r
|
||||
|
||||
|
||||
def filter_events_by_location(user_lat, user_lon, radius_km=10):
|
||||
venues_within_radius = []
|
||||
|
||||
# Check each venue to see if it's within the radius
|
||||
for venue in Venue.objects.filter(deleted=False, active=True):
|
||||
print("venue: ", venue)
|
||||
distance = haversine(user_lon, user_lat, venue.longitude, venue.latitude)
|
||||
print("distance: ", distance)
|
||||
if distance <= radius_km:
|
||||
venues_within_radius.append(venue.id)
|
||||
print("venues_within_radius: ", venues_within_radius)
|
||||
# Filter events based on the venues within the radius
|
||||
events = Event.objects.filter(venue__id__in=venues_within_radius)
|
||||
return events
|
||||
@@ -299,25 +299,26 @@ class EventView(LoginRequiredMixin, generic.ListView):
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context["page_name"] = self.page_name
|
||||
|
||||
# Paginate the queryset
|
||||
queryset = self.get_queryset()
|
||||
page_obj = Paginator(queryset, self.paginate_by)
|
||||
page_number = self.request.GET.get(
|
||||
"page"
|
||||
) # Get current page from URL parameter
|
||||
page_obj = page_obj.get_page(page_number)
|
||||
|
||||
context.update(
|
||||
{
|
||||
"events": page_obj.object_list,
|
||||
"paginator": page_obj,
|
||||
"is_paginated": page_obj.has_other_pages(), # Check if there are more pages
|
||||
}
|
||||
)
|
||||
|
||||
return context
|
||||
|
||||
# # Paginate the queryset
|
||||
# queryset = self.get_queryset()
|
||||
# page_obj = Paginator(queryset, self.paginate_by)
|
||||
# page_number = self.request.GET.get(
|
||||
# "page"
|
||||
# ) # Get current page from URL parameter
|
||||
# page_obj = page_obj.get_page(page_number)
|
||||
|
||||
# context.update(
|
||||
# {
|
||||
# "events": page_obj.object_list,
|
||||
# "paginator": page_obj,
|
||||
# "is_paginated": page_obj.has_other_pages(), # Check if there are more pages
|
||||
# }
|
||||
# )
|
||||
|
||||
# return context
|
||||
|
||||
|
||||
class EventDetailView(generic.DetailView):
|
||||
model = Event
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
{% extends 'layout/base_template.html' %}
|
||||
{% load static %}
|
||||
{% block stylesheet %}
|
||||
<!-- include required css cdn link through html here -->
|
||||
{% include "cdn_through_html/datatable_cdn_css.html" %}
|
||||
<!-- include required css cdn link through html here -->
|
||||
{% include "cdn_through_html/datatable_cdn_css.html" %}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<div class="col-lg-12">
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
<h3>Manage Events</h3>
|
||||
<h3>Manage Subscriptions</h3>
|
||||
</div>
|
||||
<div class="col-sm-6 text-md-end">
|
||||
<!--
|
||||
@@ -24,10 +24,11 @@
|
||||
<a class="btn btn-primary mb-2" href="{% url 'manage_events:event_add' %}">Add Event</a>
|
||||
<a class="btn btn-primary mb-2" href="{% url 'manage_events:event_category_list' %}">Event Category</a>
|
||||
<a class="btn btn-primary mb-2" href="{% url 'manage_events:event_master_list' %}">Event Master</a>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="row layout-spacing">
|
||||
<div class="col-lg-12">
|
||||
<div class="statbox widget box box-shadow">
|
||||
@@ -60,7 +61,8 @@
|
||||
{% for data_obj in event_obj %}
|
||||
<tr role="row">
|
||||
<td class="checkbox-column text-center sorting_1"><a
|
||||
href="{% url 'manage_events:event_detail' data_obj.id %}">{{data_obj.id}}</a></td>
|
||||
href="{% url 'manage_events:event_detail' data_obj.id %}">{{data_obj.id}}</a>
|
||||
</td>
|
||||
<td>{{data_obj.title}}</td>
|
||||
<td>{{data_obj.start_date}}</td>
|
||||
<td>{{data_obj.end_date}}</td>
|
||||
@@ -106,39 +108,39 @@
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock content %}
|
||||
|
||||
{% block javascript %}
|
||||
<!-- include required js cdn link through html here -->
|
||||
{% include "cdn_through_html/datatable_cdn_js.html" %}
|
||||
|
||||
<script>
|
||||
c3 = $('#style-3').DataTable({
|
||||
"dom": "<'dt--top-section'<'row'<'col-12 col-sm-6 d-flex justify-content-sm-start justify-content-center'l><'col-12 col-sm-6 d-flex justify-content-sm-end justify-content-center mt-sm-0 mt-3'f>>>" +
|
||||
"<'table-responsive'tr>" +
|
||||
"<'dt--bottom-section d-sm-flex justify-content-sm-between text-center'<'dt--pages-count mb-sm-0 mb-3'i><'dt--pagination'p>>",
|
||||
"oLanguage": {
|
||||
"oPaginate": { "sPrevious": '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-arrow-left"><line x1="19" y1="12" x2="5" y2="12"></line><polyline points="12 19 5 12 12 5"></polyline></svg>', "sNext": '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-arrow-right"><line x1="5" y1="12" x2="19" y2="12"></line><polyline points="12 5 19 12 12 19"></polyline></svg>' },
|
||||
"sInfo": "Showing page _PAGE_ of _PAGES_",
|
||||
"sSearch": '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-search"><circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line></svg>',
|
||||
"sSearchPlaceholder": "Search...",
|
||||
"sLengthMenu": "Results : _MENU_",
|
||||
},
|
||||
"stripeClasses": [],
|
||||
"lengthMenu": [5, 10, 20, 50],
|
||||
"pageLength": 10
|
||||
});
|
||||
|
||||
multiCheck(c3);
|
||||
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
{% endblock content %}
|
||||
|
||||
{% block javascript %}
|
||||
<!-- include required js cdn link through html here -->
|
||||
{% include "cdn_through_html/datatable_cdn_js.html" %}
|
||||
|
||||
<script>
|
||||
c3 = $('#style-3').DataTable({
|
||||
"dom": "<'dt--top-section'<'row'<'col-12 col-sm-6 d-flex justify-content-sm-start justify-content-center'l><'col-12 col-sm-6 d-flex justify-content-sm-end justify-content-center mt-sm-0 mt-3'f>>>" +
|
||||
"<'table-responsive'tr>" +
|
||||
"<'dt--bottom-section d-sm-flex justify-content-sm-between text-center'<'dt--pages-count mb-sm-0 mb-3'i><'dt--pagination'p>>",
|
||||
"oLanguage": {
|
||||
"oPaginate": { "sPrevious": '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-arrow-left"><line x1="19" y1="12" x2="5" y2="12"></line><polyline points="12 19 5 12 12 5"></polyline></svg>', "sNext": '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-arrow-right"><line x1="5" y1="12" x2="19" y2="12"></line><polyline points="12 5 19 12 12 19"></polyline></svg>' },
|
||||
"sInfo": "Showing page _PAGE_ of _PAGES_",
|
||||
"sSearch": '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-search"><circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line></svg>',
|
||||
"sSearchPlaceholder": "Search...",
|
||||
"sLengthMenu": "Results : _MENU_",
|
||||
},
|
||||
"stripeClasses": [],
|
||||
"lengthMenu": [5, 10, 20, 50],
|
||||
"pageLength": 10
|
||||
});
|
||||
|
||||
multiCheck(c3);
|
||||
|
||||
</script>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user