您好我正在编写硬件清单应用程序,我想在每次输入新部件时记录,以及任何将来的状态更改/更新。
模型
class Part(models.Model):
type = models.ForeignKey(PartType, blank=False)
bar_code = models.CharField(max_length=50, blank=False, unique=True)
serial_number = models.CharField(max_length=50, blank=False)
status = models.ForeignKey(Status, blank=False)
class PartLog(models.Model):
part = models.ForeignKey(Part, blank=False)
time_stamp = models.DateTimeField(blank=False, auto_now_add=True)
old_status = models.ForeignKey(Status, related_name='old_status_related', blank=False)
new_status = models.ForeignKey(Status, related_name='new_status_related', blank=False)
class Status(models.Model):
current_status = (
("EN", "Entered Database"),
("CO", "Checked out"),
("CI", "Checked in"),
("RM", "Returned for RMA"),
("IU", "Currently in use"),
)
status = models.CharField(max_length=2, choices=current_status)
def __unicode__(self):
return unicode(self.status)
信号
@receiver(post_save, sender=Part)
def add_to_partLog(sender, instance, signal, created, *args, **kwargs):
if created:
print "Since a new entry has been created, setting old and new status for partlog entry!"
# Automatically changing status from Entered state to Checked In state
# Part Table
instance.status=Status(3)
instance.save()
# Setting Old and New status for the first (new) partLog entry for the new added part
# Part Log table
oldStatus = Status(1)
newStatus = Status(3)
partobj = Part.objects.get(id=instance.pk)
PartLog.objects.create(part=partobj,old_status=oldStatus, new_status=newStatus)
else:
print "Entry already exists!"
# Retreiving the old status of the Part() record
oldStatus = ???
newStatus = instance.status
partobj = Part.objects.get(id=instance.pk)
PartLog.objects.create(part=partobj,old_status=oldStatus,new_status=newStatus)
视图
def check_in_part(request):
err_list=[]
c = {}
c.update(csrf(request))
if request.method == 'POST':
form = PartForm(request.POST)
print "form object is created."
if form.is_valid():
form.save()
return http.HttpResponseRedirect('/current_count/')
else:
form = PartForm(initial={'status':1L})
return render(request,'add_part.html',{
'title':'Add Item',
'form':form
})
# Checking out a part
def check_out_part(request):
errlst = []
c = {}
c.update(csrf(request))
# ADD check against DB with the appropriate status "CO" or 3
if request.method == 'POST':
form = ModifyPartForm(request.POST)
if form.is_valid():
bar_code_form = form.cleaned_data['bar_code']
try:
bar_code_model= Part.objects.get(bar_code=bar_code_form)
except Part.DoesNotExist:
#FIXME: need to get errlst to user
errlst.append("Part with bar_code %s does not exist." % bar_code_form)
else:
#bar_code_model.check_out()
bar_code_model.status_id=2L
bar_code_model.save()
return http.HttpResponseRedirect('/current_count/')
else:
form = ModifyPartForm()
# Adding default status to Check Out or "CO"
return render(request, 'remove_part.html',{
'title':'Remove Item',
'form': form,
'errors': errlst,
})
问题在于信号中的else子句。 if的第一部分工作正常。 * 我不确定在保存之前如何访问“状态”并在保存后使用它。 * 现在在一个视图中,当我检查新部件时,我将初始状态设置为“EN”,然后自动将其更改为“CI”。现在,对于check_out视图,我只想用条形码搜索Part(),并适当地更新和记录两个表。最后我希望能够在下拉列表中列出的其他状态之间进行选择。菜单,但这是为了以后=)
答案 0 :(得分:1)
我最终缓存了状态对象,这是我的答案。
#Signals.py
@receiver(post_save, sender=Part)
def log_entry(sender, instance, created, raw, *args, **kwargs):
# Using the statuses from the above method to create a PartLog entry.
newStatus = instance.status
if not created:
# Get old status from current state
oldStatus = instance._state.old_status
PartLog.objects.create(part=instance,
old_status=oldStatus,
new_status=instance.status)
instance._state.old_status = newStatus
else:
PartLog.objects.create(part=instance, old_status=Status(1), new_status=Status(3))
#Models.py
class Part(models.Model):
type = models.ForeignKey(PartType, blank=False)
bar_code = models.CharField(max_length=50, blank=False, unique=True)
serial_number = models.CharField(max_length=50, blank=False)
status = models.ForeignKey(Status, blank=False)
def __init__(self, *args, **kwargs):
super(Part, self).__init__(*args, **kwargs)
# Caching the existing Part object's status
if self.pk:
self._state.old_status = self.status
def __unicode__(self):
return unicode(self.bar_code)
答案 1 :(得分:0)
由于模型不跟踪字段的前置值,因此无法知道post_save
信号阶段的字段的先前值。您有两种选择:
__init__()
中缓存状态字段,可能在save()
上缓存新值并检查post_save
pre_save
信号中的当前值进行数据库查找并将其缓存在对象上,以便在保存完成后引用它。我倾向于使用第一种方法并避免数据库查询。您必须注意提前缓存字段意味着您不能再在查询中推迟该字段,因为您在__init__
它可能看起来像这样:
class Part(models.Model):
...
def __init__(self, *args, **kwargs):
super(Part, self).__init__(*args, **kwargs)
self._status_old_cached = self.status
@receiver(post_save, sender=Part)
def add_to_partLog(sender, instance, created, *args, **kwargs):
...
else:
oldStatus = instance._status_old_cached
因为这会立即强制在字段上进行查找,请确保提前在查询中的select_related
{:1}}:
Part.objects.select_related('status').all()
如果你实际上不需要状态对象,只想要id
,那么它可能会保存你的查找,因为模型实际上保存了id:
self._status_id_old_cached = self.status_id