Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

featuture (Event-registration): added registaration in Event model #71

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 78 additions & 4 deletions event/admin.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
# Register your models here.
from django.db.models import F, Count
from django.contrib import messages
from django import forms
from . import models
from core.base_admin import SummernoteModelAdmin, SummernoteInlineMixin
Expand All @@ -23,6 +25,49 @@ class EventImagesInline(SummernoteInlineMixin, NestedStackedInline):
extra = 1


class ParticipantsInline(SummernoteInlineMixin, NestedStackedInline):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also rather than admin pannel it would be great if we could present api for participants
so i dont think we need to make particiant more complicated than this

model = models.Participant
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also do we need inline as event is independent to the participants
just update the participants
why do we need it in the event sections

extra = 0
Copy link
Collaborator

@rex9840 rex9840 Jan 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you have defined extra=0 here but again called get_extra() to configure inline.extra ?? if you are using it extra=0 is just a extra line of code


def get_extra(self, request, obj=None, **kwargs):

if obj: # Ensure we're dealing with an existing Event object
if obj.participants.count() < obj.max_capacity:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can remove nested if else simply buy using and operator comparision

return 1 # Show one extra form
return 0 # Don't show any extra forms

def has_add_permission(self, request, obj=None):
"""
Prevent adding new participants if the event is full.
"""
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as get_extra() remove nested if

if obj: # Ensure we're dealing with an existing Event object
if obj.participants.count() >= obj.max_capacity:
messages.warning(
request,
"The event is full. You cannot add more participants.",
)
return False # Hide "Add another" button
return super().has_add_permission(request, obj)


class ParticipantAdminForm(forms.ModelForm):
class Meta:
model = models.Participant
fields = "__all__"

"""
Overriding the __init__ method to filter the events that are checked
"""

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields["events"].queryset = models.Event.objects.annotate(
participant_count=Count("participants")
).filter(
requires_registration=True, participant_count__lt=F("max_capacity")
) # Ensures max_capacity > p_count


class EventAdminForms(forms.ModelForm):
class Meta:
model = models.Event
Expand All @@ -33,6 +78,7 @@ class Meta:
"start_date": "This is the date the event will start",
"end_date": "This is the date the event will end",
"description": "This is the description of the event",
"requires_registration": "Check if the event needs registration",
"rsvp_url": "This is the link to the RSVP page",
"add_to_calender_url": "Add the event to your calendar",
"is_draft": "This is the status of the event",
Expand All @@ -51,12 +97,21 @@ class EventModelAdmin(NestedModelAdmin, SummernoteModelAdmin):
list_display = ["title", "is_draft", "start_date", "end_date"]
search_fields = ["slug", "title"]
readonly_fields = ["created_at", "updated_at", "slug"]
inlines = [
EventScheduleInline,
EventImagesInline,
]
inlines = [EventScheduleInline, EventImagesInline]
autocomplete_fields = ["location", "event_type", "hot_topics"]

"""Overriding this method to conditionally
add the ParticipantsInline to the inlines list
"""

def get_inline_instances(self, request, obj=None):
inline_instances = super().get_inline_instances(request, obj)
if obj and obj.requires_registration:
inline_instances.append(
ParticipantsInline(self.model, self.admin_site)
)
return inline_instances


@admin.register(models.Speaker)
class SpeakersAdmin(SummernoteInlineMixin, admin.ModelAdmin):
Expand Down Expand Up @@ -90,6 +145,25 @@ class HotTopicAdmin(admin.ModelAdmin):
search_fields = ["name"]


@admin.register(models.Participant)
class ParticipantAdmin(admin.ModelAdmin):
form = ParticipantAdminForm
list_display = [
"first_name",
"last_name",
"email",
"academy",
"phone_number",
]
search_fields = [
"first_name",
"last_name",
"email",
"academy",
"phone_number",
]


admin.site.register(
[
models.EventImage,
Expand Down
41 changes: 41 additions & 0 deletions event/migrations/0007_participant.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Generated by Django 5.1.1 on 2025-01-11 15:21

import django.db.models.deletion
from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("event", "0006_alter_event_image_alter_eventimage_image_and_more"),
]

operations = [
migrations.CreateModel(
name="Participant",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("first_name", models.CharField(max_length=255)),
("last_name", models.CharField(max_length=255)),
("email", models.EmailField(max_length=255)),
("academy", models.CharField(max_length=255)),
("phone_number", models.CharField(max_length=255)),
(
"events",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="participants",
to="event.event",
),
),
],
),
]
18 changes: 18 additions & 0 deletions event/migrations/0008_alter_participant_phone_number.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 5.1.1 on 2025-01-11 15:58

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("event", "0007_participant"),
]

