Django: String object prints out None - python

Hello I have a view that deletes order numbers. Once a string has been deleted, the web page redirects to the clients page letting the user know that the order number was deleted. There is a problem. I am getting this.
Previous order None deleted
It says None but I want it to state the order number that I have deleted. It seems it says none because I have already deleted that order number so when it looks in the order number list, it cannot find that number.
EDIT: here is the solution. Order number should be deleted after the message is sent.
def delete_confirmation(request, order_no = 0, service_type = 0):
order = None
count = 0
title = models.SERVICE_CHOICES[int(service_type) - 1][1]
#title = type[1]
order_number = request.session['order_number']
try:
order = models.Order.objects.get(pk = order_no)
count = order.orderservicelist_set.count()
if request.POST.get('delete'):
request.user.message_set.create(message = "Previous order " + str(order_number.pk) + " deleted")
order_number.delete()
return HttpResponseRedirect(reverse(return_clients))
except:
return HttpResponseRedirect(reverse(return_clients))
return render_to_response('delete_order.html', {'order':order, 'title':title, 'count':count, 'order_no':order_no }, context_instance = RequestContext(request))

One of the things that delete() does on a model instance is set its pk to None, so that if you try and save it, it will create a new instance rather than trying to update the old (no-longer-existing) one.
So, easy solution: grab the PK before you delete. In fact, you could just get rid of the first call to delete you have there, because you call it again after creating the message.
By the way, a better way of creating the message is to use string formatting:
message = "Previous order %s deleted" % order_number.pk

Very Careless mistake. why have I got order_number.delete() written twice?
if request.POST.get('delete'):
order_number.delete() # Why was this there? of course, if I have this it will delete till it gets to the next part where it informs the user which order number was deleted!
request.user.message_set.create(message = "Previous order " + str(order_number.pk) + " deleted")
order_number.delete()
fixed

Related

Django find item in queryset and get next

I'm trying to take an object, look up a queryset, find the item in that queryset, and find the next one.
#property
def next_object_url(self):
contacts = Model.objects.filter(owner=self.owner).order_by('-date')
place_in_query = list(contacts.values_list('id', flat=True)).index(self.id)
next_contact = contacts[place_in_query + 1]
When I add this to the model and run it, here's what I get for each variable for one instance.
CURRENT = Current Object
NEXT = Next Object
contacts.count = 1114
self.id = 3533 #This is CURRENT.id
place_in_query = 36
contacts[place_in_query] = NEXT
next_contact = CURRENT
What am i missing / what dumb mistake am i making?
In your function, contacts is a QuerySet. The actual objets are not fetched in the line:
contacts = Model.objects.filter(owner=self.owner).order_by('-date')
because you don’t use a function like list(), you don’t iterate the QuerySet yet... It is evaluated later. This is probably the reason of your problem.
Since you need to search an ID in the list of contacts and the find the next object in that list, I think there is no way but fetch all the contact and use a classic Python loop to find yours objects.
#property
def next_object_url(self):
contacts = list(Model.objects.filter(owner=self.owner).order_by('-date').all())
for curr_contact, next_contact in zip(contacts[:-1], contacts[1:]):
if curr_contact.id == self.id:
return next_contact
else:
# not found
raise ContactNotFoundError(self.id)
Another solution would be to change your database model in order to add a notion of previous/next contact at database level…

