Итак, вы хотите написать характеристику, которая будет выполнять проверку, чтобы увидеть, была ли модель обновлена с момента получения текущей, и отбросить что-то, что вы можете зацепить, чтобы уведомить пользователя? Я хотел бы изучить создание базовой модели, которую расширяют все ваши модели, и использование событий модели в этой базовой модели. Возможно, вам даже не понадобится черта, если у вас есть все модели, расширяющие базовую модель. См. Ниже пример метода события модели:
protected static function boot(){
parent::boot();
static::saving(function($thisModel){
$changes = Model::where('version', $thisModel->version)
->where('id', $thisModel->id)->first()
/** if changes->version matches this one, good, if not, set some
* property on the model that can be checked.
*/
}
}
Это произойдет , когда модель будет сохранена, и если вы return false;
окажетесь в любой точке метода, сохранение завершится неудачно, и модель не будет сохранена.
Если вы все еще хотите использовать черту, убедитесь, что метод загрузки соответствует следующему формату: bootTraitName (), иначе он не загрузится при загрузке реализующих классов. Это сложный вопрос с множеством разных точек зрения, но я надеюсь, что по крайней мере дал вам кое-что рассмотреть.
Редактировать: я никогда не использовал модельные события в базовой модели, поэтому я не уверен, что parent::boot();
необходимо. Возможно, придется проверить.
Я должен решить подобную проблему теперь. Это не будет общедоступным сайтом, но точно так же внутренним сервером с низким трафиком.
Технические ограничения:
Следовательно, нам нужны по крайней мере две сети “представления”: один, чтобы инициировать длительный процесс и другой, контролировать его состояние/собирать результаты.
Нам также нужно своего рода межпроцессное взаимодействие: отправьте пользовательские данные от инициатора (веб-сервер на запросе HTTP) к длительному процессу и затем отправьте его результаты на получатель (снова веб-сервер, управляемый запросами HTTP). Первый легок, последний менее очевиден. В отличие от этого, в нормальном программировании Unix, получатель не известен первоначально. Получатель может быть другим процессом от инициатора, и он может запуститься, когда длительное задание все еще происходит или уже закончено. Таким образом, каналы не работают, и нам нужно некоторое постоянство результатов длительного процесса.
Я вижу два возможных решения:
Я предпочел использовать временные файлы и помнить их locaiton в данных сессии. Я не думаю, что это может быть сделано более простым.
Сценарий задания (это - длительный процесс), myjob.py
:
import sys
from time import sleep
i = 0
while i < 1000:
print 'myjob:', i
i=i+1
sleep(0.1)
sys.stdout.flush()
django urls.py
отображение:
urlpatterns = patterns('',
(r'^startjob/$', 'mysite.myapp.views.startjob'),
(r'^showjob/$', 'mysite.myapp.views.showjob'),
(r'^rmjob/$', 'mysite.myapp.views.rmjob'),
)
представления django:
from tempfile import mkstemp
from os import fdopen,unlink,kill
from subprocess import Popen
import signal
def startjob(request):
"""Start a new long running process unless already started."""
if not request.session.has_key('job'):
# create a temporary file to save the resuls
outfd,outname=mkstemp()
request.session['jobfile']=outname
outfile=fdopen(outfd,'a+')
proc=Popen("python myjob.py",shell=True,stdout=outfile)
# remember pid to terminate the job later
request.session['job']=proc.pid
return HttpResponse('A <a href="/showjob/">new job</a> has started.')
def showjob(request):
"""Show the last result of the running job."""
if not request.session.has_key('job'):
return HttpResponse('Not running a job.'+\
'<a href="/startjob/">Start a new one?</a>')
else:
filename=request.session['jobfile']
results=open(filename)
lines=results.readlines()
try:
return HttpResponse(lines[-1]+\
'<p><a href="/rmjob/">Terminate?</a>')
except:
return HttpResponse('No results yet.'+\
'<p><a href="/rmjob/">Terminate?</a>')
return response
def rmjob(request):
"""Terminate the runining job."""
if request.session.has_key('job'):
job=request.session['job']
filename=request.session['jobfile']
try:
kill(job,signal.SIGKILL) # unix only
unlink(filename)
except OSError, e:
pass # probably the job has finished already
del request.session['job']
del request.session['jobfile']
return HttpResponseRedirect('/startjob/') # start a new one
Возможно, Вы могли посмотреть на проблему наоборот.
Возможно, Вы могли попробовать DjangoQueueService и иметь "демона", слушающего очередь, видя, существует ли что-то новое, и обработайте его.