Denormalising field in django - django

I'm finding it difficult to denormalise a field in a django model. I have:
class AnswerSet(models.Model):
title = models.CharField(max_length=255)
num_answers = models.PositiveIntegerField(editable=False, default=0)
answers = models.ManyToManyField(Answer, through='AnswerSetAnswer')
...
class AnswerSetAnswer(models.Model):
answer = models.ForeignKey(Answer)
answer_set = models.ForeignKey(AnswerSet)
...
I want num_answers to contain a count of the number of answers in the set.
If 5 answers are initially associated with the AnswerSet "Food" and I edit one so it becomes associated with the AnswerSet "Colours", how can I recalculate the number of answers in the AnswerSet with "Food"? All the signals only seem to send the new data so I can't just override the save method.
I've tried using the m2m_changed signal, but it never gets called when I edit relationships through the admin form.
Here's my code anyway:
def update_answer_set_num_answers(sender, **kwargs):
"""
Updates the num_answers field to reflect the number of answers
associated with this AnswerSet
"""
instance = kwargs.get('instance', False)
print "no instance" # never gets here
if not instance:
return
action = kwargs.get('action')
print "action: ", action
if (action != 'pre_remove' and action != 'pre_add' and action != 'clear'):
return
reverse = kwargs.get('reverse')
if reverse:
answer_set = instance.answer_set
else:
answer_set = instance.answer_set
num_answers = AnswerSetAnswer.objects.filter(answer_set=answer_set.id).count()
if (action == 'pre_remove'):
num_answers -= int(kwargs.get('pk_set'))
elif (action == 'pre_add'):
num_answers += int(kwargs.get('pk_set'))
elif (action == 'clear'):
num_answers = 0
answer_set.num_answers = num_answers
print 'n a: ', answer_set.num_answers
answer_set.save()
m2m_changed.connect(update_answer_set_num_answers, \
AnswerSet.answers.through, weak=False)

