新的数据条目会覆盖列中所有过去的条目,我该如何更正?
Posted
技术标签:
【中文标题】新的数据条目会覆盖列中所有过去的条目,我该如何更正?【英文标题】:New Entry of Data overwrites all past entries in column , how do i correct this? 【发布时间】:2021-05-01 22:41:22 【问题描述】:使用 Django,
当用户填写网络表单时,其中一个保存的数据会覆盖该列的所有传递输入数据。如何阻止它覆盖该列的其他过去数据?
Models.py 文件如下,
from django.db import models
from django.utils import timezone
from django.contrib.auth.models import User
class ansquestions(models.Model):
m_invested = models.CharField(max_length=100)
p_return = models.CharField(max_length=100)
years = models.CharField(max_length=100)
inflation_yes_no = models.CharField(max_length=100)
date_answered = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE, null=True)
results = models.ForeignKey('results', on_delete=models.CASCADE, null=True) # null=True
def __str__(self):
return self.m_invested + ' ' +self.p_return
class results(models.Model): # second table for output and add other data from ansquestions table as foreign keys
r_output = models.CharField(max_length=500)
author = models.ForeignKey(User, on_delete=models.CASCADE, null=True)
def __str__(self):
return self.r_output
# Important : this dunder method above __str__(self) for r_ouptput was how the actual r_output value gets displayed on admin interface. important since it was foreign key
这是前 2 个视图函数
# functions investmenttest and add are together
def investmenttest(request):
return render(request, 'fvalueapp/investmenttest.html')
# functions investmentfv and investmentfvcalc (real application)
# the html files that im using and have the css on them are home.html , about.html , investmentfv.html , fvinvestmentcalcresults.html(this outputs the result answer, as you see function below)
# CSS files are under the static folder , sub-folder "design"
def investmentfv(request):
global total_i
global perc_r
global years_i
global makeup_infl
idata = 'tmi':tmi, 'pry':pry, 'ys':ys, 'qinf':qinf
if request.method == "POST":
form = AnsquestionsForm(request.POST or None)
if form.is_valid():
total_i = request.POST.get("m_invested", '')
perc_r = request.POST.get("p_return", '')
years_i = request.POST.get("years", '')
makeup_infl = request.POST.get("inflation_yes_no", '')
newdata=ansquestions(m_invested=total_i, p_return=perc_r, years=years_i, inflation_yes_no=makeup_infl)
#newdata.results = results.objects.latest('id')#Note latest() is query set operator. BK# results.objects.order_by( 'author', 'id', 'r_output').last()#this is method for getting latest r_output from results table
newdata.author = request.user
newdata.save()
return redirect('formulafv')# redirects to formulafv view function below. 'formulafv' is the name variable for that url pattern.
else:
return render(request, 'fvalueapp/investmentfv.html', idata)
idata = 'tmi':tmi, 'pry':pry, 'ys':ys, 'qinf':qinf, 'form': form
return render(request, 'fvalueapp/investmentfv.html', idata)
下面是我遇到问题的视图函数,这是我在使用 latest.objects('id') 命令时遇到问题的地方,我发现这是一个解决方案,但它覆盖了所有行那个“结果”栏
def formulafv(request):
if makeup_infl=='no':
i_return = (float(perc_r))
elif makeup_infl=='yes' and int(years_i)<=5:
i_return = (2+float(perc_r))
elif makeup_infl=='yes' and int(years_i)>5 and int(years_i)<=9.99 :
i_return = (4 + float(perc_r))
elif makeup_infl=='yes' and int(years_i)>= 10 :
i_return = ( 6 + float(perc_r))
fv_i_value = int(total_i) * (1 + (i_return)*.01) ** int(years_i)
r_output = 'Your money would grow to the total of ' + str(fv_i_value) +' dollars at the end of this timeframe.'
if request.method == "POST": # second pre-filled html form for saving r_output. for right now have to press submit button on screen. (i would want this to automatically (save/submit).
tom = ResForm(request.POST or None)
if tom.is_valid():
r_output = request.POST.get("r_output", '')
bamdata = results(r_output=r_output)
bamdata.author = request.user
bamdata.save()
ansquestions.results = results.objects.latest('id')
dabby = ansquestions.results
dabby.author = request.user
dabby.save()
finalcalc = 'r_output': r_output
return render (request,'fvalueapp/fvinvestmentcalcresults.html', finalcalc)
【问题讨论】:
您的视图有太多的全局变量,无法读取。 不要在视图中使用全局变量,在数据库中存储任何必要的数据!即使是不断变化的唯一值,您也可以将它们存储在只有一行的表中。什么是ansquestions
(全局变量)?
哦,这是你的模型名称,作为另一个注释,因为模型是用 Pascal Case 命名它们的类,如果你给它们小写名称,真的很难将它们与变量区分开来。
@AbdulAzizBarkat 我已经添加了上面的前 2 个视图函数,如果这也有助于澄清事情的话。谢谢,
我不认为你已经把完整的formulafv视图放在了那个视图中ansquestions.results = ...
,你在期待什么? ansquestions 是您的模型(不是模型的实例)为什么要在模型上设置 results 属性?
@AbdulAzizBarkat ,在 ansquestions.results = .... 中,我试图从上面的“结果模型”中的“r_output”字段中输入最新值。问题是它会用最近的“r_output”覆盖过去的条目。
【参考方案1】:
我看了你的问题。 首先,在 cmets 中已经提到了两件事:
-
摆脱全局变量。全局变量会在 Django 应用程序中以意想不到的方式表现,除非你真的、真的、真的知道自己在做什么,否则不应该使用它们。
将您的班级名称大写,即 Ansquestions 和 Results
不碍事。让我们试着弄清楚这里发生了什么。我的理解是你想收集一些关于投资的信息,然后计算回报。
为什么结果是一个单独的模型?它可能是您的 Ansquestions 中的一个字段。您可以存储要显示的字符串,甚至更好的是,只存储数值。
为什么公式是一个单独的视图?您可以在收到输入后立即进行计算。
results.objects.latest('id')
确实会给你最新的对象。但是一旦您有多个用户访问您的应用程序,您就会遇到竞争条件,因此您会从不同的用户那里获得结果。但无论如何你在这里并不需要它。
不要直接使用request.POST,使用form.cleaned_data。如果您的 AnsquestionsForm 使用 FloatFields 和 IntegerFields,则 form.cleaned_data 将包含浮点数和整数。然后,您不需要在公式中从 str 到 int 进行任何转换
这里有一些(未经测试的)代码来说明我的意思:
# models.py
class Ansquestions(models.Model):
m_invested = models.CharField(max_length=100)
p_return = models.CharField(max_length=100)
years = models.CharField(max_length=100)
inflation_yes_no = models.CharField(max_length=100)
date_answered = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE, null=True)
results = models.FloatField()
@property
def investment_return(self):
return 'Your money would grow to the total of dollars at the end of this timeframe.'.format(self.results)
# views.py
def investmentfv(request):
idata = 'tmi':tmi, 'pry':pry, 'ys':ys, 'qinf':qinf
if request.method == "POST":
form = AnsquestionsForm(request.POST or None)
if form.is_valid():
total_i = form.cleaned_data['m_invested']
perc_r = form.cleaned_data["p_return"]
years_i = form.cleaned_data["years"]
makeup_infl = form.cleaned_data["inflation_yes_no"]
results = formulafv(makeup_infl, years_i, perc_r, total_i)
newdata=ansquestions(m_invested=total_i, p_return=perc_r, years=years_i, inflation_yes_no=makeup_infl, results=results)
newdata.author = request.user
newdata.save()
return redirect('formulafv')# redirects to formulafv view function below. 'formulafv' is the name variable for that url pattern.
else:
return render(request, 'fvalueapp/investmentfv.html', idata)
idata = 'tmi':tmi, 'pry':pry, 'ys':ys, 'qinf':qinf, 'form': form
return render(request, 'fvalueapp/investmentfv.html', idata)
def formulafv(makeup_infl, years_i, perc_r, total_i):
if makeup_infl=='no':
i_return = perc_r
elif makeup_infl=='yes' and years_i<=5:
i_return = 2 + perc_r
elif makeup_infl=='yes' and years_i>5 and years_i<=9.99 :
i_return = 4 + perc_r
elif makeup_infl=='yes' and years_i>= 10 :
i_return = 6 + perc_r
fv_i_value = total_i * (1 + (i_return)*.01) ** years_i
return fv_i_value
# admin.py
class AnsquestionAdmin(admin.ModelAdmin):
list_display = [..., 'investment_return', ...]
另外,我建议在模型、表单和视图中为字段/变量使用相同的名称。这使得更容易理解正在发生的事情。我没有在上面的代码中这样做,以不完全改变一切。
我希望这会为您指明正确的方向。
【讨论】:
以上是关于新的数据条目会覆盖列中所有过去的条目,我该如何更正?的主要内容,如果未能解决你的问题,请参考以下文章