Bangun · Django
Render gambar try-on dari worker Django
Ringkasan singkat
Integrasi Django menyimpan satu baris per job, melakukan submit dari task Celery, melakukan polling setiap 3 detik hingga statusnya completed, lalu mengunduh file ke penyimpanan Anda sendiri.
- Credits: 5 credits pada 2K · 6 credits pada 4K
- Waktu umum: 1.5–4 min
- Pemrosesan: async, polling
Setiap angka di halaman ini bersumber dari dokumentasi API Photta · diperiksa
Model yang mencerminkan job, task Celery yang mengirimkan dan melakukan polling, serta penyimpanan yang mempertahankan file setelah delivery URL kedaluwarsa.
RESPONSE=$(curl -s -X POST https://api.photta.app/api/v1/tryon/apparel \
-H "Authorization: Bearer $PHOTTA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"product_type": "top",
"product_images": [
"https://cdn.yourstore.com/products/shirt-front.jpg"
],
"product_back_image": "https://cdn.yourstore.com/products/shirt-back.jpg",
"product_category": "t_shirt",
"mannequin_id": "mnk_f3a9b1",
"pose_id": "pose_c2d4e5",
"background": "https://cdn.yourstore.com/backgrounds/studio-loft.jpg",
"lock_background": true,
"resolution": "2K",
"aspect_ratio": "3:4",
"body_size": "M",
"expression": "neutral",
"user_instruction": "Keep the collar pattern crisp and centered."
}')
ID=$(echo "$RESPONSE" | jq -r '.data.id')const res = await fetch("https://api.photta.app/api/v1/tryon/apparel", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.PHOTTA_API_KEY}`, "Content-Type": "application/json" },
body: JSON.stringify({
"product_type": "top",
"product_images": [
"https://cdn.yourstore.com/products/shirt-front.jpg"
],
"product_back_image": "https://cdn.yourstore.com/products/shirt-back.jpg",
"product_category": "t_shirt",
"mannequin_id": "mnk_f3a9b1",
"pose_id": "pose_c2d4e5",
"background": "https://cdn.yourstore.com/backgrounds/studio-loft.jpg",
"lock_background": true,
"resolution": "2K",
"aspect_ratio": "3:4",
"body_size": "M",
"expression": "neutral",
"user_instruction": "Keep the collar pattern crisp and centered."
}),
});
const { data } = await res.json(); // data.id, data.statusimport os, requests
res = requests.post(
"https://api.photta.app/api/v1/tryon/apparel",
headers={"Authorization": f"Bearer {os.environ['PHOTTA_API_KEY']}"},
json={
"product_type": "top",
"product_images": [
"https://cdn.yourstore.com/products/shirt-front.jpg"
],
"product_back_image": "https://cdn.yourstore.com/products/shirt-back.jpg",
"product_category": "t_shirt",
"mannequin_id": "mnk_f3a9b1",
"pose_id": "pose_c2d4e5",
"background": "https://cdn.yourstore.com/backgrounds/studio-loft.jpg",
"lock_background": True,
"resolution": "2K",
"aspect_ratio": "3:4",
"body_size": "M",
"expression": "neutral",
"user_instruction": "Keep the collar pattern crisp and centered."
},
)
data = res.json()["data"] # data["id"], data["status"]Cara kerja
Satu baris, satu task, satu file
Modelkan job, submit dari task, lakukan polling dengan backoff, simpan file secara persisten, ekspos statusnya.
Langkah 1
Modelkan job
Satu baris per pembuatan: produk, id pembuatan, status, dan URL output. Baris tersebut dibaca oleh views Anda; API dibaca oleh worker.
Langkah 2
Dapatkan API key Photta
Baca dari environment di settings, jangan pernah dari database, dan gunakan key terpisah per environment agar kebocoran di staging tidak menghabiskan credits produksi.
Langkah 3
Submit dalam sebuah task
Views harus langsung mengembalikan respons. Task Celery melakukan POST job dan menulis id yang dikembalikan ke dalam baris.
Langkah 4
Lakukan polling dengan backoff
Lakukan polling setiap 3 detik hingga statusnya completed atau failed. Pada status 429, tunggu durasi detik Retry-After alih-alih langsung mencoba ulang.
Langkah 5
Simpan file secara persisten
Unduh gambar yang sudah selesai ke penyimpanan Anda sendiri. URL tersebut mengirimkan satu job; bucket Anda yang akan menayangkannya di halaman produk selama bertahun-tahun.
Langkah 6
Ekspos statusnya
Front-end Anda melakukan polling ke baris database Anda, bukan ke API Photta. Ini menjaga key tetap aman di server dan memungkinkan Anda menampilkan progres sesuai keinginan.
Model, task, error, penyimpanan
Alur submit-and-poll dan penanganan error dirender dari dokumentasi API.
# store/models.py
from django.db import models
class TryOn(models.Model):
product = models.ForeignKey("Product", on_delete=models.CASCADE)
generation_id = models.CharField(max_length=64, db_index=True)
status = models.CharField(max_length=16, default="processing")
output_url = models.URLField(blank=True)
created_at = models.DateTimeField(auto_now_add=True)# store/tasks.py
from celery import shared_task
@shared_task(bind=True, max_retries=3)
def run_try_on(self, try_on_id):
import os, requests
res = requests.post(
"https://api.photta.app/api/v1/tryon/apparel",
headers={"Authorization": f"Bearer {os.environ['PHOTTA_API_KEY']}"},
json={
"product_type": "top",
"product_images": [
"https://cdn.yourstore.com/products/shirt-front.jpg"
],
"product_back_image": "https://cdn.yourstore.com/products/shirt-back.jpg",
"product_category": "t_shirt",
"mannequin_id": "mnk_f3a9b1",
"pose_id": "pose_c2d4e5",
"background": "https://cdn.yourstore.com/backgrounds/studio-loft.jpg",
"lock_background": True,
"resolution": "2K",
"aspect_ratio": "3:4",
"body_size": "M",
"expression": "neutral",
"user_instruction": "Keep the collar pattern crisp and centered."
},
)
data = res.json()["data"] # data["id"], data["status"]
import time
def wait_for(job_id):
for _ in range(120):
res = requests.get(f"https://api.photta.app/api/v1/tryon/apparel/{job_id}", headers={"Authorization": f"Bearer {os.environ['PHOTTA_API_KEY']}"})
data = res.json()["data"]
if data["status"] == "completed":
return data["output_url"]
if data["status"] == "failed":
raise RuntimeError(data.get("error_message", "generation failed"))
time.sleep(3)
raise TimeoutError("timed out after 6 minutes")try:
photta("POST", "/tryon/apparel", json={
"product_type": "top",
"product_images": [
"https://cdn.yourstore.com/products/shirt-front.jpg"
],
"product_back_image": "https://cdn.yourstore.com/products/shirt-back.jpg",
"product_category": "t_shirt",
"mannequin_id": "mnk_f3a9b1",
"pose_id": "pose_c2d4e5",
"background": "https://cdn.yourstore.com/backgrounds/studio-loft.jpg",
"lock_background": True,
"resolution": "2K",
"aspect_ratio": "3:4",
"body_size": "M",
"expression": "neutral",
"user_instruction": "Keep the collar pattern crisp and centered."
})
except PhottaError as e:
if e.status == 402:
print("insufficient_credits_error: top up before retrying")
elif e.status == 429:
time.sleep(int(e.retry_after or 30))
else:
raise# store/tasks.py — the output URL delivers one job; your storage keeps it
import requests
from django.core.files.base import ContentFile
def persist(try_on, output_url):
body = requests.get(output_url, timeout=60).content
try_on.product.gallery.save(f"{try_on.generation_id}.jpg", ContentFile(body))
try_on.status, try_on.output_url = "completed", output_url
try_on.save(update_fields=["status", "output_url"])Pertanyaan umum developer
Pertanyaan yang sering diajukan developer Django
Mengapa menggunakan worker alih-alih view?
Proses pembuatan memakan waktu lebih lama dari batas waktu request yang ideal. Worker tetap bertahan meski tab browser ditutup, ada deploy, atau terjadi timeout; view tidak dapat bertahan dari kondisi tersebut.
Berapa lama task harus melakukan polling?
Cukup lama sesuai latensi endpoint yang terdokumentasi, dengan batas maksimal. Contoh di sini berhenti setelah jumlah percobaan tertentu alih-alih melakukan polling tanpa henti.
Bisakah saya menggunakan Django async alih-alih Celery?
Bisa — pemanggilannya menggunakan HTTP biasa. Yang terpenting adalah proses kerja tetap berjalan melampaui siklus request, apa pun cara yang Anda gunakan.
Bagaimana cara menguji tanpa menghabiskan credits?
Rekam satu respons nyata dan putar ulang dalam pengujian. Endpoint resource dan analisis foto detail bersifat gratis, sehingga pemeriksaan key dan konektivitas tidak memerlukan biaya.
Bisakah satu key digunakan untuk semua environment?
Bisa, tetapi setiap key memotong saldo yang sama, sehingga loop di staging dapat menguras credits produksi. Key yang terpisah membuat dampak lebih terlihat dan mudah dihentikan.
Halaman terkait
Bacaan terkait
Kapabilitas
Virtual try-on API untuk pakaian
REST API yang memakaikan pakaian pada manekin AI. Asinkron, waktu generasi 1.5–4 menit, 5 credits pada 2K, 6 pada 4K. Contoh cURL, Node.js, dan Python.
BacaQuickstart
Gambar Photta pertama dalam waktu kurang dari lima menit.
Daftar, buat API key, jalankan pemanggilan cURL pertama Anda, lakukan polling hingga selesai, simpan hasilnya. Lima langkah, terdokumentasi end-to-end.
BacaBahasa
Python walkthrough
BacaErrors
Baca
Setiap angka di halaman ini bersumber dari dokumentasi API Photta · diperiksa
Sebuah worker, satu baris, dan satu file
Alur submit-and-poll pada halaman ini dirender dari dokumentasi API.