How can I get at the Labels data from within my Task model?
class Task(db.Model):
title = db.StringProperty()
class Label(db.Model):
name = db.StringProperty()
class Tasklabel(db.Model):
task = db.ReferenceProperty(Task)
label = db.ReferenceProperty(Label)
creating the association is no problem, but how can I get at the labels associated with a task like:
task = Task.get('...')
for label in task.labels
This worked for me with your current datamodel:
taskObject = db.Query(Task).get()
for item in taskObject.tasklabel_set:
item.label.name
Or you could remove the Label class and just do a one-to-many relationship between Task and TaskLabel:
class Task(db.Model):
title = db.StringProperty()
class TaskLabel(db.Model):
task = db.ReferenceProperty(Task)
label = db.StringProperty()
Then
taskObject = db.Query(Task).get()
for item in taskObject.tasklabel_set:
item.label
Here is a tip from the Google article on modeling relationships in the datastore
By defining it as a ReferenceProperty, you have created a property that can only be assigned values of type 'Task'. Every time you define a reference property, it creates an implicit collection property on the referenced class. By default, this collection is called _set. In this case, it would make a property Task.tasklabel_set.
The article can be found here.
I also recommend playing around with this code in the interactive console on the dev appserver.
Don't you want a ListProperty on Task like this to do a many-to-many?
class Label(db.Model)
name = db.StringProperty()
#property
def members(self):
return Task.gql("WHERE labels = :1", self.key())
class Task(db.Model)
title = db.StringProperty();
labels = db.ListProperty(db.Key)
Then you could do
foo_label = Label.gql("WHERE name = 'foo'").get()
task1 = Task.gql("WHERE title = 'task 1'").get()
if foo_label.key() not in task1.labels:
task1.labels.append(foo_label.key())
task1.put()
There's a thorough article about modeling entity relationships on Google code. I stole the code above from this article.
Related
I am failing to find a way I can create a self-referencing table using peewee. I am trying to create an entity similar to one on this article.
I have tried this solution here and it doesn't seem to give me the results that I want.
class Customer(Model):
name = TextField()
class CustomerDepartment(Model):
refid = ForeignKeyField(Customer, related_name='customer')
id = ForeignKeyField(Customer, related_name='department')
These are documented here: http://docs.peewee-orm.com/en/latest/peewee/models.html#self-referential-foreign-keys
class Department(BaseModel):
parent = ForeignKeyField('self', null=True, backref='children')
name = CharField()
Example use:
root = Department.create(name='root')
d1 = Department.create(parent=root, name='Dept 1')
# etc.
I'm using the pythons factory_boy package to create instances of models for testing purposes.
I want to pass the parameters used when calling Facotry.create() to all the SubFactories in the Factory being called.
Here's how I do it now:
Example 1:
I have to explicitly set the company when calling the SubFactory (the BagFactory)
class BagTrackerFactory(BaseFactory):
company = factory.SubFactory(CompanyFactory)
bag = factory.SubFactory(BagFactory, company=factory.SelfAttribute("..company"))
class BagFactory(BaseFactory):
company = factory.SubFactory(CompanyFactory)
Example 2:
In this example, I have to add company to Params in the BagFactory, so I can pass it down to ItemFactory which has the company parameter.
class BagTrackerFactory(BaseFactory):
company = factory.SubFactory(CompanyFactory)
bag = factory.SubFactory(BagFactory, company=factory.SelfAttribute("..company"))
class BagFactory(BaseFactory):
item = factory.SubFactory(ItemFactory, company=factory.SelfAttribute("..company"))
class Params:
company = factory.SubFactory(CompanyFactory)
class ItemFactory(BaseFactory):
company = factory.SubFactory(CompanyFactory)
The reason why I do it like this is that it saves time and it makes sense that the Bag belongs to the same company as the BagTracker when created by the same Factory.
Note: the BaseFactory is factory.alchemy.SQLAlchemyModelFactory
Question:
What I would like is to have company (and all the other parameters) from the parent Factory be passed down to SubFactories without having to pass it explicitly. And this continues downstream all the way to the last SubFactory, so every model has the same company, from the topmost parent Factory to the lowest child SubFactory. I hope you understand what I'm saying.
Is there an easy way to do this? Like some option in the factory-boy package?
EDIT:
I ended up doing it the long way, passing down parameters manually. In this example, I'm showing both cases: when the parent factory has the company parameter(BagTrackerFactory) and doesn't have it but must pass it downstream (BagFactory).
class CompanyFactory(BaseFactory):
id = get_sequence()
class Meta:
model = Company
class ItemFactory(BaseFactory):
id = get_sequence()
owner = factory.SubFactory(CompanyFactory)
owner_id = factory.SelfAttribute("owner.id")
class Meta:
model = Item
class BagFactory(BaseFactory):
id = get_sequence()
item = factory.SubFactory(ItemFactory, owner=factory.SelfAttribute("..company"))
item_id = factory.SelfAttribute("item.id")
class Params:
company = factory.SubFactory(CompanyFactory)
class Meta:
model = Bag
class BagTrackerFactory(BaseFactory):
id = get_sequence()
company = factory.SubFactory(CompanyFactory)
company_id = factory.SelfAttribute("company.id")
item = factory.SubFactory(ItemFactory, owner=factory.SelfAttribute("..company"))
item_id = factory.SelfAttribute("item.id")
bag = factory.SubFactory(BagFactory, company=factory.SelfAttribute("..company"))
bag_id = factory.SelfAttribute("bag.id")
class Meta:
model = BagTracker
This is possible, but will have to be done specifically for your codebase.
At its core, a factory has no knowledge of your models' specific structure, hence can't forward the company field — for instance, some models might not accept that field in their __init__, and providing the field would crash.
However, if you've got a chain where the field is always accepted, you may use the following pattern:
class WithCompanyFactory(factory.BaseFactory):
class Meta:
abstract = True
company = factory.Maybe(
"factory_parent", # Is there a parent factory?
yes_declaration=factory.SelfAttribute("..company"),
no_declaration=factory.SubFactory(CompanyFactory),
)
This works thanks to the factory_parent attribute of the stub used when building a factory's parameters: https://factoryboy.readthedocs.io/en/stable/reference.html#parents
This field either points to the parent (when the current factory is called as a SubFactory), or to None. With a factory.Maybe, we can copy the value through a factory.SelfAttribue when a parent is defined, and instantiate a new value.
This can be used afterwards in your code:
class ItemFactory(WithCompanyFactory):
pass
class BagFactory(WithCompanyFactory):
item = factory.SubFactory(ItemFactory)
class BagTrackerFactory(WithCompanyFactory):
bag = factory.SubFactory(BagFactory)
>>> tracker = BagTrackerFactory()
>>> assert tracker.company == tracker.bag.company == tracker.bag.item.company
... True
# It also works starting anywhere in the chain:
>>> company = Company(...)
>>> bag = BagFactory(company=company)
>>> assert bag.company == bag.item.company == company
... True
If some models must pass the company value to their subfactories, but without a company field themselves, you may also split the special WithCompanyFactory into two classes: WithCompanyFieldFactory and CompanyPassThroughFactory:
class WithCompanyFieldFactory(factory.Factory):
"""Automatically fill this model's `company` from the parent factory."""
class Meta:
abstract = True
company = factory.Maybe(
"factory_parent", # Is there a parent factory?
yes_declaration=factory.SelfAttribute("..company"),
no_declaration=factory.SubFactory(CompanyFactory),
)
class CompanyPassThroughFactory(factory.Factory):
"""Expose the parent model's `company` field to subfactories declared in this factory."""
class Meta:
abstract = True
class Params:
company = factory.Maybe(
"factory_parent", # Is there a parent factory?
yes_declaration=factory.SelfAttribute("..company"),
no_declaration=factory.SubFactory(CompanyFactory),
)
I am struggling to understand django models relationship.
I have this arborescence:
A train have cars, and those cars are divided into parts. Then those parts all contains different references.
Like, for exemple, all the trains have the 6 cars, and the cars 6 parts. Each part have x reference to be associated.
I would like to use all of them in a template later on, where the user can select the train, the car and the part he worked on, then generate a table from his selections with only the references associated to the parts he selected.
It should update the train and the car (I'm trying to update a stock of elements for a company)
I dont really understand which model field give to each of them. After checking the doc, Ive done something like this but i am not convinced:
class Train(Car):
train = models.CharField(max_length=200)
id = models.CharField(primary_key='True', max_length=100)
selected = models.BooleanField()
class Meta:
abstract = True
class Car(Part):
car = models.CharField(max_length=200)
id = models.CharField(primary_key='True', max_length=100)
selected = models.BooleanField()
class Meta:
abstract = True
class Part(Reference):
part = models.CharField(max_length=200)
id = models.CharField(primary_key='True', max_length=100)
selected = models.BooleanField()
class Meta:
abstract = True
class Reference(models.Model):
reference = models.CharField(max_length=200)
id = models.CharField(primary_key='True', max_length=100)
selected = models.BooleanField()
def __str__(self):
return self.reference
Can someone please help me understand this so I can do well ? Thanks!!
1-)if you add abstract = True in your Model Meta class, your class doesn't created on database as a table. If you store data for any class, you mustn't define abstract = True.
2-)For relations, you can use models.ForeignKey . If you add a class into brackets of another class, it names: inheritance.(You can think like parent-child relation). In database management, we can use foreignkey for one-to-many relationship.
3-)In Django ORM, id field automatically generated. So you don't need to define id field.
If I understand correctly, also you want to store parts of user's selected.
So, your model can be like that:
class Train(models.Model):
name = models.CharField(max_length=200) # I think you want to save name of train
class Car(models.Model):
train = models.ForeignKey(Train,on_delete=models.Cascade)
name = models.CharField(max_length=200)
class Part(models.Model):
car = models.ForeignKey(Car,on_delete=models.Cascade)
name = models.CharField(max_length=200)
class Reference(models.Model):
part = models.ForeignKey(Part,on_delete=models.Cascade)
name = models.CharField(max_length=200)
def __str__(self):
return self.reference
#addtional table for storing user's references
class UserReference(models.Model):
user = models.ForeignKey(User,on_delete=models.Cascade)
reference = models.ForeignKey(Reference,on_delete=models.Cascade)
name = models.CharField(max_length=200)
With this definitions, you can store user's definition on UserReference table. And with Django Orm, you can access train object from UserReferenceObject.
#user_reference: UserReference object like that result of UserReference.objects.first()
user_reference.reference.part.car.train.name
I am trying to show a M2M field in a django-table2 as seen in Django-tables2: How to use accessor to bring in foreign columns? and Accessing related models with django-tables2
Using: foreigncolumn = tables.Column(accessor='foreignmodel.foreigncolumnname'), I only see a '--'...
# The models:
class Organism(models.Model):
species_name = models.CharField(max_length=200)
strain_name = models.CharField(max_length=200)
eukaryotic = models.BooleanField(default=True)
lipids = models.ManyToManyField('Lipid',blank=True)
class Lipid(models.Model):
lm_id = models.CharField(max_length=100)
common_name = models.CharField(max_length=100,blank=True)
category = models.CharField(max_length=100,blank=True)
#The tables
class OrganismTable(tables.Table):
name = tables.LinkColumn('catalog:organism-detail', text=lambda record: record.species_name, args=[A('pk')])
lp = tables.Column(accessor='Lipid.common_name')
class Meta:
model = Organism
sequence = ['name','lp']
exclude = ['id','species_name']
Any idea what I'm doing wrong?
This does not work so easily for ManyToManyFields because of the simple way Accessor works. You could display the repr of the related QuerySet via 'lipids.all' but that does not seem sufficient here. You can, however, add a property (or method) to your Organism model and use it in the accessor. This way, you can display any custom information related to the instance:
class Organism(models.Model):
# ...
#property
def lipid_names(self):
return ', '.join(l.common_name for l in self.lipids.all()) # or similar
class OrganismTable(tables.Table):
# ...
lp = tables.Column(accessor='lipid_names')
I would recommend then to add a prefetch_related('lipids') to the Organism QuerySet that you pass to the table for better performance.
I've had some data being gathered in production for a couple of days with, lets say, the following model:
class Tags(ndb.Model):
dt_added = ndb.DateTimeProperty(auto_now_add=True)
s_name = ndb.StringProperty(required=True, indexed=True)
Imagine I now add a new property to the model:
class Foo(ndb.Model):
is_valid = ndb.BooleanProperty(default=False)
some_key = ndb.KeyProperty(repeated=True)
class Tags(ndb.Model):
dt_added = ndb.DateTimeProperty(auto_now_add=True)
name = ndb.StringProperty(required=True, indexed=True)
new_prop = ndb.StructuredProperty(Foo)
... and gather some more data with this new model.
So now I have a portion of data that has the property new_prop set, and another portion that does not have it set.
My question is: how to I query for the data with the new property new_prop NOT set?
I've tried:
query_tags = Tags.query(Tags.new_prop == None).fetch()
But does not seem to get the data without that property set... Any suggestions?
Thanks!
The Datastore distinguishes between an entity that does not possess a property and one that possesses the property with a null value (None).
It is not possible to query for entities that are specifically lacking a given property. One alternative is to define a fixed (modeled) property with a default value of None, then filter for entities with None as the value of that property.