I am unable to read the column of another table which is joined. It throws AttributeError
class Component(Model):
id = IntegerField(primary_key=True)
title = CharField()
class GroupComponentMap(Model):
group = ForeignKeyField(Component, related_name='group_fk')
service = ForeignKeyField(Component, related_name='service_fk')
Now the query is
comp = (Component
.select(Component, GroupComponent.group.alias('group_id'))
.join(GroupComponent, on=(Component.id == GroupComponent.group))
)
for row in comp:
print row.group_id
Now I get an error AttributeError: 'Component' object has no attribute 'group_id'
If you just want to directly patch the group_id attribute onto the selected Component, call .naive(). This instructs peewee that you don't want to reconstruct the graph of joined models -- you just want all attributes patched onto a single Component instance:
for row in comp.naive():
print row.group_id # This will work now.
Related
Using PeeWee on top of SQLite, I am trying to do a left outer join between two tables that do not have a ForeignKey relation defined. I can get the data if the right table an entry that matches the left table, but if there is no match, the columns in the right table do not make it into the returned models.
class BaseModel(Model):
class Meta:
database = db
class Location(BaseModel):
location_key = CharField(primary_key=True)
lat = FloatField(null = False)
lon = FloatField(null = False)
class Household(BaseModel):
name = CharField(null=True)
location_id = CharField(null=True)
I am trying to do something like:
for h in Household.select(Household,Location).join(Location, on=(Household.location_id == Location.location_key), join_type=JOIN.LEFT_OUTER):
print(type(h), h, h.location, h.location.lat)
This works if Household.location_id matches something in Location, but if Household.location_id is None (null), then I get an AttributeError: 'Household' object has no attribute 'location'
I would have expected location to be present, but have a valid of None.
How can I check for the existence of location before using it? I am trying to avoid using ForeignKey, there are a lot of mismatches between Household.location_id and Location.location_key and PeeWee really gets angry about that...
I think I understand what you're trying to do after re-reading. What I'd suggest is to use Peewee's "on" keyword argument in the join, which can patch the related Location (if it exists) onto a different attr than "location":
query = (HouseHold
.select(HouseHold, Location)
.join(Location, on=(HouseHold.location_id == Location.location_key),
attr='location_obj', join_type=JOIN.LEFT_OUTER))
Then you can check the "location_obj" to retrieve the related object.
for house in query:
# if there was a match, get the location obj or None.
location_obj = getattr(house, 'location_obj', None)
# the location_id is still present.
print(house.location_id, location_obj)
Found my own answer. Implement __getattr__(self) in the Household model, and return None if the name is 'location'. __getattr__(self) is only called if there is no property with that name.
I have two Django models and connected via Foreignkey element and in the second model I need to use the firs model's attribute - example (pseudocode):
Class Category(models.Model):
c_attribute = "Blue"
Class Object(models.Model):
o_category = models.ForeignKey(Category)
o_color = o_category.c_attribute
The key here is the last line - I got error saying that ForeignKey object has no attribute c_attribute.
Thanks
Because o_category is a Key to a Category, not a Category itself!
you can check by type(o_category) to check is not Category!
so you have access to related Cateogry of a Object in other parts of application when connected to database.for example in shell you can write:
c = Category()
c.save()
o = Object(o_category = c, ...) #create Object with desired params
... #some changes to o
o.save()
o.o_category.c_attribute #this will work! :)
You can use to_field='', but that might give you an error as well.
Class Object(models.Model):
o_category = models.ForeignKey(Category)
o_color = models.ForeignKey(Category, to_field="c_attribute")
The best thing is do create a function in your Object model, that would get you the categories c_attribute like so:
def get_c_attribute(self):
return self.o_category.c_attribute
Is it possible to override values inside a Model? I am getting 'MyModel' object does not support item assignment.
-- model.py
class Slider(models.Model):
name = models.CharField(max_length=255)
rows = models.SmallIntegerField(max_length=2)
cat = models.ForeignKey(Products)
order = models.SmallIntegerField()
status = models.BooleanField(default=0)
--- views.py
rows = Slider.objects.all().order_by('order')
for item in rows:
product = Products.objects.filter(cat=item.cat)[:10]
item['product'] = product
print item
Exception Value:'Slider' object does not support item assignment
If you want to persist the value of product in the database for a particular Slider, then add a ForeignKey field to Slider:
class Slider(models.Model):
...
product = models.ForeignKey(Products)
If you want to have stored temporarily, just add a regular attribute to Slider to hold it.
class Slider(models.Model):
...
product = None
In either case, you'd set it like this:
rows = Slider.objects.all().order_by('order')
for item in rows:
item.product = ...
If you prefer you can just leave out the attribute declaration entirely, but this will mean if you go to check for item.product, without having first set it, you would get an AttributeError.
I am using the code below to get all values from a row.
from google.appengine.ext import db
from python_lib.models import Field
field = Field.all()[0]
names = Field.properties()
for key in names:
print field.get(key)
But it giving the following error,
BadKeyError: Invalid string key name.
You are confusing too different api's in this code.
for key in names:
print field.get(key)
Your get() call is invalid, as your are actually trying to call a class method to fetch an entity from the datastore - see the docs for this method https://developers.google.com/appengine/docs/python/datastore/modelclass#Model_get .
To get a property by name from an instance of field (your object) you should be using getattr
as in
for key in names:
print getattr(field,key)
or all alternately use get_value_for_datastore(model_instance) of the property object, which is returned from properties() call along with the name of the property.
Is this what you want?
Code:
from google.appengine.ext import db
class Field(db.Model):
author = db.StringProperty()
content = db.StringProperty(multiline=True)
date = db.DateTimeProperty(auto_now_add=True)
a = Field(author="me")
a.put()
EDIT:
field = Field.all()
for f in field:
print f.author
print f.content
props = Field.properties()
print props
for vals in props:
print vals
output:
<__main__.Field object at 0xb8c9e4c>
{'content': <google.appengine.ext.db.StringProperty object at 0xb7c0aec>, 'date': <google.appengine.ext.db.DateTimeProperty object at 0xb7c06cc>, 'author': <google.appengine.ext.db.StringProperty object at 0xb7c0f6c>}
content
date
author
I get this error message:
TypeError: 'City' object does not support indexing
when this is my model:
class City(db.Model):
region = db.ReferenceProperty()
name = db.StringProperty()
image = db.BlobProperty()
vieworder = db.IntegerProperty()
areacode = db.IntegerProperty()
and this is my query
items = Item.all().filter('modified >', timeline).filter('published =', True).order('-modified').filter('cities =',city[0].key()).fetch(PAGESIZE + 1)`
Can you tell my how I should make my query or model my class definitions? I use listproperty(db.Key) to model relationships with references and I thought I could filter like the above query since it worked for one item. What should I do?
city[0].key()
is the cause of your error. Chances are you thought city was a list, but it's actually a single item, or some such.