1
0
Fork 0
mirror of https://github.com/seanmorley15/AdventureLog.git synced 2025-07-23 06:49:37 +02:00

transportation

This commit is contained in:
Sean Morley 2024-07-27 19:04:55 -04:00
parent 66a2e30711
commit ae9a7f5479
7 changed files with 155 additions and 6 deletions

View file

@ -1,7 +1,7 @@
import os
from django.contrib import admin
from django.utils.html import mark_safe
from .models import Adventure, Collection
from .models import Adventure, Collection, Transportation
from worldtravel.models import Country, Region, VisitedRegion
@ -74,6 +74,7 @@ admin.site.register(Collection, CollectionAdmin)
admin.site.register(Country, CountryAdmin)
admin.site.register(Region, RegionAdmin)
admin.site.register(VisitedRegion)
admin.site.register(Transportation)
admin.site.site_header = 'AdventureLog Admin'
admin.site.site_title = 'AdventureLog Admin Site'

View file

@ -0,0 +1,41 @@
# Generated by Django 5.0.7 on 2024-07-27 22:49
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('adventures', '0012_collection_end_date_collection_start_date'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.AlterField(
model_name='adventure',
name='type',
field=models.CharField(choices=[('visited', 'Visited'), ('planned', 'Planned'), ('lodging', 'Lodging'), ('dining', 'Dining')], max_length=100),
),
migrations.CreateModel(
name='Transportation',
fields=[
('id', models.AutoField(primary_key=True, serialize=False)),
('type', models.CharField(max_length=100)),
('name', models.CharField(max_length=200)),
('description', models.TextField(blank=True, null=True)),
('rating', models.FloatField(blank=True, null=True)),
('link', models.URLField(blank=True, null=True)),
('date', models.DateTimeField(blank=True, null=True)),
('flight_number', models.CharField(blank=True, max_length=100, null=True)),
('from_location', models.CharField(blank=True, max_length=200, null=True)),
('to_location', models.CharField(blank=True, max_length=200, null=True)),
('is_public', models.BooleanField(default=False)),
('created_at', models.DateTimeField(auto_now_add=True)),
('updated_at', models.DateTimeField(auto_now=True)),
('collection', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='adventures.collection')),
('user_id', models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
]

View file

@ -12,6 +12,17 @@ ADVENTURE_TYPES = [
('dining', 'Dining')
]
TRANSPORTATION_TYPES = [
('car', 'Car'),
('plane', 'Plane'),
('train', 'Train'),
('bus', 'Bus'),
('boat', 'Boat'),
('bike', 'Bike'),
('walking', 'Walking'),
('other', 'Other')
]
# Assuming you have a default user ID you want to use
default_user_id = 1 # Replace with an actual user ID
@ -70,3 +81,33 @@ class Collection(models.Model):
def __str__(self):
return self.name
# make a class for transportaiotn and make it linked to a collection. Make it so it can be used for different types of transportations like car, plane, train, etc.
class Transportation(models.Model):
id = models.AutoField(primary_key=True)
user_id = models.ForeignKey(
User, on_delete=models.CASCADE, default=default_user_id)
type = models.CharField(max_length=100, choices=TRANSPORTATION_TYPES)
name = models.CharField(max_length=200)
description = models.TextField(blank=True, null=True)
rating = models.FloatField(blank=True, null=True)
link = models.URLField(blank=True, null=True)
date = models.DateTimeField(blank=True, null=True)
flight_number = models.CharField(max_length=100, blank=True, null=True)
from_location = models.CharField(max_length=200, blank=True, null=True)
to_location = models.CharField(max_length=200, blank=True, null=True)
is_public = models.BooleanField(default=False)
collection = models.ForeignKey('Collection', on_delete=models.CASCADE, blank=True, null=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def clean(self):
if self.collection:
if self.collection.is_public and not self.is_public:
raise ValidationError('Transportations associated with a public collection must be public. Collection: ' + self.trip.name + ' Transportation: ' + self.name)
if self.user_id != self.collection.user_id:
raise ValidationError('Transportations must be associated with collections owned by the same user. Collection owner: ' + self.collection.user_id.username + ' Transportation owner: ' + self.user_id.username)
def __str__(self):
return self.name

View file

@ -1,5 +1,5 @@
import os
from .models import Adventure, Collection
from .models import Adventure, Collection, Transportation
from rest_framework import serializers
class AdventureSerializer(serializers.ModelSerializer):
@ -31,5 +31,38 @@ class CollectionSerializer(serializers.ModelSerializer):
# fields are all plus the adventures field
fields = ['id', 'description', 'user_id', 'name', 'is_public', 'adventures', 'created_at', 'start_date', 'end_date']
class TransportationSerializer(serializers.ModelSerializer):
class Meta:
model = Transportation
fields = [
'id', 'user_id', 'type', 'name', 'description', 'rating',
'link', 'date', 'flight_number', 'from_location', 'to_location',
'is_public', 'collection', 'collection_id', 'created_at', 'updated_at'
]
read_only_fields = ['id', 'created_at', 'updated_at']
def validate(self, data):
# Check if the collection is public and the transportation is not
collection = data.get('collection')
is_public = data.get('is_public', False)
if collection and collection.is_public and not is_public:
raise serializers.ValidationError(
'Transportations associated with a public collection must be public.'
)
# Check if the user owns the collection
request = self.context.get('request')
if request and collection and collection.user_id != request.user:
raise serializers.ValidationError(
'Transportations must be associated with collections owned by the same user.'
)
return data
def create(self, validated_data):
# Set the user_id to the current user
validated_data['user_id'] = self.context['request'].user
return super().create(validated_data)

View file

@ -1,6 +1,6 @@
from django.urls import include, path
from rest_framework.routers import DefaultRouter
from .views import AdventureViewSet, CollectionViewSet, StatsViewSet, GenerateDescription, ActivityTypesView
from .views import AdventureViewSet, CollectionViewSet, StatsViewSet, GenerateDescription, ActivityTypesView, TransportationViewSet
router = DefaultRouter()
router.register(r'adventures', AdventureViewSet, basename='adventures')
@ -8,6 +8,7 @@ router.register(r'collections', CollectionViewSet, basename='collections')
router.register(r'stats', StatsViewSet, basename='stats')
router.register(r'generate', GenerateDescription, basename='generate')
router.register(r'activity-types', ActivityTypesView, basename='activity-types')
router.register(r'transportations', TransportationViewSet, basename='transportations')
urlpatterns = [

View file

@ -4,9 +4,9 @@ from rest_framework.decorators import action
from rest_framework import viewsets
from django.db.models.functions import Lower
from rest_framework.response import Response
from .models import Adventure, Collection
from .models import Adventure, Collection, Transportation
from worldtravel.models import VisitedRegion, Region, Country
from .serializers import AdventureSerializer, CollectionSerializer
from .serializers import AdventureSerializer, CollectionSerializer, TransportationSerializer
from rest_framework.permissions import IsAuthenticated
from django.db.models import Q, Prefetch
from .permissions import IsOwnerOrReadOnly, IsPublicReadOnly
@ -238,6 +238,9 @@ class CollectionViewSet(viewsets.ModelViewSet):
# Update associated adventures to match the collection's is_public status
Adventure.objects.filter(collection=instance).update(is_public=new_public_status)
# do the same for transportations
Transportation.objects.filter(collection=instance).update(is_public=new_public_status)
# Log the action (optional)
action = "public" if new_public_status else "private"
print(f"Collection {instance.id} and its adventures were set to {action}")
@ -379,3 +382,30 @@ class ActivityTypesView(viewsets.ViewSet):
allTypes.append(x)
return Response(allTypes)
class TransportationViewSet(viewsets.ModelViewSet):
queryset = Transportation.objects.all()
serializer_class = TransportationSerializer
permission_classes = [IsAuthenticated]
filterset_fields = ['type', 'is_public', 'collection']
# return error message if user is not authenticated on the root endpoint
def list(self, request, *args, **kwargs):
# Prevent listing all adventures
return Response({"detail": "Listing all adventures is not allowed."},
status=status.HTTP_403_FORBIDDEN)
def get_queryset(self):
"""
This view should return a list of all transportations
for the currently authenticated user.
"""
user = self.request.user
return Transportation.objects.filter(user_id=user)
def perform_create(self, serializer):
serializer.save(user_id=self.request.user)

View file

@ -163,9 +163,11 @@
<div class="badge badge-primary">Visited</div>
{:else if user?.pk == adventure.user_id && adventure.type == 'planned'}
<div class="badge badge-secondary">Planned</div>
{:else if (user?.pk !== adventure.user_id && adventure.type == 'planned') || adventure.type == 'visited'}
<div class="badge badge-secondary">Adventure</div>
{:else if user?.pk == adventure.user_id && adventure.type == 'lodging'}
<div class="badge badge-success">Lodging</div>
{:else if user?.pk == adventure.user_id && adventure.type == 'dining'}
{:else if adventure.type == 'dining'}
<div class="badge badge-accent">Dining</div>
{/if}