Django if elif else statement - python

I'm trying to print the result according to the user's age selection in the form, but my if,elif and else statements are not working.
class Quiz(models.Model):
age_choices = (('10-12', '10-12'),
('13-16', '13-16'),
('17-20', '17-20'),
('21-23','21-23'),
)
age = models.CharField(max_length = 100, choices = age_choices)
views.py
def create_order(request):
form = QuizForm(request.POST or None)
if request.method == 'POST':
quiz = Quiz.objects
if quiz.age=='10-12':
print("10-12")
elif quiz.age=='13-16':
print("13-16")
elif quiz.age=='17-20':
print("17-20")
elif quiz.age=='21-23':
print("21-23")
else:
return None
context = {'form':form}
return render(request, "manualupload.html", context)

quiz = Quiz.objects will return a django.db.models.manager.Manager object and this can be further used to fetch the objects from database belonging to that particular model. The appropriate query set will be quiz = Quiz.objects.all() Then you will get the list of all objects in that belong to Quiz model. Once you get list of all objects, you can get the specific object either by indexing or by filtering using a specific query that you need to look into and then for that particular object you can get the age property.
Refer to official django documentation about creating queries for more information.

As #Abhijeetk431 mentioned, your issue lies in quiz = Quiz.objects.
If you use type(quiz), you will find that it outputs django.db.models.manager.Manager. This is not what you want, as age is a property of the Quiz class, not the Manager class.
For starters, refer to this.
This will return you a Queryset list, something akin to an Excel table. age is akin to the column in the table. To get age, what you want is the row (the actual Quiz object) in said table, which you can achieve using get or using the square brackets [].
Thus, your code should look something like this:
Model.objects.all()[0]
That would return the correct object(only the first row) and allow you to get the column value.
However, further clarification will be needed though, to know exactly what your problem is aside from 'it doesn't work'. How did you know your code is not working; what did the debugger tell you?

Related

Filtering by method value - too many SQL variables error

One of my views needs to filter a queryset by a method value, example:
invoices_ids = list(map(lambda inv: inv.id, filter(lambda inv: inv.status().lower() == request['status'], invoices)))
invoices = invoices.filter(id__in = invoices_ids)
The status method comes from something like this:
class Invoice(models.Model):
(...)
def status(self):
if self.canceled:
return 'Canceled'
elif self.passed_date:
return 'Passed'
elif self.req_date:
return 'Requested'
return 'Inserted'
Problem is this kind of filtering gives me an OperationalError "too many SQL variables".. I guess there are too many invoices with a specific status, and the filter id__in gets a gigantic list.
How can i overcome this? (To filter by status without having to save into another model variable)

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…

Random Option In Django Drop Down Form

I've been picking my brain trying to figure this out and so now I turn to the community for help.
I'm using models to create a form in Django and I want to add a Random option to a few of the drop-down choices.
Here is a general idea of what I'm working with:
models.py
Character(models.Model):
name = models.CharField(max_length=255,unique=True)
age = models.PositiveIntegerField(default=0)
gender = models.CharField(max_length=20,choices=creation_choices.GENDERS)
race = models.CharField(max_length=500,choices=creation_choices.RACE)
creation_choices.py
GENDERS = (
('male',"Male"),
("female","Female"),
("unknown","Unknown"),
)
RACE = (
('human','Human'),
('elf','Elf'),
('dwarf','Dwarf'),
)
What I am trying to do is add a way for users to select Random and it returns one of the other values. I tried a lot of different methods but most returned an error. When I created a function with random.choice() and pushed that through it seemed to work, but for some reason always returned the same value.
Any help would be greatly appreciated!
add (None,'Random') to choice sets and on the model-fields in question declare
default=select_random_gender and default=select_random_race as well as blank=False, null=False.
declare these functions:
def select_random_gender():
selection = random.choice(GENDERS)[0]
return selection if selection else select_random_gender()
def select_random_race():
selection = random.choice(RACE)[0]
return selection if selection else select_random_race()

Django form field instance variable

In order to make a simple captacha-like field, I tried the following:
class CaptchaField(IntegerField):
def __init__(self, *args, **kwargs):
super(CaptchaField, self).__init__(*args, **kwargs)
self.reset()
def reset(self):
self.int_1 = random.randint(1, 10)
self.int_2 = random.randint(1, 10)
self.label = '{0} + {1}'.format(self.int_1, self.int_2)
def clean(self, value):
value = super(CaptchaField, self).clean(value)
if value != self.int_1 + self.int_2:
self.reset()
raise ValidationError(_("Enter the result"), code='captcha_fail')
return True
Every time my answer is wrong, the label is changed as expected but the test is performed against the first values of int_1 and int_2 and not against the newly randomly generated values.
I don't understand how Field object are created and why I can't access the values of my field.
Thanks in advance
Have a think about how this works in your view. When you render the form, the field is instantiated and sets the label to your random values, which is fine. Now, the user posts back to the view: what happens? Well, the form is instantiated again, as is the field, and the field is set to two new random values. Not surprisingly, this won't match up to the previous value, because you haven't stored that anywhere.
To do anything like this, you need to store state somewhere so it is preserved between requests. You could try putting it in the session, perhaps: or, a better way might be to hash the two values together and put them in a hidden field, then on submit hash the submitted value and compare it against the one in the hidden field. This would probably need to managed at the form level, not the field.

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