Google App Engine - Get from repeated StructuredProperty - google-app-engine

I have the following structures:
class UserOther(ndb.Model):
other_type = ndb.StringProperty(indexed = True)
other_data = ndb.StringProperty(indexed = False)
class User(ndb.Model):
name = ndb.StringProperty(default = "NULL", indexed = False)
email = ndb.StringProperty(default = "NULL", indexed = False)
active = ndb.BooleanProperty(default = True)
others = ndb.StructuredProperty(UserOther, repeated = True)
updated_at = ndb.DateTimeProperty(auto_now = True)
How can I use an User key id and a string for other_type(like "job") to get and be able to edit that information. I tried using the ancestor parameter, but perhaps I didn't do that correctly.
user_key = ndb.Key("User", user_id)
user = user_key.get()
other = UserOther.query(UserOther.other_type == "job", ancestor = user_key).get()
So if i print my user looks like this :
1425436064.0User(key=Key('User', 5171003185430528), active=True, email=u'NULL', name=u'NULL', others=[UserOther(other_data=u'0', other_type=u'job'), UserOther(other_data=u'0', other_type=u'times_worked'), UserOther(other_data=u'0', other_type=u'times_opened')], updated_at=datetime.datetime(2015, 3, 6, 10, 35, 24, 838078))
But if I print the job variable it is
1425436759.0None

You've misunderstood how to query for structured properties. The UserOther entity doesn't live on its own, it's part of the relevant User entity, so that's what you need to query.
The documentation explains exactly how to do this, but in summary you would do:
job = User.query(User.others.other_type == "job").get()

What I would do is get the user (by id) and then filter the 'others' in code:
user = User.get_by_id(user_key_id)
for other in user.others:
if other.other_type == 'job':
print other.other_data # do edits

Related

Add M2M field using create(): Django

I have a lot of doubts about managing the M2m field, I finally got a solution to add that data to a model, but there are still some issues, give me a solution to overcome this,
class CourseListSerializer(serializers.ModelSerializer):
instructors = serializers.SerializerMethodField()
image = FileField()
keyarea = CourseKeyAreaSerializer
subject = CourseSubjectsSerializer
sections = serializers.ListField(write_only=True)
beneficiaries = serializers.ListField(write_only=True)
section = CourseSectionSerializers
beneficiary = CourseBeneficiarySerializer
def create(self, validated_data):
data = validated_data
try:
new = Course.objects.create(image=data['image'], name=data['name'], description=data['description'], is_free=data['is_free'],
keyarea=data['keyarea'], subject=data['subject'])
new.save()
beneficiary_data = data['beneficiaries']
new.beneficiary.set(*[beneficiary_data])
section_data = data['sections']
new.section.set(*[section_data])
return new
except Exception as e:
e = "invalid data"
return e
here first creating the "new" object after that to set the M2M field like
"new.beneficiary.set(*[beneficiary_data])"
but is there any way to add beneficiary and section like this
"new = Course.objects.create(image=data['image'],name=data['name'], description=data['description'],is_free=data['is_free'],....)"

How to use 'contains' with manytomany field?

I have a model:
class Tasks(models.Model):
name = models.CharField(max_length = 50, null = True, blank = True)
assigned_to = models.ManyToManyField(User, null = True, blank = True)
I have to execute a query
tasks_for_myuser = Tasks.objects.filter(assigend_to__contains = myuser)
But this is throwing an error.
django.core.exceptions.FieldError: Related Field got invalid lookup: contains
Please help!
If you are trying to filter Tasks which has assigned_to field set to myuser, you can simply query like this.
tasks_for_myuser = Tasks.objects.filter(assigend_to = myuser)
You don't really require contains here, since it is a many-to-many field.

The best way to store data or query data on google app engine

I want to be able to store some data in app engine and I am looking for some help on the best way to store the data or retrieve the data through a query. I have a list of users and want them to be able to add cars they want to sell and enter a lower and upper limit they would accept. When a user is searching for a car and enters a price, if this price is between the lower and upper limits, it will return the car:
class User(ndb.Model):
username = ndb.StringProperty()
cars = ndb.StructuredProperty(Car, repeated = True)
datecreated = ndb.DateTimeProperty(auto_now_add = True)
date_last_modified = ndb.DateTimeProperty(auto_now = True)
class Car(ndb.Model):
lowerprice = ndb.IntegerProperty()
maxprice = ndb.IntegerProperty()
make = ndb.StringProperty()
model = ndb.StringProperty()
datecreated = ndb.DateTimeProperty(auto_now_add = True)
date_last_modified = ndb.DateTimeProperty(auto_now = True)
I can't filter on:
c = User.query(User.car.lowerprice >= int(self.carprice), User.car.maxprice < int(self.carprice)).get())
As it returns BadRequestError: Only one inequality filter per query is supported.
Should I structure or store the data differently to allow filtering on one inequality or should I try and use and and / or query?
Is there anything else you would recommend?
Try something like this:
holder = User.query(User.car.lowerprice >= int(self.carprice)).get())
results = filter(lambda x: x.car.maxprice < int(self.carprice), holder)
It boils down to having to programmably handling the second filter.

