diff --git a/car_spotting/app/database.sqlite b/car_spotting/app/database.sqlite new file mode 100644 index 0000000..a8a6d4a Binary files /dev/null and b/car_spotting/app/database.sqlite differ diff --git a/car_spotting/app/migrations/0001_initial.py b/car_spotting/app/migrations/0001_initial.py new file mode 100644 index 0000000..3dfc853 --- /dev/null +++ b/car_spotting/app/migrations/0001_initial.py @@ -0,0 +1,37 @@ +# Generated by Django 5.1.4 on 2026-03-31 16:15 + +import banjo.models +from django.db import migrations, models + + +class Migration(migrations.Migration): + initial = True + + dependencies = [] + + operations = [ + migrations.CreateModel( + name="SpottingEvent", + fields=[ + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("make", banjo.models.StringField(default="")), + ("model", banjo.models.StringField(default="")), + ("color", banjo.models.StringField(default="")), + ("bodystyle", banjo.models.StringField(default="")), + ("location", banjo.models.StringField(default="")), + ("instances", banjo.models.IntegerField(default=0)), + ("note", banjo.models.StringField(blank=True, default="", null=True)), + ], + options={ + "abstract": False, + }, + ), + ] diff --git a/car_spotting/app/migrations/__init__.py b/car_spotting/app/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/car_spotting/app/models.py b/car_spotting/app/models.py new file mode 100644 index 0000000..3a4db47 --- /dev/null +++ b/car_spotting/app/models.py @@ -0,0 +1,16 @@ +from banjo.models import Model, StringField, IntegerField + + +class SpottingEvent(Model): + make = StringField() + model = StringField() + color = StringField() + bodystyle = StringField() + location = StringField() + instances = IntegerField() + note = StringField(blank=True, null=True) + + def __repr__(self): + rep = self.to_dict() + return rep + diff --git a/car_spotting/app/views.py b/car_spotting/app/views.py new file mode 100644 index 0000000..2581b00 --- /dev/null +++ b/car_spotting/app/views.py @@ -0,0 +1,47 @@ +from banjo.urls import route_get, route_post +from banjo.http import BadRequest, NotFound +from app.models import SpottingEvent + + +@route_get('all', args={}) +def list_events(params): + events = sorted(SpottingEvent.objects.all(), key=lambda event: event.make) + return {'events': [event.to_dict() for event in events]} + +@route_post('new', args={'make': str, 'model': str, 'color': str, 'bodystyle': str, 'location': str, 'note': str, 'instances': int} ) +def create_event(params): + event = SpottingEvent.from_dict(params) + event.save() + return {'event': event.to_dict()} + +@route_get('search', args={'category': str, 'value': str}) +def search_events(params): + validcat = ['id', 'make', 'model', 'color', 'bodystyle', 'location'] + if params['category'] not in validcat: + raise BadRequest('Invalid category: can search by id, make, model, bodystyle, or location') + if params['category'] == 'make': + matches = SpottingEvent.objects.filter(make=params['value']) + elif params['category'] == 'model': + matches = SpottingEvent.objects.filter(model=params['value']) + elif params['category'] == 'bodystyle': + matches = SpottingEvent.objects.filter(bodystyle=params['value']) + elif params['category'] == 'location': + matches = SpottingEvent.objects.filter(location=params['value']) + elif params['category'] == 'color': + matches = SpottingEvent.objects.filter(color=params['value']) + elif params['category'] == 'id': + matches = SpottingEvent.objects.filter(id=int(params['value'])) + if not matches: + raise NotFound("No Event Found (make and model start with capital letters, e.g. Honda Civic)") + return {'events': [event.to_dict() for event in matches]} + +@route_post('addnotes', args={'id': int, 'new_note': str}) +def add_note(params): + try: + event = SpottingEvent.objects.get(id=params['id']) + except: + raise NotFound('Event not found') + event.note = params['new_note'] + event.save() + return {'event': event.to_dict()} + diff --git a/planning.md b/planning.md index b19ea29..b8e55a4 100644 --- a/planning.md +++ b/planning.md @@ -7,13 +7,13 @@ My app is for people who like car spotting, I am my target user. Car spotting is ## 2. What need or problem will your app solve? How do you know this is really a need for your target user? How does the target user currently deal with the problem? -This app will act as a place to store cars I have spotted. It will include make, model, color, body style, city, and country that I saw it in. I will be able to search for a car that I saw by these characteristics. I also want to be able to add a note about the event. +This app will act as a place to store cars I have spotted. It will include make, model, color, body style, location that I saw it in, and amount of times I saw it. I will be able to search for a car that I saw by these characteristics. I also want to be able to add a note about the event. This app is a niche need, and it is for me. I thought of this after going to some carribbean islands and seeing new cars that I have never heard of before. I deal with this problem now by trying to rely on memory, which is not perfect. So, having a place to put these cars would be a great solution. ## 3. How will your app's design meet the need you have identified? -I will have methods to add these car spotting events coded into the app. I will support search by any of the qualities outlined earlier: make, model, color, body style, city, country. I will support adding notes about the spotting event. +I will have methods to add these car spotting events coded into the app. I will support search for car spotting events for: make, model, body style, color, and location. I will support adding notes about the spotting event. ## 4. How could your app possibly cause harm? (For example, could someone get hurt if data leaked or if someone used the app inappropriately?) What steps will you take to ensure that nobody is harmed by your app?