Skip to content

Commit

Permalink
Update folder structure and add dockerfile
Browse files Browse the repository at this point in the history
  • Loading branch information
eidan66 authored Sep 11, 2024
1 parent b6e1f15 commit fea8a52
Show file tree
Hide file tree
Showing 18 changed files with 327 additions and 181 deletions.
9 changes: 3 additions & 6 deletions .github/workflows/update_schema.yml
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
name: Update OpenAPI Schema

on:
push:
paths:
- 'server/**'
pull_request:
paths:
- 'server/**'
branches-ignore:
- main
branches:
- main

permissions:
contents: write
Expand Down Expand Up @@ -48,4 +45,4 @@ jobs:
git add schema.yml
git commit -m "Force update OpenAPI schema" || echo "No changes to commit"
git push origin HEAD:${{ github.head_ref }}
working-directory: ./server
working-directory: ./server
2 changes: 1 addition & 1 deletion server/.idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 5 additions & 1 deletion server/.idea/server.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

40 changes: 40 additions & 0 deletions server/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#TEMP disabled - because it doesn't work well.

#FROM ubuntu:latest
#LABEL authors="idanlevian"
#
#RUN apt-get update && apt-get install -y \
# python3-pip \
# python3-dev \
# build-essential \
# libpq-dev \
# python3-venv \
# curl \
# && apt-get clean
#
#WORKDIR /code
#
#RUN python3 -m venv /code/venv
#ENV PATH="/code/venv/bin:$PATH"
#
#RUN pip install pipenv
#
#COPY Pipfile Pipfile.lock /code/
#RUN pipenv install --system --deploy
#
#COPY . /code/
#
#EXPOSE 8000
#
#ENV PYTHONDONTWRITEBYTECODE=1
#ENV PYTHONUNBUFFERED=1
#
#COPY /.env /code/.env
#
#SHELL ["/bin/bash", "-c"]
#RUN if [ -f /code/.env ]; then \
# set -a && . /code/.env && set +a; \
# fi
#
#CMD ["pipenv", "run", "gunicorn", "--bind", "0.0.0.0:8000", "pokedexServer.wsgi:application"]
##CMD ["pipenv", "run", "gunicorn", "pokedexServer.wsgi:application"]
2 changes: 2 additions & 0 deletions server/Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ pokebase = "*"
drf_spectacular = "*"
python-decouple = "*"
gunicorn = "*"
djangorestframework = "*"

[dev-packages]
django = "*"

[requires]
python_version = "3.12"
31 changes: 29 additions & 2 deletions server/Pipfile.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

55 changes: 48 additions & 7 deletions server/README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@

# Django Project Setup Guide

This guide provides instructions for setting up and running the Django project on a MacBook.
This guide provides instructions for setting up and running the Django project on a MacBook using either **Pipenv** or **Docker**.

## Prerequisites