operations = [
migrations.AlterField(
model_name="participant",
name="phone_number",
field=models.CharField(max_length=14),
),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Generated by Django 5.1.1 on 2025-01-11 16:58

import django.core.validators
from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("event", "0008_alter_participant_phone_number"),
]

operations = [
migrations.AddField(
model_name="participant",
name="age",
field=models.IntegerField(default=20),
preserve_default=False,
),
migrations.AlterField(
model_name="participant",
name="phone_number",
field=models.CharField(
max_length=14,
validators=[
django.core.validators.RegexValidator(
message="Phone number must be entered in the format: '9999999999'. Up to 14 digits allowed including +977",
regex="^\\+?[0-9]*$",
)
],
),
),
]
40 changes: 40 additions & 0 deletions event/migrations/0010_event_requires_registration_and_more.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Generated by Django 5.1.1 on 2025-01-12 06:42

import django.core.validators
from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("event", "0009_participant_age_alter_participant_phone_number"),
]

operations = [
migrations.AddField(
model_name="event",
name="requires_registration",
field=models.BooleanField(default=False),
),
migrations.AlterField(
model_name="participant",
name="academy",
field=models.CharField(blank=True, max_length=255),
),
migrations.AlterField(
model_name="participant",
name="phone_number",
field=models.CharField(
max_length=14,
validators=[
django.core.validators.RegexValidator(
message=(
"Phone number must be 10 digit",
"long and Up to 14 digits allowed including +977",
),
regex="^\\+?[0-9]{10,14}$",
)
],
),
),
]
24 changes: 24 additions & 0 deletions event/migrations/0011_alter_participant_events.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Generated by Django 5.1.1 on 2025-01-12 07:05

import django.db.models.deletion
from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("event", "0010_event_requires_registration_and_more"),
]

operations = [
migrations.AlterField(
model_name="participant",
name="events",
field=models.ForeignKey(
error_messages="Event is required",
on_delete=django.db.models.deletion.CASCADE,
related_name="participants",
to="event.event",
),
),
]
54 changes: 54 additions & 0 deletions event/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from uuid import uuid4

from django.core.exceptions import ValidationError
from django.core.validators import RegexValidator
from django.db import models
from django.utils.text import slugify

Expand Down Expand Up @@ -42,6 +43,7 @@ class Event(models.Model):
start_date = models.DateField(blank=False, null=False)
end_date = models.DateField(blank=False, null=False)
description = models.TextField(blank=False, null=False)
requires_registration = models.BooleanField(default=False)
rsvp_url = models.URLField(max_length=500, null=True, blank=True)
image = models.ImageField(
upload_to="%Y/%m/%d/events", null=True, blank=True
Expand Down Expand Up @@ -162,6 +164,13 @@ def clean(self):
"Registration deadline must be less than start date."
)

"""
validation if the participants exceeds the maximum capacity"""
if self.participants.count() > self.max_capacity:
raise ValidationError(
"Participants cannot be more than the maximum capacity"
)

def save(self, *args, **kwargs):
"""
We are overriding events save model
Expand Down Expand Up @@ -246,3 +255,48 @@ def __str__(self):

class Meta:
ordering = ["position"]


class Participant(models.Model):
first_name = models.CharField(max_length=255)
last_name = models.CharField(max_length=255)
email = models.EmailField(max_length=255)
academy = models.CharField(max_length=255, blank=True)
phone_number = models.CharField(
max_length=14,
validators=[
RegexValidator(
# makes sure the it is at least 10 and no more than 14
regex=r"^\+?[0-9]{10,14}$",
message=(
"Phone number must be 10 digit",
"long and Up to 14 digits allowed including +977",
),
)
],
)
events = models.ForeignKey(
Event,
related_name="participants",
on_delete=models.CASCADE,
blank=False,
null=False,
)
age = models.IntegerField(null=False, blank=False)

def clean(self):
"""
Do not allow saving the participant if the event is full.
"""
if self.events.participants.count() >= self.events.max_capacity:
raise ValidationError("Event is full")
if not self.events:
raise ValidationError("Event is required")

def save(self, *args, **kwargs):
# Call clean() before saving
self.clean()
super().save(*args, **kwargs)

def __str__(self):
return self.first_name + " " + self.last_name
7 changes: 7 additions & 0 deletions event/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,19 @@ class Meta:
fields = "__all__"


Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seriailzer exiss but not route and view for the participants

class ParticipantsSerializer(serializers.ModelSerializer):
class Meta:
model = models.Participant
fields = "__all__"


class EventSerializer(serializers.ModelSerializer):
event_type = serializers.StringRelatedField()
location = EventLocationSerializer()
hot_topics = serializers.StringRelatedField(many=True)
schedules = ScheduleSerializer(many=True)
images = serializers.SerializerMethodField(read_only=True)
participants = ParticipantsSerializer(many=True)

def get_images(self, obj):
"""
Expand Down
Loading