Bygg · Django
Generer try-on-bilder fra en Django-worker
I én setning
En Django-integrasjon lagrer én rad per jobb, sender inn fra en Celery-oppgave, poller hvert 3. sekund til statusen er completed, og laster deretter ned filen til din egen lagringsplass.
- Credits: 5 credits ved 2K · 6 credits ved 4K
- Typisk tidsbruk: 1.5–4 min
- Prosessering: asynkron, polling
Hvert tall på denne siden er hentet fra dokumentasjonen for Photta-API-et · verifisert
En modell som speiler jobben, en Celery-task som sender inn og poller, og lagring som beholder filen etter at leverings-URL-en er borte.
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"]Slik fungerer det
Én rad, én oppgave, én fil
Modeller jobben, send inn fra en oppgave, poll med backoff, lagre filen, eksponer statusen.
Trinn 1
Modeller jobben
Én rad per generering: produktet, genererings-id-en, statusen og output-URL-en. Raden er det visningene dine leser; API-et er det workeren leser.
Trinn 2
Skaff en Photta-API-nøkkel
Les den fra miljøet i innstillingene, aldri fra databasen, og bruk en separat nøkkel per miljø slik at en lekkasje i staging ikke kan bruke opp produksjons-credits.
Trinn 3
Send inn i en oppgave
Visninger bør returnere umiddelbart. Celery-oppgaven poster jobben med POST og skriver den returnerte id-en til raden.
Trinn 4
Poll med backoff
Poll hvert 3. sekund til statusen er completed eller failed. Ved en 429, vent antall sekunder angitt i Retry-After i stedet for å prøve igjen med en gang.
Trinn 5
Lagre filen
Last ned det ferdige bildet til din egen lagringsplass. URL-en leverer én jobb; bucketen din er det som server produktsiden i årevis.
Trinn 6
Eksponer statusen
Frontend-en din poller raden din, ikke Photta-API-et. Det holder nøkkelen på serveren og lar deg vise fremdrift akkurat slik du vil.
Modell, oppgave, feil, lagring
Innsending-og-polling og feilhåndteringen er gjengitt fra API-dokumentasjonen.
# 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"])Spørsmål utviklere stiller
Spørsmål Django-utviklere stiller
Hvorfor en worker i stedet for en view?
En generering tar lengre tid enn en forespørsel bør ta. En worker overlever en lukket nettleserfane, en deploy og en tidsavbruddsfeil; en view overlever ingen av delene.
Hvor lenge bør oppgaven polle?
Lenge nok til å dekke endepunktets dokumenterte latenstid, med et øvre tak. Eksemplene her stopper etter et fast antall forsøk i stedet for å polle evig.
Kan jeg bruke asynkron Django i stedet for Celery?
Ja — kallene er ren HTTP. Det som betyr noe, er at arbeidet lever lenger enn forespørselen, uansett hvordan du organiserer det.
Hvordan tester jeg uten å bruke credits?
Ta opp én reell respons og spill den av i testene. Ressursendepunktene og detaljfotoanalysen er gratis, så nøkkel- og tilkoblingssjekker koster ingenting.
Kan én nøkkel betjene alle miljøer?
Det kan den, men alle nøkler trekker fra samme saldo, så en løkke i staging tømmer produksjons-credits. Separate nøkler gjør skaden synlig og enkel å stoppe.
Relaterte sider
Relatert lesing
Funksjoner
Virtuell try-on API for klær
REST API som plasserer klær på AI-mannequiner. Asynkront, 1,5–4 minutters generering, 5 credits i 2K, 6 i 4K. Eksempler for cURL, Node.js og Python.
LesHurtigstart
Første Photta-bilde på under fem minutter.
Registrer deg, generer en API-nøkkel, kjør ditt første cURL-kall, utfør polling til det er fullført, lagre resultatet. Fem trinn, dokumentert fra start til slutt.
LesSpråk
Python walkthrough
LesErrors
Les
Hvert tall på denne siden er hentet fra dokumentasjonen for Photta-API-et · verifisert
En worker, en rad og en fil
Innsending-og-polling på denne siden er gjengitt fra API-dokumentasjonen.