Skip to content

Commit

Permalink
Merge pull request #1 from moevm/hello-world
Browse files Browse the repository at this point in the history
Task 1 complete
  • Loading branch information
u5ele55 authored Sep 22, 2024
2 parents 4f9839d + 6c36116 commit 5a92e6a
Show file tree
Hide file tree
Showing 5 changed files with 156 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.idea
.code
9 changes: 9 additions & 0 deletions hello_world/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
FROM python:3.9-slim

WORKDIR /app

RUN pip install neo4j bcrypt

Check failure on line 5 in hello_world/Dockerfile

View workflow job for this annotation

GitHub Actions / Проверка наличия тега 0.8 и работоспособности docker-compose

DL3013 warning: Pin versions in pip. Instead of `pip install <package>` use `pip install <package>==<version>` or `pip install --requirement <requirements file>`

Check failure on line 5 in hello_world/Dockerfile

View workflow job for this annotation

GitHub Actions / Проверка наличия тега 0.8 и работоспособности docker-compose

DL3042 warning: Avoid use of cache directory with pip. Use `pip install --no-cache-dir <package>`

COPY . /app

CMD ["python", "main.py"]
42 changes: 42 additions & 0 deletions hello_world/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Каталог всех дворов-колодцев СПБ

Задача - составить каталог всех дворов-колодцев в СПБ. Смысл сервиса - дать возможность найти все дворы, а также вести учет персональных достижений (Кто в скольки дворах побывал). Страницы : профиль пользователя, карточка двора, поиск пользователей и дворов, карта.

## Идея

При входе на сайт человек видит карту Санкт-Петербурга, на которой отмечены дворы колодцы. Присутствует поиск по дворам. Аутентифицированный пользователь может выбирать двор на карте и вводить дату его посещения. Если Access токен пользователя отсутствует или не действителен, система будет требовать аутентифицироваться (войти или зарегистрироваться) для отметки двора.

Помимо карты у пользователя будет возможность посмотреть на ТОП пользователей по количеству посещенных дворов. А также зайти в профиль каждого пользователя, где будет доступен список всех посещенных им дворов.

## Инструменты
- Python (FastAPI)
- Neo4j
- JS (без фреймворков)
- HTML
- CSS

Для отображения карты предлагается использовать:
- OpenStreetMap / Google Maps / Яндекс.Карты API
- LeaFlet в случае работы с OpenStreetMap https://github.com/Leaflet/Leaflet

## Описание сущностей и отношений

### Сущность - Пользователь (User)
- id (int)
- email
- name
- password (bcrypt hash)

### Сущность - Двор (Courtyard)
- id (int)
- latitude
- longitude
- address
- name
- description (nullable)

### Отношение - Посещение (Visit)
- id
- date
- courtyard_id
- user_id
24 changes: 24 additions & 0 deletions hello_world/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
version: '3.8'

services:
neo4j:
image: neo4j:latest
environment:
- NEO4J_AUTH=neo4j/password
ports:
- "7474:7474" # Browser
- "7687:7687"
volumes:
- neo4jdata:/data

app:
build: .
depends_on:
- neo4j
environment:
- NEO4J_URI=bolt://neo4j:7687
- NEO4J_USER=neo4j
- NEO4J_PASSWORD=password

volumes:
neo4jdata:
79 changes: 79 additions & 0 deletions hello_world/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import os
from neo4j import GraphDatabase
import bcrypt
from datetime import datetime


def create_user(tx, email, name, password):
hashed_password = bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt())
query = """
CREATE (u:User {email: $email, name: $name, password: $password})
RETURN u
"""
tx.run(query, email=email, name=name, password=hashed_password.decode('utf-8'))


def create_courtyard(tx, latitude, longitude, address, name, description=None):
query = """
CREATE (c:Courtyard {latitude: $latitude, longitude: $longitude, address: $address, name: $name, description: $description})
RETURN c
"""
tx.run(query, latitude=latitude, longitude=longitude, address=address, name=name, description=description)


def create_visit(tx, user_id, courtyard_id, date):
query = """
MATCH (u:User) WHERE ID(u)=$user_id
MATCH (c:Courtyard) WHERE ID(c)=$courtyard_id
CREATE (u)-[:VISIT {date: $date}]->(c)
RETURN u, c
"""
tx.run(query, user_id=user_id, courtyard_id=courtyard_id, date=date)


def get_users(tx):
query = """
MATCH (u:User)
RETURN ID(u) AS id
"""
result = tx.run(query)
return [record["id"] for record in result]


def get_courtyards(tx):
query = """
MATCH (c:Courtyard)
RETURN ID(c) AS id
"""
result = tx.run(query)
return [record["id"] for record in result]


def main():
uri = os.getenv("NEO4J_URI", "bolt://localhost:7687")
user = os.getenv("NEO4J_USER", "neo4j")
password = os.getenv("NEO4J_PASSWORD", "password")

driver = GraphDatabase.driver(uri, auth=(user, password))

with driver.session() as session:
# Создание пользователя
session.execute_write(create_user, "[email protected]", "John Doe", "password123")

users = session.execute_read(get_users)
print("Users from DB:", users)

# Создание двора
session.execute_write(create_courtyard, 55.751244, 37.618423, "123 Main St", "Central Park", "A beautiful park")

courtyards = session.execute_read(get_courtyards)
print("Courtyards from DB:", courtyards)

# Посещение
session.execute_write(create_visit, users[-1], courtyards[-1], datetime.now().strftime("%Y-%m-%d"))

driver.close()


if __name__ == "__main__":
main()

0 comments on commit 5a92e6a

Please sign in to comment.