diff --git a/cms/admin.py b/cms/admin.py index de3762d..f06fc55 100644 --- a/cms/admin.py +++ b/cms/admin.py @@ -1,5 +1,5 @@ from django.contrib import admin -from cms.models import Profile, EmailConfirmation, Place, Activity, PlaceActivity, Type, Tag, District, Province +from cms.models import Profile, EmailConfirmation, Place, Activity, PlaceActivity, Type, Tag, District, Province, Image from messaging.models import Message, Conversation class ListAdmin(admin.ModelAdmin): def __init__(self, model, admin_site): @@ -33,4 +33,4 @@ def __init__(self, model, admin_site): admin.site.register(Province, ListAdmin) admin.site.register(Message,ListAdmin) admin.site.register(Conversation,ListAdmin) - +admin.site.register(Image,ListAdmin) diff --git a/cms/migrations/0008_image_place_ratings_place_header_image_place_images.py b/cms/migrations/0008_image_place_ratings_place_header_image_place_images.py new file mode 100644 index 0000000..f67d40d --- /dev/null +++ b/cms/migrations/0008_image_place_ratings_place_header_image_place_images.py @@ -0,0 +1,45 @@ +# Generated by Django 4.2.13 on 2024-08-30 16:26 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + dependencies = [ + ("cms", "0007_alter_place_accommodation_places_nearby"), + ] + + operations = [ + migrations.CreateModel( + name="Image", + fields=[ + ("created_at", models.DateTimeField(auto_now_add=True)), + ("updated_at", models.DateTimeField(auto_now=True)), + ("id", models.AutoField(primary_key=True, serialize=False)), + ("image", models.TextField()), + ], + options={ + "abstract": False, + }, + ), + migrations.AddField( + model_name="place", + name="ratings", + field=models.FloatField(blank=True, null=True), + ), + migrations.AddField( + model_name="place", + name="header_image", + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.PROTECT, + to="cms.image", + ), + ), + migrations.AddField( + model_name="place", + name="images", + field=models.ManyToManyField(related_name="places", to="cms.image"), + ), + ] diff --git a/cms/migrations/0009_remove_image_image_image_image_url.py b/cms/migrations/0009_remove_image_image_image_image_url.py new file mode 100644 index 0000000..cb78099 --- /dev/null +++ b/cms/migrations/0009_remove_image_image_image_image_url.py @@ -0,0 +1,22 @@ +# Generated by Django 4.2.13 on 2024-08-30 16:57 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("cms", "0008_image_place_ratings_place_header_image_place_images"), + ] + + operations = [ + migrations.RemoveField( + model_name="image", + name="image", + ), + migrations.AddField( + model_name="image", + name="image_url", + field=models.CharField(default=1, max_length=1000), + preserve_default=False, + ), + ] diff --git a/cms/migrations/0010_alter_image_image_url.py b/cms/migrations/0010_alter_image_image_url.py new file mode 100644 index 0000000..2a77300 --- /dev/null +++ b/cms/migrations/0010_alter_image_image_url.py @@ -0,0 +1,17 @@ +# Generated by Django 4.2.13 on 2024-08-30 17:00 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("cms", "0009_remove_image_image_image_image_url"), + ] + + operations = [ + migrations.AlterField( + model_name="image", + name="image_url", + field=models.CharField(max_length=1001), + ), + ] diff --git a/cms/migrations/0011_alter_image_image_url.py b/cms/migrations/0011_alter_image_image_url.py new file mode 100644 index 0000000..748a1d6 --- /dev/null +++ b/cms/migrations/0011_alter_image_image_url.py @@ -0,0 +1,17 @@ +# Generated by Django 4.2.13 on 2024-08-30 17:01 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("cms", "0010_alter_image_image_url"), + ] + + operations = [ + migrations.AlterField( + model_name="image", + name="image_url", + field=models.CharField(max_length=1000), + ), + ] diff --git a/cms/migrations/0012_image_data.py b/cms/migrations/0012_image_data.py new file mode 100644 index 0000000..71438bf --- /dev/null +++ b/cms/migrations/0012_image_data.py @@ -0,0 +1,17 @@ +# Generated by Django 4.2.13 on 2024-08-30 17:08 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("cms", "0011_alter_image_image_url"), + ] + + operations = [ + migrations.AddField( + model_name="image", + name="data", + field=models.TextField(blank=True, null=True), + ), + ] diff --git a/cms/migrations/0013_rename_image_url_image_url.py b/cms/migrations/0013_rename_image_url_image_url.py new file mode 100644 index 0000000..2133c84 --- /dev/null +++ b/cms/migrations/0013_rename_image_url_image_url.py @@ -0,0 +1,17 @@ +# Generated by Django 4.2.13 on 2024-08-30 17:28 + +from django.db import migrations + + +class Migration(migrations.Migration): + dependencies = [ + ("cms", "0012_image_data"), + ] + + operations = [ + migrations.RenameField( + model_name="image", + old_name="image_url", + new_name="url", + ), + ] diff --git a/cms/models.py b/cms/models.py index a86f778..53e8f8f 100644 --- a/cms/models.py +++ b/cms/models.py @@ -26,6 +26,14 @@ class Province(TimeStampMixin): id = models.AutoField(primary_key=True) name = models.CharField(max_length=255) +class Image(TimeStampMixin): + id = models.AutoField(primary_key=True) + data = models.TextField(null=True, blank=True) + image_url = models.CharField(max_length=1000) + + def __str__(self): + return f"Image {self.id}" + class Image(TimeStampMixin): id = models.AutoField(primary_key=True) data = models.TextField(null=True, blank=True) @@ -54,12 +62,16 @@ class Place(TimeStampMixin): ratings = models.FloatField(null=True, blank=True) header_image = models.ForeignKey(Image, on_delete=models.PROTECT, null=True, blank=True) images = models.ManyToManyField(Image, related_name="places") + ratings = models.FloatField(null=True, blank=True) + header_image = models.ForeignKey(Image, on_delete=models.PROTECT, null=True, blank=True) + images = models.ManyToManyField(Image, related_name="places") def __str__(self): return self.place_name # column1=place_id,column2=place_name,column3=description,column4=district_id,column5=province_id,column6=ticket_price,column7=location,column8=latitude,column9=longitude,column10=how_to_visit,,column11=best_time_to_visit_in_year,,column12=data + class Activity(TimeStampMixin): activity_id = models.AutoField(primary_key=True) activity_name = models.CharField(max_length=255) diff --git a/cms/serializers.py b/cms/serializers.py index 180adb4..fa1fb4a 100644 --- a/cms/serializers.py +++ b/cms/serializers.py @@ -39,6 +39,10 @@ class PlaceSerializer(serializers.ModelSerializer): district_name = serializers.SerializerMethodField() province_name = serializers.SerializerMethodField() activity_objects = serializers.SerializerMethodField() + header_image = serializers.SerializerMethodField( + + ) + images = serializers.SerializerMethodField() # accommodation_places_nearby = serializers.SerializerMethodField() class Meta: model = Place @@ -50,6 +54,14 @@ def get_province_name(self, obj): return obj.province.name def get_activity_objects(self, obj): return obj.activities.values("activity_id", "activity_name", "description") + + def get_header_image(self, obj): + return {"url": obj.header_image.image_url if obj.header_image else None} + + def get_images(self, obj): + return obj.images.values("image_url") + + class TypeSerializer(serializers.ModelSerializer): diff --git a/cms/urls.py b/cms/urls.py index d568a6e..efd264b 100644 --- a/cms/urls.py +++ b/cms/urls.py @@ -2,6 +2,7 @@ from cms.viewsets.UserViewset import UserViewSet from rest_framework import routers from cms.views import ProfileViewSet, EmailConfirmationViewSet, DistrictViewSet, ProvinceViewSet, PlaceViewSet, ActivityViewSet, PlaceActivityViewSet, TypeViewSet, TagViewSet +from messaging.views import ConversationViewSet, MessageViewSet router = routers.DefaultRouter() @@ -15,6 +16,7 @@ router.register(r"placeactivity", PlaceActivityViewSet) router.register(r"type", TypeViewSet) router.register(r"tag", TagViewSet) - +router.register(r"conversation", ConversationViewSet) +router.register(r"message", MessageViewSet) urlpatterns = router.urls \ No newline at end of file diff --git a/cms/views.py b/cms/views.py index f251c2b..555f0c2 100644 --- a/cms/views.py +++ b/cms/views.py @@ -79,4 +79,3 @@ class TagViewSet(viewsets.ModelViewSet): queryset = Tag.objects.all() serializer_class = TagSerializer - diff --git a/messaging/migrations/0003_alter_conversation_isai.py b/messaging/migrations/0003_alter_conversation_isai.py new file mode 100644 index 0000000..c600841 --- /dev/null +++ b/messaging/migrations/0003_alter_conversation_isai.py @@ -0,0 +1,17 @@ +# Generated by Django 4.2.13 on 2024-08-30 14:58 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("messaging", "0002_rename_guide_id_message_guide_and_more"), + ] + + operations = [ + migrations.AlterField( + model_name="conversation", + name="isAI", + field=models.BooleanField(default=True), + ), + ] diff --git a/messaging/migrations/0004_rename_conversation_id_conversation_id_and_more.py b/messaging/migrations/0004_rename_conversation_id_conversation_id_and_more.py new file mode 100644 index 0000000..bf29388 --- /dev/null +++ b/messaging/migrations/0004_rename_conversation_id_conversation_id_and_more.py @@ -0,0 +1,33 @@ +# Generated by Django 4.2.13 on 2024-08-30 16:57 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("messaging", "0003_alter_conversation_isai"), + ] + + operations = [ + migrations.RenameField( + model_name="conversation", + old_name="conversation_id", + new_name="id", + ), + migrations.AlterField( + model_name="message", + name="date", + field=models.DateField(default=datetime.date.today), + ), + migrations.AlterField( + model_name="message", + name="id", + field=models.AutoField(primary_key=True, serialize=False), + ), + migrations.AlterField( + model_name="message", + name="time", + field=models.TimeField(default=datetime.time), + ), + ] diff --git a/messaging/models.py b/messaging/models.py index 1d5b76d..82a95ab 100644 --- a/messaging/models.py +++ b/messaging/models.py @@ -1,23 +1,25 @@ from django.db import models from cms.models import Place from django.contrib.auth.models import User +from datetime import date, time # Create your models here. class Conversation(models.Model): - conversation_id = models.AutoField(primary_key=True) + id = models.AutoField(primary_key=True) user = models.ForeignKey(User, on_delete=models.PROTECT) - isAI = models.BooleanField() + isAI = models.BooleanField(default=True) def __str__(self): - return f"Conversation {self.conversation_id} - User {self.user_id}" + return f"Conversation {self.id} - User {self.user}" class Message(models.Model): - date = models.DateField() - time = models.TimeField() + id = models.AutoField(primary_key=True) + date = models.DateField(default=date.today) + time = models.TimeField(default=time) conversation = models.ForeignKey(Conversation, on_delete=models.CASCADE) - message = models.TextField() - place = models.ForeignKey(Place, null=True, blank=True, on_delete=models.PROTECT) - guide = models.ForeignKey(User, null=True, blank=True, on_delete=models.PROTECT) - + message = models.TextField() + place = models.ForeignKey(Place, null=True, blank=True, on_delete=models.PROTECT) + guide = models.ForeignKey(User, null=True, blank=True, on_delete=models.PROTECT) + def __str__(self): - return f"Message in Conversation {self.conversation.conversation_id} on {self.date} at {self.time}" + return f"Message {self.id} in Conversation {self.conversation} on {self.date} at {self.time}" diff --git a/messaging/serializers.py b/messaging/serializers.py index 8825496..e2c88ac 100644 --- a/messaging/serializers.py +++ b/messaging/serializers.py @@ -6,7 +6,7 @@ class ConversationSerializer(serializers.ModelSerializer): class Meta: model = Conversation - fields = ['conversation_id', 'user_id', 'isAI'] + fields = ['id', 'user', 'isAI'] class MessageSerializer(serializers.ModelSerializer): conversation = serializers.PrimaryKeyRelatedField(queryset=Conversation.objects.all()) diff --git a/messaging/views.py b/messaging/views.py index d7da7b7..af56640 100644 --- a/messaging/views.py +++ b/messaging/views.py @@ -1,9 +1,7 @@ from django.shortcuts import render - -# Create your views here. -from rest_framework import viewsets +from rest_framework import viewsets, status from rest_framework.response import Response -from rest_framework import status +from datetime import datetime from .models import Conversation, Message from .serializers import ConversationSerializer, MessageSerializer @@ -11,44 +9,54 @@ class ConversationViewSet(viewsets.ModelViewSet): queryset = Conversation.objects.all() serializer_class = ConversationSerializer - # def create(self, request, *args, **kwargs): - # serializer = self.get_serializer(data=request.data) - # serializer.is_valid(raise_exception=True) - # self.perform_create(serializer) - # return Response(serializer.data, status=status.HTTP_201_CREATED) - - # def update(self, request, *args, **kwargs): - # partial = kwargs.pop('partial', False) - # instance = self.get_object() - # serializer = self.get_serializer(instance, data=request.data, partial=partial) - # serializer.is_valid(raise_exception=True) - # self.perform_update(serializer) - # return Response(serializer.data) - - # def destroy(self, request, *args, **kwargs): - # instance = self.get_object() - # self.perform_destroy(instance) - # return Response(status=status.HTTP_204_NO_CONTENT) + def create(self, request, *args, **kwargs): + serializer = self.get_serializer(data=request.data) + serializer.is_valid(raise_exception=True) + self.perform_create(serializer) + return Response(serializer.data, status=status.HTTP_201_CREATED) class MessageViewSet(viewsets.ModelViewSet): queryset = Message.objects.all() serializer_class = MessageSerializer - # def create(self, request, *args, **kwargs): - # serializer = self.get_serializer(data=request.data) - # serializer.is_valid(raise_exception=True) - # self.perform_create(serializer) - # return Response(serializer.data, status=status.HTTP_201_CREATED) - - # def update(self, request, *args, **kwargs): - # partial = kwargs.pop('partial', False) - # instance = self.get_object() - # serializer = self.get_serializer(instance, data=request.data, partial=partial) - # serializer.is_valid(raise_exception=True) - # self.perform_update(serializer) - # return Response(serializer.data) - - # def destroy(self, request, *args, **kwargs): - # instance = self.get_object() - # self.perform_destroy(instance) - # return Response(status=status.HTTP_204_NO_CONTENT) + def create(self, request, *args, **kwargs): + serializer = self.get_serializer(data=request.data) + serializer.is_valid(raise_exception=True) + + # Save the new message + self.perform_create(serializer) + + # Get the conversation ID from the newly created message + conversation_id = serializer.validated_data['conversation'].id # Corrected field reference + current_message = serializer.validated_data['message'] + messages = Message.objects.filter(conversation_id=conversation_id).order_by('-date', '-time')[:5] + message_history = messages.values('date', 'time', 'message') + + conversation = Conversation.objects.get(id=conversation_id) # Corrected field reference + if conversation.isAI: + ai_response = self.get_response_AI(conversation_id, message_history) + + Message.objects.create( + conversation_id=conversation_id, # Corrected field reference + date=datetime.now().date(), # Current date + time=datetime.now().time(), # Current time + message=ai_response, + ) + + return Response(serializer.data, status=status.HTTP_201_CREATED) + + def create_conversation_json(self, messages): + conversation_history = [] + for message in messages: + conversation_history.append({ + 'date': message.date.isoformat(), + 'time': message.time.isoformat(), + 'message': message.message, + 'place': message.place.place_name if message.place else None, + 'guide': message.guide.username if message.guide else None, + }) + return conversation_history + + def get_response_AI(self, conversation_id, current_message): + # Placeholder function for AI response + return "This is an AI generated response"