我有一个postgres函数,它所做的是当我保存一个项目时,它创建一个test2021-20221-1. cl_itemid然后,在表clearing_office中,列office_serial增量+1,因此保存的下一项将是office_serial
SELECT CONCAT(f_office_id,f_sy,f_sem,'-',office_serial) INTO office_lastnumber from curriculum.clearing_office
where office_id=f_office_id;
UPDATE curriculum.clearing_office SET office_serial =office_serial+1 where office_id=f_office_id;
{
"studid": "4321-4321",
"office": "test",
"sem": "1",
"sy": "2021-2022",
}是否可以通过Django模型来创建这个问题,或者可能是解决这个问题的另一个解决方案?
这是我的模型课
class Item(models.Model):
cl_itemid = models.CharField(primary_key=True, max_length=20)
studid = models.CharField(max_length=9, blank=True, null=True)
office = models.ForeignKey('ClearingOffice', models.DO_NOTHING, blank=True, null=True)
sem = models.CharField(max_length=1, blank=True, null=True)
sy = models.CharField(max_length=9, blank=True, null=True)
class Meta:
managed = False
db_table = 'item'发布于 2022-09-08 01:42:43
一个简单的方法可能是在python中使用default函数。
def get_default_id():
last_id = Item.objects.last().cl_itemid
split_id = last_id.split('-')
split_id[-1] = str(int(split_id[-1])+1)
new_id = '-'.join(split_id)
return new_id
class Item(models.Model):
cl_itemid = models.CharField(..., default=get_default_id)类似的方法在这个答案中描述。
在这种方法中,您需要预见的一件事是,当同时创建两个或多个新对象(即,两个新对象同时运行默认函数,可能会导致两个新对象返回相同的ID )时,可能会出现争用条件。如果您认为事务或重试将是应用程序中的一个问题,则可以解决该问题。
一种健壮的方法是创建您自己的模型字段并在内部处理该领域的实现。这将允许您以不同的方式实现解决方案,这取决于DB方言,并让它在没有竞争条件问题的情况下跨DB实现工作。
发布于 2022-09-08 01:41:50
我在很多模特身上都这样做,有点不同。我只是在自定义保存方法上使用窗体和tac。
我没有使用过非托管模型,但从我从google上看到的情况来看,这并没有什么不同。
表格(forms.py)
class ItemForm(forms.ModelForm):
class Meta:
model = Item
fields = (
'cl_itemid',
'studid',
'office',
'sem',
'sy',
)
def __init__(self, *args, **kwargs):
super(ItemForm, self).__init__(*args, **kwargs)
def save(self, commit=True):
obj = super(ItemForm, self).save(commit=False)
if not self.instance:
# you only want it hitting this if it's new!
from datetime import datetime
now = datetime.now()
count = Item.objects.all().count()
# you could also just grab the last
# + chop the id to get the last number
obj.cl_itemid = 'test{0}-{1}'.format(now.strftime('%Y-%m%d%y'), count)
if commit:
obj.save()您甚至可以在实际的保存方法super(ItemForm, self).save(commit=False)之前对其进行测试,甚至可以执行一个cl_itemid。我将在我的终端进行一些测试,看看这是否是一个选项,可能会更干净。
用法
视图(职位)
def ItemFormView(request):
from app.forms import ItemForm
if request.method == "POST":
# this is just for edits
itemObj = Item.objects.get(pk=request.POST.get('itemid')) if request.POST.get('itemid') else None
form = ItemForm(request.POST or None, instance=itemObj)
if form.is_valid():
obj = form.save()
return HttpResponseRedirect(reverse('sucesspage')
print(form.errors)
print(form.errors.as_data())
# this will render the page with the errors
data = {'form': form}
else:
data = {'form': ItemForm()}
return render(request, 'itemform.html', data)壳
f = ItemForm(data={'office':'test', 'sem':'1', 'etc':'etc'})
if f.is_valid():
o = f.save()https://stackoverflow.com/questions/73642741
复制相似问题