Query for repeated ndb.KeyProperty not working

What's wrong with my query?
Here are my models:
class Positions(ndb.Model):
title = ndb.StringProperty(indexed=True)
summary = ndb.TextProperty()
duties = ndb.TextProperty()
dateCreated = ndb.DateTimeProperty(auto_now_add=True)
dateUpdated = ndb.DateTimeProperty(auto_now=True)
class Applicants(ndb.Model):
name = ndb.StringProperty(indexed=True)
position = ndb.KeyProperty(kind=Positions,repeated=True)
file = ndb.BlobKeyProperty()
dateCreated = ndb.DateTimeProperty(auto_now_add=True)
dateUpdated = ndb.DateTimeProperty(auto_now=True)
Here is my query:
class AdminPositionInfoHandler(BaseHandler):
def get(self,positionKeyId):
user = users.get_current_user()
if users.is_current_user_admin():
positionKey = ndb.Key('Positions',int(positionKeyId))
position = positionKey.get()
applicants = Applicants.query(position=position.key).fetch() # the query
values = {
'position': position,
'applicants': applicants,
}
self.render_html('admin-position-info.html',values)
else:
self.redirect(users.create_login_url(self.request.uri))
What seems to be wrong in using the query:
applicants = Applicants.query(position=position.key).fetch()
I got this error:
File "C:\xampp\htdocs\angelstouch\main.py", line 212, in get
applicants = Applicants.query(position=position.key).fetch()
...
TypeError: __init__() got an unexpected keyword argument 'position'
I also tried using positionKey instead of position.key:
applicants = Applicants.query(position=positionKey).fetch()
I got this from "Ancestor Queries" section of GAE site:
https://developers.google.com/appengine/docs/python/ndb/queries
You don't pass arguments to query like that - ndb uses overridden equality/inequality operators, so you can express queries more 'naturally', with '==', '<', '>' etc., so:
applicants = Applicants.query(Applications.position==position.key).fetch()
The section in the on Filtering by Property Values gives some more examples.
(ancestor is a special-case for queries - it isn't a model property)

Apex Lookup Value copy to second Object

I have a trigger that moves the values from one object to another, but am stuck on how to move the values of the lookup fields from one to the other. what is the syntax? If you could show me the Company and the Chair_Rep ones that would be great!
<Lead> newLeadsList= new List<Lead>();
for (integer i=0; i<newContacts.size(); i++) {
if (newContacts[i].createlead__c == TRUE && oldContacts[i].createlead__c == FALSE ) {
newLeadsList.add(new Lead(
firstName = newContacts[i].firstName,
lastName = newContacts[i].lastName,
***Company = newContacts[i].account.name,***
Status = 'identified',
LeadSource = newContacts[i].leadsource ,
Product_Interest__c = 'CE',
//ContactLink__c = newContacts[i].ID,
Title = newContacts[i].title,
Email = newContacts[i].email,
//***Chair_Rep__c = newContacts[i].Chair_Rep__c***
Phone = newContacts[i].Phone,
MobilePhone = newContacts[i].MobilePhone,
// Address = newContacts[i].MailingAddress,
//Website = newContacts[i].Website,
nickname__c = newContacts[i].Nickname__c
Lookup fields should contain references (IDs) on records.
Is 'Company' a standard Lead field in your code?
***Company = newContacts[i].account.name,***
If so, then it's a Text(255) type field, which cannot be used as lookup.
If you need to make a lookup on a Contact's account record, then you can create a custom Lookup field on Lead with reference to Account. And then you could try this code (assuming ContactCompany is that custom lookup field :
ContactCompany__c = newContacts[i].AccountId
or
ContactCompany__c = newContacts[i].Account.Id
Chair_Rep__c and newContacts.Chair_Rep__c should be lookup fields on same object. Then this
Chair_Rep__c = newContacts[i].Chair_Rep__c
or this should work
Chair_Rep__c = newContacts[i].Chair_Rep__r.Id

Resources