Do you really need to denormalise this? You can calculate it with a simple aggregate:
from django.db.models import Count
answersets = AnswerSet.objects.all().annotate(num_answers=Count('answers')

Related

django filter data and make union of all data points to assignt to a new data

My model is as follows
class Drawing(models.Model):
drawingJSONText = models.TextField(null=True)
project = models.CharField(max_length=250)
Sample data saved in drawingJSONText field is as below
{"points":[{"x":109,"y":286,"r":1,"color":"black"},{"x":108,"y":285,"r":1,"color":"black"},{"x":106,"y":282,"r":1,"color":"black"},{"x":103,"y":276,"r":1,"color":"black"},],"lines":[{"x1":109,"y1":286,"x2":108,"y2":285,"strokeWidth":"2","strokeColor":"black"},{"x1":108,"y1":285,"x2":106,"y2":282,"strokeWidth":"2","strokeColor":"black"},{"x1":106,"y1":282,"x2":103,"y2":276,"strokeWidth":"2","strokeColor":"black"}]}
I am trying to write a view file where the data is filtered based on project field and all the resulting queryset of drawingJSONText field are made into one data
def load(request):
""" Function to load the drawing with drawingID if it exists."""
try:
filterdata = Drawing.objects.filter(project=1)
ids = filterdata.values_list('pk', flat=True)
length = len(ids)
print(list[ids])
print(len(list(ids)))
drawingJSONData = dict()
drawingJSONData = {'points': [], 'lines': []}
for val in ids:
if length >= 0:
continue
drawingJSONData1 = json.loads(Drawing.objects.get(id=ids[val]).drawingJSONText)
drawingJSONData["points"] = drawingJSONData1["points"] + drawingJSONData["points"]
drawingJSONData["lines"] = drawingJSONData1["lines"] + drawingJSONData["lines"]
length -= 1
#print(drawingJSONData)
drawingJSONData = json.dumps(drawingJSONData)
context = {
"loadIntoJavascript": True,
"JSONData": drawingJSONData
}
# Editing response headers and returning the same
response = modifiedResponseHeaders(render(request, 'MainCanvas/index.html', context))
return response
I runs without error but it shows a blank screen
i dont think the for function is working
any suggestions on how to rectify
I think you may want
for id_val in ids:
drawingJSONData1 = json.loads(Drawing.objects.get(id=id_val).drawingJSONText)
drawingJSONData["points"] = drawingJSONData1["points"] + drawingJSONData["points"]
drawingJSONData["lines"] = drawingJSONData1["lines"] + drawingJSONData["lines"]

Django: Not fetching the same object

I have a form where i am entering four details 'Persona Name', 'Persona Key' ,'Persona Key Label' and 'Persona Key Value' and on entering these values i am pressing Submit button which generates a GET request on my server.
Following are django views:-
def PersonaSave(request):
persona_name = request.GET.get('persona_name',)
persona_key = request.GET.get('key_name',)
persona_key_value = request.GET.get('key_value',)
persona_key_label = request.GET.get('key_label',)
persona_submit = request.GET.get('Save',)
return( persona_name , persona_key , persona_key_label , persona_key_value , persona_submit )
def TestPageView(request):
x=PersonaSave(request)
persona_name = x[0]
persona_key = x[1]
persona_key_label=x[2]
persona_key_value=x[3]
persona_submit=x[4]
if(persona_name is None and persona_key is None and persona_key_label is None and persona_key_value is None):
return render(request, 'dashboard/test_page.html')
elif TestPersonaName.objects.filter(name=persona_name).exists():
t= TestPersonaName.objects.get(pk=persona_name)
testpersona = TestPersona.objects.get(name=t)
if testpersona.key == persona_key:
testpersona.label= persona_key_label
testpersona.value = persona_key_value
t=TestPersonaName(name=persona_name)
t.save()
testpersona = TestPersona(name=t,key=persona_key,label=persona_key_label,value=persona_key_value)
testpersona.save()
return render(request,'dashboard/test_page.html')
I am rewriting codes of lines where updation and new persona formation starts to maintain the clarity of question.
Update Function starts from here-----
elif TestPersonaName.objects.filter(name=persona_name).exists():
t= TestPersonaName.objects.get(pk=persona_name)
testpersona = TestPersona.objects.get(name=t)
if testpersona.key == persona_key:
testpersona.label= persona_key_label
testpersona.value = persona_key_value
-----This is where update function ends
If persona name is different then complete new TestPersonaName object and TestPersona object will be formed.
For this the function starts here----
t=TestPersonaName(name=persona_name)
t.save()
testpersona = TestPersona(name=t,key=persona_key,label=persona_key_label,value=persona_key_value)
testpersona.save()
----and ends here.
Now the problem is for the same persona name and same persona key two different TestPersona objects are being formed. For e.g If I enter persona_name = Ankit,
key = 'city' and value = 'New Delhi' and later i want to change city so i enter
name='Ankit' , key = 'city' and name = 'Lucknow'. On pressing submit two different TestPersona objects are being formed. i.e
object1(name='Ankit',key='city', value='New Delhi') and
object2(name='Ankit',key='city',value='Lucknow')
Ideally it should be:-
object1(name='Ankit', key='city', value='Lucknow')
Following are TestPersonaName and TestPersona models:-
class TestPersonaName(models.Model):
name = models.CharField(max_length=100,primary_key=True)
class TestPersona(models.Model):
name = models.ForeignKey('TestPersonaName',on_delete=models.CASCADE)
key = models.CharField(max_length=200)
label = models.CharField(max_length=200,null=True,blank=True)
value = models.CharField(max_length=200)
elif TestPersonaName.objects.filter(name=persona_name).exists():
t= TestPersonaName.objects.get(pk=persona_name)
testpersona = TestPersona.objects.get(name=t)
if testpersona.key == persona_key:
testpersona.label= persona_key_label
testpersona.value = persona_key_value
You need too save the persona and return here as in the if above. Otherwise the interpreter exits this block and continues with
t=TestPersonaName(name=persona_name)
t.save()
testpersona = TestPersona(name=t,key=persona_key,label=persona_key_label,value=persona_key_value)
testpersona.save()
which replaces the value of t with a new persona that gets saved to DB. After every attempt to edit you'll keep ending up with a new record.

Why are two objects being created in my sqlalchemy init? [duplicate]

This question already has answers here:
Why does running the Flask dev server run itself twice?
(7 answers)
Closed 5 years ago.
This is my Model:
class Category(db.Model):
__tablename__='category'
id = db.Column(db.Integer,primary_key=True)
items = db.relationship('Item',backref='category',lazy='dynamic')
name = db.Column(db.String(80))
order = db.Column(db.Integer)
private = db.Column(db.Boolean)
color = db.Column(db.String(80),unique=False)
def __init__(self,name,order=None,private=None):
r = lambda: random.randint(0, 255)
color = (r(), r(), r())
color = ('#%02X%02X%02X' % color)
count = db.session.query(Category).count()
print count
self.name = name
self.color = color
self.order = count+1
self.private = 1
def __repr__(self):
return '<Category %r>' % self.name
and I create the tables here:
def initialize_tables():
db.create_all()
c = Category(name="uncategorized")
db.session.add(c)
db.session.commit()
if __name__ == '__main__':
initialize_tables()
app.run(debug=True)
This creates two categories in my database named 'uncategorized'. Why is this happening?
That's because you're using app.run with debug=True:
If the debug flag is set the server will automatically reload for code changes and show a debugger in case an exception happened.
The way the reloader works is by starting itself again in a subprocess, so if __name__ == '__main__' (and hence initialize_tables) runs twice.

Setting and Retrieving Data with TkInter

I just ran into some strange behavior that has me stumped. I'm writing a simple little GUI for some in-house data processing. I want to allow a user to switch between a few different data-processing modes and input some parameters which define how the data is processed for each mode. The problem is that when the user inputs new parameters, the app ignores requests to switch modes.
The code below replicates the issue. I apologize for the size, this was the shortest code that replicates the problem.
import Tkinter as Tk
class foo(Tk.Frame):
def __init__(self):
self.master = master =Tk.Tk()
Tk.Frame.__init__(self,self.master) #Bootstrap
#Here mode and parameters as key, value pairs
self.data = {'a':'Yay',
'b':'Boo'
}
self.tex = Tk.Text(master=master)
self.tex.grid(row=0,column=0,rowspan=3,columnspan=4)
self.e = Tk.Entry(master=master)
self.e.grid(row=3,column=0,columnspan=4)
self.sv =Tk.StringVar()
self.sv.set('a')
self.b1 = Tk.Radiobutton(master=master,
text = 'a',
indicatoron = 0,
variable = self.sv,
value = 'a')
self.b2 = Tk.Radiobutton(master=master,
text = 'b',
indicatoron = 0,
variable = self.sv,
value = 'b')
self.b3 = Tk.Button(master = master,
text='Apply',command=self.Apply_Func)
self.b4 = Tk.Button(master = master,
text='Print',command=self.Print_Func)
self.b1.grid(row=4,column=0)
self.b2.grid(row=4,column=1)
self.b3.grid(row=4,column=2)
self.b4.grid(row=4,column=3)
def Apply_Func(self):
self.innerdata = self.e.get()
def Print_Func(self):
self.tex.insert(Tk.END,str(self.innerdata)+'\n')
#This is how I'm retrieving the user selected parameters
#property
def innerdata(self):
return self.data[self.sv.get()]
#And how I'm setting the user defined parameters
#innerdata.setter
def innerdata(self,value):
self.data[self.sv.get()] = value
if __name__ == "__main__":
app = foo()
app.mainloop()
Expected behavior:
1) Press button 'a' then 'print' prints:
Yay
2) Press button 'b' then 'print' prints:
Boo
3) Type 'Zep Rocks' into the entry field and press apply
4) Pressing 'print' now yields
Zep Rocks
5) Pressing 'a' then 'print' should yield
Yay
But instead yields
Zep Rocks
Which might be true, but not desired right now. What is going on here?
Edit: I have some new information. Tk.Frame in python 2.7 is not a new-style class. It isn't friendly with descriptors, so rather than interpreting the '=' as a request to use the foo.innerdata's __set__ method, it just assigns the result of self.e.get() to innerdata.
ARGLEBARGLE!!!
Still an open question: how do I get this to do what I want in a clean manner?
So the core problem is that Tk.Frame doesn't subclass from object, so it is not a new-style python class. Which means it doesn't get down with descriptors like I was trying to use. One solution that I found is to subclass my app from object instead.
Code that solves my problem is below:
import Tkinter as Tk
class foo(object):
def __init__(self,master):
self.master = master #Bootstrap
self.mainloop = master.mainloop
self.data = {'a':{'value':7,'metavalue':False},
'b':{'value':'Beeswax','metavalue':True}
}
self.tex = Tk.Text(master=master)
self.tex.grid(row=0,column=0,rowspan=3,columnspan=4)
self.e = Tk.Entry(master=master)
self.e.grid(row=3,column=0,columnspan=4)
self.sv =Tk.StringVar()
self.sv.set('a')
self.b1 = Tk.Radiobutton(master=master,
text = 'a',
indicatoron = 0,
variable = self.sv,
value = 'a')
self.b2 = Tk.Radiobutton(master=master,
text = 'b',
indicatoron = 0,
variable = self.sv,
value = 'b')
self.b3 = Tk.Button(master = master,text='Apply',command=self.Apply_Func)
self.b4 = Tk.Button(master = master,text='Print',command=self.Print_Func)
self.b1.grid(row=4,column=0)
self.b2.grid(row=4,column=1)
self.b3.grid(row=4,column=2)
self.b4.grid(row=4,column=3)
def Apply_Func(self):
self.innerdata = self.e.get()
def Print_Func(self):
self.tex.insert(Tk.END,str(self.innerdata)+'\n')
#property
def innerdata(self):
return self.data[self.sv.get()]
#innerdata.setter
def innerdata(self,value):
self.data[self.sv.get()] = value
if __name__ == "__main__":
master = Tk.Tk()
app = foo(master)
app.mainloop()