Django- Updating data sent from a generic CBV? (Refreshing a view's variable)

I am trying to do the following:
class PurchaseCreate(CreateView):
template_name = "generic_create.html"
model = Purchase
form_class = PurchaseForm
try:
latest_tag = Purchase.objects.latest('tag').tag
print(latest_tag)
next_tag = latest_tag + 1
except:
next_tag = 1
initial = {'tag': next_tag}
The "tag" field should start with a value that is + 1 of the previous value that has been entered. When I test it out in the Django API, it works fine. However, when called from the view, it works correctly the first time, but seems to get "stuck" returning that first value, even when new objects are created which should update the value.
In fact, the try/except portion is never executed after the first page load, as the print order never shows up in the terminal, even with a hard browser refresh. How do I set this view to send an updated result every time the page is loaded?
As suggested, I moved the logic into the get_initial() method like so:
def get_initial(self):
super(PurchaseCreate, self).get_initial()
try:
latest_tag = Purchase.objects.latest('tag').tag
print(latest_tag)
next_tag = latest_tag + 1
except:
next_tag = 1
initial = {'tag': next_tag}
return initial

python: changing from print to return does not process items right

I created a program that reads a couchDB to list followers and friends ids of a single twitter user. Friends are identified under the group “friend_edges” and followers under “follower_edges”.
I use the intersection operation between sets -set1.intersection(set.2)- in order to obtain the list of those who are both friends and followers.
When I use print to see the outputs, the results are correct. But when I change to return to process the results, it only processes friends, not followers.
Can somebody give me a clue of what I'm doing wrong and how to improve the code?.... thanks in advance.
from twitter_login import oauth_login
from twitter_DB import load_from_DB
from sets import Set
def friends_and_followers(doc):
if 'friend_edges' in doc.keys():
flist = []
for x in doc['friend_edges']:
flist.append(x)
#print "Number of friends: ", len(flist) <-- shows the right number of items
return flist
else:
return []
if 'follower_edges' in doc.keys():
followlist = []
for x in doc['follower_edges']:
followlist.append(x)
#print "Number of followers: ", len(followlist) <-- shows the right number of items
return followlist
else:
return []
flist = Set(flist)
followlist = Set(followlist)
return flist.intersection(followlist)
if __name__ == '__main__':
twitter_api = oauth_login()
DBname = 'users-aguy-+-only'
ff_results = load_from_DB(DBname)
print 'number loaded', len(ff_results)
for doc in ff_results:
together = friends_and_followers(doc)
print "Friends and followers of a guy: ", together
A return statement stops execution of that method and returns to the calling method, so by adding a return statement you are saying, "Stop here and go back to where you came from"
You need to store both the values you want returned in variables and return them at the same time at the end of your method:
return value1, value2
You will call this with something like this:
val1, val2 = get_value1_and_value2(input)
It might make more sense to just break that up into two separate methods that each return the correct value though.

why is my Python GAE code asynchronous?

This is the code:
def create_game(user_id):
game = classes.Games(user_id = user_id)
game.put()
def get_game(user_id):
game_query = classes.Games.gql('WHERE user_id = :1', user_id)
game = False
for item in game_query:
game = item
if not game:
create_game(user_id)
get_game(user_id)
else:
return game
def render_page(self):
message = 'this is a game page<br>'.decode('utf-8')
user = creditentials.get_user(self)
if not user:
self.redirect('/')
return
game = get_game(user.key().id())
message += 'current game ID: '.decode('utf-8') + str(game.key().id())
self.response.write(message)
I expect it to create just one instance of the game, instad it creates 10! Appearantly GQL query is perfromed asynchronously, and starting from the 3rd (?) instance of the get_game(user_id) it just skips game_query = classes.Games.gql('WHERE user_id = :1', user_id) line.
Am I right? How do I avoid this?
Queries aren't immediately consistent, so an entity that you've only just created won't be returned in a query performed right-away, you need to wait a bit.
In your case, you don't need to query for the entity - you just created it, so you know it exists, and can use it. Change your create_game function to return the new game, and then use that.
If you expect your user_id to be unique (and given your query, this seems to be the case) you could use it as the entity-id, then you can get-by-id instead of querying, which will strongly-consistent.
Check the "Data Consistency" section on this docs page for more detail on how queries work.

how to get entities which don't have certain attribute in datastore

I'm trying to make an appraisal system
This is my class
class Goal(db.Expando):
GID = db.IntegerProperty(required=True)
description = db.TextProperty(required=True)
time = db.FloatProperty(required=True)
weight = db.IntegerProperty(required=True)
Emp = db.UserProperty(auto_current_user=True)
Status = db.BooleanProperty(default=False)
Following things are given by employee,
class SubmitGoal(webapp.RequestHandler):
def post(self):
dtw = simplejson.loads(self.request.body)
try:
maxid = Goal.all().order("-GID").get().GID + 1
except:
maxid = 1
try:
g = Goal(GID=maxid, description=dtw[0], time=float(dtw[1]), weight=int(dtw[2]))
g.put()
self.response.out.write(simplejson.dumps("Submitted"))
except:
self.response.out.write(simplejson.dumps("Error"))
Now, here Manager checks the goals and approve it or not.. if approved then status will be stored as true in datastore else false
idsta = simplejson.loads(self.request.body)
try:
g = db.Query(Goal).filter("GID =", int(idsta[0])).get()
if g:
if idsta[1]:
g.Status=True
try:
del g.Comments
except:
None
else:
g.Status=False
g.Comments=idsta[2]
db.put(g)
self.response.out.write(simplejson.dumps("Submitted"))
except:
self.response.out.write(simplejson.dumps("Error"))
Now, this is where im stuck..."filter('status=',True)".. this is returning all the entities which has status true.. means which are approved.. i want those entities which are approved AND which have not been assessed by employee yet..
def get(self):
t = []
for g in Goal.all().filter("Status = ",True):
t.append([g.GID, g.description, g.time, g.weight, g.Emp])
self.response.out.write(simplejson.dumps(t))
def post(self):
idasm = simplejson.loads(self.request.body)
try:
g = db.Query(Goal).filter("GID =", int(idasm[0])).get()
if g:
g.AsmEmp=idasm[1]
db.put(g)
self.response.out.write(simplejson.dumps("Submitted"))
except:
self.response.out.write(simplejson.dumps("Error"))
How am I supposed to do this? as I know that if I add another filter like "filter('AsmEmp =', not None)" this will only return those entities which have the AsmEmp attribute what I need is vice versa.
You explicitly can't do this. As the documentation states:
It is not possible to query for entities that are missing a given property.
Instead, create a property for is_assessed which defaults to False, and query on that.
could you not simply add another field for when employee_assessed = db.user...
and only populate this at the time when it is assessed?
The records do not lack the attribute in the datastore, it's simply set to None. You can query for those records with Goal.all().filter('status =', True).filter('AsmEmp =', None).
A few incidental suggestions about your code:
'Status' is a rather unintuitive name for a boolean.
It's generally good Python style to begin properties and attributes with a lower-case letter.
You shouldn't iterate over a query directly. This fetches results in batches, and is much less efficient than doing an explicit fetch. Instead, fetch the number of results you need with .fetch(n).
A try/except with no exception class specified and no action taken when an exception occurs is a very bad idea, and can mask a wide variety of issues.
Edit: I didn't notice that you were using an Expando - in which case #Daniel's answer is correct. There doesn't seem to be any good reason to use Expando here, though. Adding the property to the model (and updating existing entities) would be the easiest solution here.

Categories