Easy-to-manage touch screens
무료 오픈소스 터치스크린으로 USB 설정 가이드, 드래그‑드롭 편집기, 로컬 제어를 제공하며 Home Assistant용으로 제작되었습니다
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
A recipe sharing web application for home cooks — publish and save recipes,
rate and review them, and generate meal plans from what you've saved.
Course project, Group 4 (AM5). Django + DRF backend, MySQL database, with a
Next.js frontend to follow.
Full project spec — roles, features, ERD, and team split — lives in
CLAUDE.md. Read that before making changes.
Do these in order. Steps 4 and 6 are the ones people skip.
Activate it — this differs by shell, and you need it active in every new
terminal:
Your prompt should now start with (.venv).README 전문 보기 ↗A recipe sharing web application for home cooks — publish and save recipes, rate and review them, and generate meal plans from what you've saved.
Course project, Group 4 (AM5). Django + DRF backend, MySQL database, with a Next.js frontend to follow.
Full project spec — roles, features, ERD, and team split — lives in
CLAUDE.md. Read that before making changes.
| Version | Notes | |
|---|---|---|
| Python | 3.12+ | developed on 3.14 |
| MySQL | 8.0+ | MySQL Workbench is fine for creating the database |
| Git | any |
Do these in order. Steps 4 and 6 are the ones people skip.
git clone https://github.com/<your-org>/FlavorShare-Home-Cooking.git
cd FlavorShare-Home-Cooking
python -m venv .venv
Activate it — this differs by shell, and you need it active in every new terminal:
# Windows PowerShell
.\.venv\Scripts\Activate.ps1
# Git Bash / macOS / Linux
source .venv/Scripts/activate # Windows
source .venv/bin/activate # macOS / Linux
Your prompt should now start with (.venv).
pip install -r requirements.txt
If mysqlclient fails to build here, see Troubleshooting.
The app does not create the database for you — only the tables inside it.
In MySQL Workbench (or the mysql CLI), run:
CREATE DATABASE IF NOT EXISTS flavorshare_db
CHARACTER SET utf8mb4
COLLATE utf8mb4_unicode_ci;
-- A dedicated account, so nobody has to put their root password in a file.
-- Using root locally works too; just match it in DATABASE_URL below.
CREATE USER IF NOT EXISTS 'flavorshare'@'localhost' IDENTIFIED BY 'choose-a-password';
GRANT ALL PRIVILEGES ON flavorshare_db.* TO 'flavorshare'@'localhost';
-- Django builds a separate database when running tests and drops it after.
GRANT ALL PRIVILEGES ON test_flavorshare_db.* TO 'flavorshare'@'localhost';
FLUSH PRIVILEGES;
The
CREATE TABLEstatements inbackend/flavorshare.sqlare reference documentation for the ERD. Don't run them — Django creates the real tables from the models in step 6.
Create a file at backend/.env — by hand, not by copying a template. No
.env file of any kind belongs in this repository, so there is nothing to
copy from; .gitignore blocks the whole .env* family on purpose.
| Variable | Required | Example | What it does |
|---|---|---|---|
DATABASE_URL | yes | mysql://flavorshare:[email protected]:3306/flavorshare_db | Points Django at MySQL. Omit it and Django silently falls back to a local SQLite file — the usual reason your tables look empty. |
DB_SSL_CA_PATH | production only | /etc/secrets/tidb-ca.pem | Path to a CA certificate, required to connect to TiDB Cloud's Public Endpoint in production (Render). Leave it unset locally — local MySQL and SQLite need no certificate, and this variable being absent is what keeps them working exactly as they do today. On Render, point it at wherever the Secret Files feature places the CA certificate you download from the TiDB Cloud console. |
SECRET_KEY | yes | generate one, see below | Signs sessions and JWTs. Never share or reuse one. |
DEBUG | no | True | True locally, False in production. |
ALLOWED_HOSTS | no | localhost,127.0.0.1 | Comma-separated. Add your Render hostname once deployed. |
CORS_ALLOWED_ORIGINS | no | http://localhost:3000,http://127.0.0.1:3000 | Origins allowed to call this API. Add the Vercel URL once the frontend ships. |
Testing from another device on your Wi-Fi (a phone, or this laptop's own
LAN address instead of localhost)? Both of the above need your machine's
LAN IP added too, e.g. ipconfig/ifconfig says 192.168.1.23:
ALLOWED_HOSTS=localhost,127.0.0.1,192.168.1.23
CORS_ALLOWED_ORIGINS=http://localhost:3000,http://127.0.0.1:3000,http://192.168.1.23:3000
and run the backend bound to every interface, not just loopback - see step 9.
Without this, next dev's printed "Network" URL loads the page fine (Next
already binds every interface by default) but every API call from it fails,
since Django never even hears the request.
| CLOUDINARY_CLOUD_NAME | for uploads | dxxxxxxxx | Cloudinary account to upload recipe photos to. |
| CLOUDINARY_API_KEY | for uploads | 123456789012345 | Public half of the Cloudinary credentials. |
| CLOUDINARY_API_SECRET | for uploads | from your dashboard | Secret half. Server-side only — never put this in the frontend. |
| BREVO_API_KEY | for signup & reset | xkeysib-xxxxxxxx | Sends verification and password-reset codes. Server-side only. |
| BREVO_FROM_EMAIL | for signup & reset | FlavorShare <[email protected]> | The From address. Must be a real mailbox you control — see below. |
| THEMEALDB_API_KEY | no | 1 | Used only by python manage.py import_themealdb, which seeds the catalogue from TheMealDB. Defaults to 1, TheMealDB's own free/test key — no signup needed unless it starts throttling. |
The three CLOUDINARY_* keys are needed only for image uploads. Leave them
out and everything else runs; POST /api/recipes/images/upload/ answers
503 with a message saying they are missing. Find all three on the Cloudinary
dashboard at https://console.cloudinary.com under Account Details — the
free tier is enough for this project.
The two BREVO_* keys work the same way: leave them out and everything else
runs, but POST /api/accounts/register/ and the password-reset request answer
503 saying which one is missing. Since an account is only created once its
email is verified, signup cannot complete without them — so you need both to
register a user through the API at all. Get a key at https://brevo.com under
SMTP & API → API Keys; the free tier allows 300 emails a day and asks for no
card.
BREVO_FROM_EMAIL takes either [email protected] or
FlavorShare <[email protected]> — the code splits the two forms apart, so use
whichever reads better.
It has to be a real mailbox you control. Without a verified sending domain,
Brevo only accepts a From address it can tie to your account, so an invented one
like [email protected] is rejected. Use the address you signed up with,
or add another under Senders and click the confirmation link Brevo emails
you.
Mail sent this way reaches any recipient, which is why Brevo replaced Resend here — Resend's unverified sandbox sender could only deliver to the account owner's own inbox, so nobody else could ever receive a code. The tradeoff is that mail from an unverified domain is likelier to land in spam, so check the spam folder before assuming something is broken.
THEMEALDB_API_KEY needs no setup at all — leave it out and the default
still works. Run python manage.py import_themealdb (optionally with
--limit N or --category "Vegetarian") to pull public recipes in as
ordinary published rows, owned by a service account so they show up credited
rather than authorless. Most of the time you want seed_demo_data instead
(see step 8 below) — it runs this for you and adds the ratings/reviews and
featured picks that make the homepage worth looking at.
Nutrition info (Feature 9) is deferred — there's no page or endpoint for it right now. Three providers were tried and dropped: Edamam's nutrition API has no free tier at all (only its unrelated Meal Planner API does), and CalorieNinjas — later folded into API Ninjas — locks calories and protein behind a paid plan on its free tier, which defeats the point. Worth knowing before re-attempting either.
Generate your own SECRET_KEY:
python -c "from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())"
So a minimal backend/.env looks like:
DATABASE_URL=mysql://flavorshare:[email protected]:3306/flavorshare_db
SECRET_KEY=paste-your-generated-key-here
# Only needed if you are working on image uploads
CLOUDINARY_CLOUD_NAME=your-cloud-name
CLOUDINARY_API_KEY=your-api-key
CLOUDINARY_API_SECRET=your-api-secret
# Needed to register a user at all - signup sends a verification code
BREVO_API_KEY=your-brevo-key
BREVO_FROM_EMAIL=FlavorShare <[email protected]>
The three optional keys have working defaults in settings.py; set them only
when you need to override one.
Create frontend/.env.local the same way — by hand, and it is gitignored too.
| Variable | Required | Example | What it does |
|---|---|---|---|
NEXT_PUBLIC_API_BASE_URL | no locally, yes when deployed | http://127.0.0.1:8000/api | Where the browser sends every API call: login, signup, and everything under recipes. Note the value includes /api — callers pass /token/ and /recipes/, not /api/token/. |
Locally you can skip it: in the browser, lib/api.ts falls back to asking
whatever host actually served the page, on port 8000 - localhost:3000
asks localhost:8000, and next dev's Network URL asks that same LAN
address, which is what makes testing from a phone work without setting
anything here. (Server-side rendering has no such host to read, so it
always falls back to 127.0.0.1:8000/api, which is correct since Next's
server and Django always run on the same machine.)
Deploying is where this bites. Next inlines every NEXT_PUBLIC_* variable
into the JavaScript bundle at build time, not at runtime. So on Vercel it
has to be set in the project's environment variables before the build runs —
add it and redeploy, rather than adding it to a build that already finished.
Miss this and the deployed site asks 127.0.0.1:8000 for its data, which is the
visitor's own machine: every request fails, with nothing in the UI pointing at
the cause. It is also the reason the value cannot be changed without rebuilding.
The NEXT_PUBLIC_ prefix is required — Next only exposes variables carrying it
to browser code. Never put a secret behind that prefix; anything with it is
readable by anyone who opens the page. The Cloudinary and Brevo keys above stay
server-side for exactly that reason.
python backend/manage.py migrate
Run this again every time you pull. New models and new third-party apps both arrive as migrations, and skipping it produces confusing "table doesn't exist" errors at runtime rather than at startup.
python backend/manage.py createsuperuser
Superusers count as Admins in this project, so this account can reach
admin-only endpoints and the Django admin panel at /admin/.
The homepage's Trending and Featured Recipes sections, and the Explore page, all read real published recipes - a fresh database has none, so those sections show up empty or missing entirely (Featured Recipes hides itself outright when nothing is featured).
python backend/manage.py seed_demo_data
One command does both steps: it imports the TheMealDB catalogue for you
if you have not already (same as running import_themealdb yourself - see
the THEMEALDB_API_KEY note above), then adds five demo reviewer
accounts, a spread of ratings and reviews across half the imported
recipes, and features two of them. This is what makes the homepage and
Explore page look like a used app instead of an empty one.
Safe to run more than once - it will not create duplicate ratings or reviews. Keyed by TheMealDB's own recipe id rather than your database's local one, so everyone on the team gets the same recipes rated and featured, even though the local id each recipe ends up with will differ machine to machine.
python backend/manage.py runserver
The API is at http://127.0.0.1:8000/ and the Django admin at http://127.0.0.1:8000/admin/.
Testing from another device on the same Wi-Fi (see the ALLOWED_HOSTS/
CORS_ALLOWED_ORIGINS note in step 5)? The bare command above only binds
loopback - nothing outside this machine can reach it. Bind every interface
instead:
python backend/manage.py runserver 0.0.0.0:8000
Run these from inside backend/, not from the project root:
cd backend
python manage.py test # everything
python manage.py test accounts # one app
Test discovery starts from the current directory, so python backend/manage.py test from the project root finds zero tests and still
prints OK — a silent false pass. Naming an app
(python backend/manage.py test accounts) works from anywhere; only the
bare form needs the cd.
Tests build and drop their own test_flavorshare_db; your real data is never
touched. If this fails with a permissions error, revisit the second GRANT
in step 4.
Everything below is live. Recipes, social, meal plans, and dashboard routes are still being built by Persons 2–5.
Send the access token as a header: Authorization: Bearer <access token>.
| Method | Endpoint | Access | Body | Returns |
|---|---|---|---|---|
POST | /api/accounts/register/ | anyone | username, email, password, dietary_preferences (optional) | 201 + the new profile |
POST | /api/token/ | anyone | username, password | 200 + access and refresh tokens |
POST | /api/token/refresh/ | anyone | refresh | 200 + a new access and a new refresh |
POST | /api/token/verify/ | anyone | token | 200 if valid, 401 if not |
POST | /api/accounts/logout/ | signed in | refresh | 204, no body |
GET | /api/accounts/me/ | signed in | — | 200 + the caller's own profile |
PATCH | /api/accounts/me/ | signed in | any of username, email, dietary_preferences | 200 + the updated profile |
POST | /api/accounts/password/ | signed in | current_password, new_password | 204, no body |
Three things that will otherwise cost you an afternoon:
/api/token/refresh/ returns a new refresh
token and immediately invalidates the one you sent. Store the new one — reusing
the old one returns 401.role is read-only. Sending it to /register/ or PATCH /me/ does
nothing; every new account is registered. Promotion to admin is an
Admin-only action.Requires an account with role = admin (or a superuser). Anything else gets
403.
| Method | Endpoint | Body | Returns |
|---|---|---|---|
GET | /api/accounts/users/ | — | 200 + a paginated list of accounts |
GET | /api/accounts/users/<id>/ | — | 200 + one account |
PATCH | /api/accounts/users/<id>/ | role and/or is_active | 200 + the updated account |
DELETE | /api/accounts/users/<id>/ | — | 204, no body |
List supports ?search= (username, email), ?role=, ?is_active=, and
?ordering= (username, created_at, role; prefix with - to reverse).
DELETE deactivates — it does not delete. The row stays, is_active
goes False, and the account's recipes and reviews survive. Undo with
PATCH {"is_active": true}. Deactivating also revokes that account's
refresh tokens, so an existing session can't outlive it.role and is_active. Username, email, and
dietary preferences stay read-only here, so moderation can't rewrite
someone's profile.400. Another admin
has to do it — otherwise the last admin could lock everyone out.POST. Accounts are only created by signing up.pip install fails building mysqlclient (Windows).
It compiles against MySQL's C client. Either install the
MySQL Connector/C and the
"Desktop development with C++" workload from the Visual Studio Build Tools,
or install a prebuilt wheel:
pip install mysqlclient --only-binary :all:
django.db.utils.OperationalError: (1049, "Unknown database 'flavorshare_db'")
Step 4 wasn't run, or DATABASE_URL names a different database.
Access denied for user ...
The credentials in backend/.env don't match the MySQL user from step 4.
Table 'flavorshare_db.<something>' doesn't exist
You pulled new code without migrating. Run python backend/manage.py migrate.
Changes to a model do nothing.
Editing models.py doesn't touch the database. Run
python backend/manage.py makemigrations, then migrate.
Expired refresh tokens. Every login and refresh records a row so tokens can be revoked. Once a token has expired it's rejected on age anyway, so the row is dead weight — clear them out occasionally:
python backend/manage.py flushexpiredtokens
backend/
├── backend/ # settings and the main URL router
├── accounts/ # User model, auth, shared permission classes
├── recipes/ # Recipe, Ingredient, Step, Image
├── social/ # Rating, Comment, Tag, SavedRecipe
├── meal_plans/ # MealPlan, MealPlanEntry, NutritionInfo
└── dashboard/ # Activity, admin dashboard, moderation
Every app owns its own models.py, serializers.py, views.py, and
urls.py. Shared permission classes live in accounts/permissions.py —
import from there rather than writing your own role checks.