django: Class-based Form has no errors but is not valid. What is happening?

I have a form which is returning False from .is_valid(), but .errors and .non_field_errors() appear to be empty. Is there any other way to check out what might be causing this?
In case it's a problem with my logging code, here it is:
logger.debug('form.non_field_errors(): ' + str(form.non_field_errors()))
logger.debug('form.errors: ' + str(form.errors))
My form code:
class IncorporateForm(forms.Form):
type_choices = (("LTD", "Private company limited by shares"),
("LTG", "Private company limited by guarantee"),
("PLC", "Public limited company"),
("USC", "Unlimited company with share capital"),
("UWS", "Unlimited company without share capital"))
country_choices = (("EW", "England and Wales"),
("CY", "Wales"),
("SC", "Scotland"),
("NI", "Northern Ireland"))
articles_choices = (("MOD", "Model articles"),
("AMD", "Model articles with amendments"),
("BES", "Entirely bespoke articles"))
name = forms.CharField(initial = "[name] limited")
registered_office = forms.CharField(widget=forms.Textarea,
label='Registered office address')
registration_country = forms.ChoiceField(choices=country_choices,
widget=forms.RadioSelect(renderer=SaneRadioField))
company_type = forms.ChoiceField(choices=type_choices,
widget=forms.RadioSelect(renderer=SaneRadioField), initial="LTD")
articles_type = forms.ChoiceField(choices=articles_choices,
initial='MOD',
widget=forms.RadioSelect(renderer=SaneRadioField))
restricted_articles = forms.BooleanField()
arts_upload = forms.FileField(label='Articles to upload')
My view code (to the point where I detect that the form is not valid):
def incorporate_view(request):
form = IncorporateForm()
DirectorsFormset = forms.formsets.formset_factory(OfficerForm, extra=30)
CapitalFormset = forms.formsets.formset_factory(CapitalForm, extra=30)
HoldingFormset = forms.formsets.formset_factory(HoldingForm, extra=30)
AmendsFormset = forms.formsets.formset_factory(ArticlesAmendsForm, extra=50)
if request.method == 'POST':
#bind and validate
form.data = request.POST
guarantee_form = GuaranteeForm(data=request.POST)
directors_formset = DirectorsFormset(prefix='directors', data=request.POST)
capital_formset = CapitalFormset(prefix='capital', data=request.POST)
holding_formset = HoldingFormset(prefix='holding', data=request.POST)
amends_formset = AmendsFormset(prefix='amends', data=request.POST)
save_objects = [] # objects to be saved at the end if there is no error
user_objects = {} # keyed by email
individual_objects = {} # keyed by email?
if(not (form.is_valid() and guarantee_form.is_valid()
and directors_formset.is_valid()
and capital_formset.is_valid() and
holding_formset.is_valid() and
amends_formset.is_valid())):
dbg_str = """
form.is_valid(): %s
guarantee_form.is_valid(): %s
directors_formset.is_valid(): %s
capital_formset.is_valid(): %s
holding_formset.is_valid(): %s
amends_formset.is_valid(): %s
""" % (form.is_valid(), guarantee_form.is_valid(),
directors_formset.is_valid(),
capital_formset.is_valid(),
holding_formset.is_valid(),
amends_formset.is_valid())
logger.debug(dbg_str)
logger.debug('form.non_field_errors(): ' + str(form.non_field_errors()))
logger.debug('form.errors: ' + str(form.errors))
Assigning to form.data does not bind the form — you should pass the data dict when the object is constructed (or look into the code and see which flags are set, but that's probably not documented and therefore not recommended).