I'm a total beginner with Python/Django and trying to understand why this isn't working. I have a function that contains a for loop, doing some logic and then updating a model. but when I have more than 1 item in the loop I get a UNIQUE constraint failed: app_token.token_name error.
So I think I'm misunderstanding how the loop is working?
function
tokens = Token.objects.all()
for item in tokens:
if item.token_contract_address is not None:
token = Token.objects.get(pk=item.id)
parameters = {
'address':token.token_contract_address
}
session = Session()
session.headers.update(headers)
response = session.get(url, params=parameters)
resp = json.loads(response.text)
token_id = (resp['data'][next(iter(resp['data']))]['id'])
logo = (resp['data'][next(iter(resp['data']))]['logo'])
url = 'https://pro-api.coinmarketcap.com/v1/cryptocurrency/quotes/latest'
parameters = {
'id':token_id
}
session = Session()
session.headers.update(headers)
response = session.get(url, params=parameters)
id = str(token_id)
price = (json.loads(response.text)['data'][id]['quote']['USD']['price'])
market_cap = (json.loads(response.text)['data'][id]['quote']['USD']['market_cap'])
change = (json.loads(response.text)['data'][id]['quote']['USD']['percent_change_24h'])
r = Token.objects.update(token_capture_date = formatedDate, token_price = price, token_name=item.token_name )
I'm expecting the this Token.objects.update(token_capture_date = formatedDate, token_price = price, token_name=item.token_name ) to update the model based on the item loop?
The model is very simple:
class Token(models.Model):
token_name = models.CharField(max_length=50, blank=False, unique=True)
token_slug = models.CharField(max_length=50, blank=True,null=True)
token_price = models.FloatField(blank=True,null=True)
token_capture_date = models.DateField(blank=True,null=True)
token_contract_address = models.CharField(max_length=50, blank=True,null=True)
def __str__(self):
return str(self.token_name)
I'm using the update on the objects and have tried removing the token_name, and tried using token.token_name
If I remove token_name= it updates both items in the database with the same values? which makes me think its this line r = Token.objects.update(token_capture_date = formatedDate, token_price = price, token_name=item.token_name ) do i need to apply some kinda of filter?
Thanks
I believe that by calling Token.objects.update() you actually end up trying to update all Token objects. Since token_name has to be unique, and you are giving it the same name as another Token object it throws that error.
Since you are already in a for loop, you can simply update the token that is currently being processed.
My suggestion would be to use this code instead:
item.token_capture_date = formattedDate
item.token_price = price
item.save()
This will make it so that the current token object which is being processed in the for loop has its respective field values updated and saved in the database.
Also, this line is unnecessary: token = Token.objects.get(pk=item.id) as we already have access to the token through the looping variable item.
Do let me know if this helps!
Related
I just want to iterate through the list of JSON data which I get in the payload but getting an error as list indices must be integers or slices, not dict
payload:
[{"AuditorId":10,"Agents":"sa","Supervisor":"sa","TicketId":"58742","QId":150,"Answer":"Yes","TypeSelected":"CMT Mails","Comments":"na","TicketType":"Regularticket","Action":"na","AuditSubFunction":"na","AuditRegion":"na"},{"AuditorId":10,"Agents":"sa","Supervisor":"sa","TicketId":"58742","QId":151,"Answer":"Yes","TypeSelected":"CMT Mails","Comments":"na","TicketType":"Regularticket","Action":"na","AuditSubFunction":"na","AuditRegion":"na"}]
views.py:
#api_view(['POST'])
def SaveUserResponse(request):
for ran in request.data:
auditorid = request.data[ran].get('AuditorId')
ticketid = request.data[ran].get('TicketId')
qid = request.data[ran].get('QId')
answer = request.data[ran].get('Answer')
sid = '0'
TicketType = request.data[ran].get('TicketType')
TypeSelected = request.data[ran].get('TypeSelected')
agents = request.data[ran].get('Agents')
supervisor = request.data[ran].get('Supervisor')
Comments = request.data[ran].get('Comments')
action = request.data[ran].get('Action')
subfunction = request.data[ran].get('AuditSubFunction')
region = request.data[ran].get('AuditRegion')
cursor = connection.cursor()
cursor.execute('EXEC [dbo].[sp_SaveAuditResponse] #auditorid=%s,#ticketid=%s,#qid=%s,#answer=%s,#sid=%s,#TicketType=%s,#TypeSelected=%s,#agents=%s, #supervisor =%s, #Comments=%s, #action=%s, #subfunction=%s, #region=%s',
(auditorid,ticketid,qid,answer, sid,TicketType, TypeSelected, agents, supervisor, Comments, action, subfunction,region))
return Response(True)
I ran this code on my machine and it works for the payload you provided.
#api_view(['POST'])
def SaveUserResponse(request):
for ran in request.data:
auditorid = ran.get('AuditorId')
ticketid = ran.get('TicketId')
qid = ran.get('QId')
answer = ran.get('Answer')
sid = '0'
TicketType = ran.get('TicketType')
TypeSelected = ran.get('TypeSelected')
agents = ran.get('Agents')
supervisor = ran.get('Supervisor')
Comments = ran.get('Comments')
action = ran.get('Action')
subfunction = ran.get('AuditSubFunction')
region = ran.get('AuditRegion')
If it doesn't then content of request.data must be different then payload you shared in original post
BEFORE :
class Person(ndb.Model):
name = ndb.StringProperty()
age = ndb.StringProperty()
other_details = ndb.StructuredProperty(OtherDetails, 'othrdtl')
class OtherDetails(ndb.Model):
success = ndb.StringProperty()
qr_code = ndb.TextProperty()
AFTER:
class Person(ndb.Expando):
pass
rows_to_be_updated = []
for person in Person.all():
person.age = int(person.age)
rows_to_be_updated.append(person)
if len(rows_to_be_updated)>0:
ndb.put_multi_async(rows_to_be_updated)
#"When the above line is executed i am getting error"
Very AFTER:
class Person(db.Model):
name = db.StringProperty()
age = db.IntegerProperty()
other_details = ndb.StructuredProperty(OtherDetails, 'othrdtl')
As per the datastore document, the TextProperty is unindexed by default. What is the reason for the error? I have tried making explicit Indexed=False (ndb.TextProperty(indexed= False)) but didn't work.
Instead of trying to go through an expando model, you might consider using a different name in your database than in your model.
E.g. after
class Person(ndb.Model):
name = ndb.StringProperty()
string_age = ndb.StringProperty('age')
age = ndb.IntegerProperty('int_age')
other_details = ndb.StructuredProperty(OtherDetails, 'othrdtl')
Then you could use a hook to ensure that Person.age is always set, e.g.
class Person(ndb.Model):
#classmethod
def _post_get_hook(cls, key, future):
p = future.get_result()
if p and not p.age:
p.age = int(p.string_age)
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"]
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.
I have a form which references three models and I want to save the items to each model. One of the models has foreign key references to the other models and I want to save them too.
My models look like:
class Address(models.Model):
housenumber = models.CharField(max_length=20,default='',blank=True)
street = models.CharField(max_length=80,default='',blank=True)
town = models.CharField(max_length=80,default='',blank=True)
county = models.CharField(max_length=60,default='',blank=True)
country = models.CharField(max_length=20,default='',blank=True)
postcode = models.CharField(max_length=10,default='',blank=True)
class GeoLocation(models.Model):
longitude = models.FloatField(default=-4.2576300)
latitude = models.FloatField(default=55.8651500)
class Location(models.Model):
locationname = models.CharField(max_length=80,default='',blank=True)
address = models.ForeignKey(Address, on_delete=models.CASCADE)
geolocation = models.ForeignKey(GeoLocation, on_delete=models.CASCADE, default='')
My views looks like:
if locationform.is_valid() and addressform.is_valid() and geolocationform.is_valid():
locationform.save(commit=False)
new_address = addressform.save()
new_geolocation = geolocationform.save()
locationform.address = new_address
locationform.geolocation = new_geolocation
locationform.save()
This will give me an error that states "NOT NULL constraint failed: location_location.address_id".
Can anyone help? I am new to Django so find this stuff hard.
Thanks Eduardo I managed to get it working with the following code, almost the same as yours:
if locationform.is_valid() and addressform.is_valid() and geolocationform.is_valid():
new_location = locationform.save(commit=False)
new_address = addressform.save()
new_geolocation = geolocationform.save()
Location.objects.create(
locationname= new_location.locationname,
address=new_address,
geolocation=new_geolocation)
One solution could be:
if locationform.is_valid() and addressform.is_valid() and geolocationform.is_valid():
new_address = addressform.save()
new_geolocation = geolocationform.save()
locationform.address = new_address
locationform.geolocation = new_geolocation
Location.objects.create(
locationname=locationform.data.get('locationname', " ",
address=new_address,
geolocation=new_geolocation)