Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
101 views
in Technique[技术] by (71.8m points)

python - New Entry of Data overwrites all past entries in column , how do i correct this?

Using Django,

when the User fills out the webform, one of the saved Data overwrites all pass entered data for that column. How do i stop it from overwriting it the other past data for that column ?

Models.py file below,

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

Here are the first 2 View Functions

# 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)

Below is the View Function that im having problem with, This is where i'm having the trouble with the latest.objects('id') command, i found this as a solution, but it's overwriting all of the rows for that "Results" Column

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)

enter image description here

question from:https://stackoverflow.com/questions/65930289/new-entry-of-data-overwrites-all-past-entries-in-column-how-do-i-correct-this

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

I had a look at your question. First, two things that were already noted in the comments:

  1. Get rid of the global variables. Global variables will behave in unexpected?ways in a Django application, you should not use them unless you really, really, really know what you are doing.
  2. Capitalize your class names, i.e. Ansquestions and Results

With that out of the way. Let's try to figure out what's going on here. My understanding is that you want to collect some information about an investment and then calculate the returns.

Why is Results a separate model? It could be a field on your Ansquestions. You could store the string you want to display, or even better, just the numerical value.

Why is?formulafv a separate view? You can do the calculation immediately when you receive the inputs.

results.objects.latest('id') will indeed give you the latest object. But once you have multiple users accessing your application, you will run into a race-conditions so you get the results from a different user. But you don't really need it here anyways.

Don't use request.POST directly, use form.cleaned_data. If your?AnsquestionsForm uses FloatFields and IntegerFields, form.cleaned_data will contain floats and ints. You then don't need any conversions from str to int in?formulafv

Here is some (untested) code to illustrate what I mean:

# 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', ...]

Also, I would suggest using the same name for a field/variable in your model, form and views. That makes it much easier to understand what's going on. I have not done that in the code above to not change everything completely.

I hope that points you in the right direction.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...