- macOS
- Homebrew (for installing Python if not already installed)
- [Docker Desktop](https://www.docker.com/products/docker-desktop) (for running the project with Docker)

## Installation Steps
## Setup Options

You can set up the project using **Pipenv** or **Docker**. Choose the method that best fits your development workflow.

---

## Option 1: Set Up Using Pipenv

### Step 1: Install Python via Homebrew

Expand All @@ -23,6 +30,7 @@ brew install python
This installs Python and `pip`, Python’s package manager.

### Step 2: Install Dependencies and Setup Environment with Pipenv

If pipenv is not already installed, you can install it using pip. This tool helps manage dependencies and virtual environments:

```bash
Expand Down Expand Up @@ -51,25 +59,58 @@ Start the server by running:
python manage.py runserver
```

### Step 5: Run the Django Development Server
The server will start on `http://127.0.0.1:8000/` by default. You can access your Django application by visiting this URL in a web browser.

Start the server by running:
---

## Option 2: Set Up Using Docker (Recommended)

Docker allows you to run the project inside containers, ensuring a consistent development environment without needing to install Python or other dependencies locally.

### Step 1: Install Docker

Download and install Docker Desktop from the [official Docker website](https://www.docker.com/products/docker-desktop).

### Step 2: Build the Docker Image

Navigate to the project directory and run the following command to build the Docker image:

```bash
python manage.py runserver
docker build -t pokedex-server .
```

The server will start on `http://127.0.0.1:8000/` by default. You can access your Django application by visiting this URL in a web browser.
This command will build the Docker image based on the provided `Dockerfile`.

### Step 3: Run the Docker Container

After building the image, run the container using this command:

```bash
docker run -p 8000:8000 pokedex-server
```

This will start the Django server inside the Docker container, and you can access the application at `http://127.0.0.1:8000/`.

### Step 4: Stopping the Docker Container

To stop the Docker container, press `CTRL + C` in the terminal where the container is running.

---

## Additional Configuration

- Ensure that all necessary environment variables are set up correctly for your development environment.
- Ensure your database server is running and accessible if your project requires a database.

For Docker, you can also configure your `docker-compose.yml` file to include a database service.

---

## Troubleshooting

- **Docker Issues:** If you're new to Docker and encounter issues, ensure that Docker Desktop is running and that the ports are not already in use.
- **Environment Variables:** Check that all required environment variables are set.
- **Database Connections:** Verify that the database is running and the connection settings in your Django settings are correct.
- **Dependency Issues:** If you encounter errors related to missing packages, ensure all dependencies are correctly installed according to `requirements.txt`.
- **Dependency Issues:** If you encounter errors related to missing packages, ensure all dependencies are correctly installed using `pipenv install` (for Pipenv) or the Docker image builds successfully.

For more information, refer to the official [Django documentation](https://docs.djangoproject.com/).
14 changes: 13 additions & 1 deletion server/pokedexServer/models/pokemon/PokemonModel.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,16 @@ def __init__(self, id=None, name=None, number=None, types=None, boxBg=None, gif=
self.types = types
self.boxBg = boxBg
self.gif = gif
self.error = error
self.error = error

@property
def padded_id(self):
return f"#{self.id:03d}"

@property
def sprite_url(self):
return f'https://github.com/eidan66/pokemon-api-sprites/blob/master/sprites/pokemon/other/showdown/{self.id}.gif?raw=true'

@property
def color(self):
return self.boxBg
Empty file.
10 changes: 10 additions & 0 deletions server/pokedexServer/serializers/pokemon_detail_serializers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from rest_framework import serializers

class PokemonDetailSerializer(serializers.Serializer):
id = serializers.IntegerField()
name = serializers.CharField(max_length=100)
padded_id = serializers.CharField(max_length=10)
types = serializers.ListField(child=serializers.CharField(max_length=50))
color = serializers.CharField(max_length=50)
sprite_url = serializers.URLField()

Original file line number Diff line number Diff line change
@@ -1,27 +1,5 @@
# serializers.py

from rest_framework import serializers


class PokemonSerializer(serializers.Serializer):
id = serializers.IntegerField()
name = serializers.CharField(max_length=100)
number = serializers.CharField(max_length=50)
types = serializers.ListField(child=serializers.CharField(max_length=50))
boxBg = serializers.CharField(max_length=100)
svg = serializers.URLField()
error = serializers.CharField(max_length=200, required=False)


class PokemonDetailSerializer(serializers.Serializer):
id = serializers.IntegerField()
name = serializers.CharField(max_length=100)
padded_id = serializers.CharField(max_length=10)
types = serializers.ListField(child=serializers.CharField(max_length=50))
color = serializers.CharField(max_length=50)
sprite_url = serializers.URLField()


class AbilitySerializer(serializers.Serializer):
name = serializers.CharField()
isHidden = serializers.BooleanField()
Expand Down
11 changes: 11 additions & 0 deletions server/pokedexServer/serializers/pokemon_list_serializers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from rest_framework import serializers

class PokemonListSerializer(serializers.Serializer):
id = serializers.IntegerField()
name = serializers.CharField(max_length=100)
number = serializers.CharField(max_length=50)
types = serializers.ListField(child=serializers.CharField(max_length=50))
boxBg = serializers.CharField(max_length=100)
svg = serializers.URLField()
error = serializers.CharField(max_length=200, required=False)

22 changes: 3 additions & 19 deletions server/pokedexServer/urls.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,10 @@
"""
URL configuration for pokedexServer project.
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/5.1/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: path('', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path
from drf_spectacular.views import SpectacularAPIView, SpectacularRedocView, SpectacularSwaggerView
from .pokemons import PokemonListView, PokemonDetailView, PokemonInfoView

from . import pokemons

from pokedexServer.views.pokemons.list_view import PokemonListView
from pokedexServer.views.pokemons.detail_view import PokemonDetailView
from pokedexServer.views.pokemons.info_view import PokemonInfoView

urlpatterns = [
path('admin/', admin.site.urls),
Expand Down
Empty file.
48 changes: 48 additions & 0 deletions server/pokedexServer/views/pokemons/detail_view.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import pokebase as pb

from drf_spectacular.utils import extend_schema
from rest_framework.response import Response
from rest_framework import status
from rest_framework.views import APIView

import logging

logger = logging.getLogger(__name__)

from pokedexServer.models.pokemon.Colors import Colors
from pokedexServer.models.pokemon.PokemonModel import PokemonModel
from pokedexServer.models.pokemon.PokemonTypeModel import PokemonTypeModel
from pokedexServer.serializers.pokemon_detail_serializers import PokemonDetailSerializer
from pokedexServer.utils import pad


class PokemonDetailView(APIView):
serializer_class = PokemonDetailSerializer

@extend_schema(operation_id="pokemon_detail", summary="Retrieve a Pokémon by ID")
def get(self, request, id):
pokemonModel = self.fetchAndMapPokemon(id)
if pokemonModel.error: # Now correctly checking for an error
return Response({"error": pokemonModel.error}, status=status.HTTP_404_NOT_FOUND)
serializer = self.serializer_class(pokemonModel)
return Response(serializer.data, status=status.HTTP_200_OK)

def fetchAndMapPokemon(self, id):
try:
pokeAPIPokemon = pb.pokemon(id)
if not pokeAPIPokemon:
return PokemonModel(error="Pokemon not found")
return PokemonModel(
id=pokeAPIPokemon.id,
name=pokeAPIPokemon.name,
number=pad(pokeAPIPokemon.id),
types=[type.type.name for type in pokeAPIPokemon.types],
boxBg=Colors[PokemonTypeModel(pokeAPIPokemon.types[0].type.name).value].value[0],
gif=f'https://github.com/eidan66/pokemon-api-sprites/blob/master/sprites/pokemon/other/showdown/{pokeAPIPokemon.id}.gif?raw=true'
)
except Exception as e:
logger.error(f"Error fetching Pokemon: {e}")
return PokemonModel(error="Error fetching Pokemon")

def mapToPokemonTypeModel(self, pokeAPIPokemonType):
return PokemonTypeModel(pokeAPIPokemonType.type.name)
Loading

0 comments on commit fea8a52

Please sign in to comment.