私はまだセロリの感触を自分自身で得ていると言って、これを前置きさせてください。そうは言っても、私はこれにどのように取り組むかについて一般的な傾向があり、他の誰も応答していないので、それを試してみます。
あなたが書いたものに基づいて、比較的単純な(私は最適化されていないと思いますが)解決策は、ドキュメントからのブログコメントスパムタスクの例の広い輪郭に従うことです。
app.models.py
class Address(models.Model):
GEOCODE_STATUS_CHOICES = (
('pr', 'pre-check'),
('su', 'success'),
('fl', 'failed'),
)
address = models.TextField()
...
geocode = models.TextField()
geocode_status = models.CharField(max_length=2,
choices=GEOCODE_STATUS_CHOICES,
default='pr')
class AppUser(models.Model):
name = models.CharField(max_length=100)
...
address = models.ForeignKey(Address)
app.tasks.py
from celery import task
from app.models import Address, AppUser
from some_module import geocode_function #assuming this returns a string
@task()
def get_geocode(appuser_pk):
user = AppUser.objects.get(pk=appuser_pk)
address = user.address
try:
result = geocode_function(address.address)
address.geocode = result
address.geocode_status = 'su' #set address object as successful
address.save()
return address.geocode #this is optional -- your task doesn't have to return anything
on the other hand, you could also choose to decouple the geo-
code function from the database update for the object instance.
Also, if you're thinking about chaining tasks together, you
might think about if it's advantageous to pass a parameter as
an input or partial input into the child task.
except Exception as e:
address.geocode_status = 'fl' #address object fails
address.save()
#do something_else()
raise #re-raise the error, in case you want to trigger retries, etc
app.views.py
from app.tasks import *
from app.models import *
from django.shortcuts import get_object_or_404
def geocode_for_address(request, app_user_pk):
app_user = get_object_or_404(AppUser, pk=app_user_pk)
...etc.etc. --- **somewhere calling your tasks with appropriate args/kwargs
これは、上記で概説した最小要件を満たしていると思います。ビューをどの程度正確にトリガーしたいかがわからないため、意図的にビューを未開発のままにしました。住所をジオコーディングできない場合にも、ある種のユーザー通知が必要になる可能性があります(「データベースのフィールドを更新してユーザーに通知したい」)。この要件の詳細について詳しく知らなくても、htmlテンプレート(instance.attribute値がXの場合、テンプレートにqを表示)またはdjango.signals(セットアップuser.address.geocode_statusが失敗に切り替わったときのシグナル(たとえば、ユーザーにメールで通知するなど)。
上記のコードへのコメントで、上記のget_geocodeタスクのコンポーネント部分をデカップリングおよびチェーンする可能性について言及しました。カスタムエラーハンドラータスクを記述し、link_errorパラメーター(たとえば、add.apply_async((2、2)、link_error = error_handler.s()、ここで、error_handlerはapp.tasks.pyでタスクとして定義されています。また、メインタスク(get_geocode)を介してエラーを処理するか、リンクされたエラーハンドラーを介してエラーを処理するかを選択する場合は、もっと具体的にしたいと思います。さまざまな種類のエラーを処理する方法について(たとえば、アドレスデータが正しくフォーマットされていない場合とは異なる接続エラーで何かを行う)。
より良いアプローチがあるのではないかと思います。タスクを連鎖させたり、グループやコードを使用したりすることで、いかに独創性が得られるかを理解し始めたばかりです。これが少なくともいくつかの可能性について考えさせるのに役立つことを願っています。ベストプラクティスを推奨するのは他の人に任せます。