I'm using the peewee orm and I would like to know how to do a reverse foreignkey query.
These are my models:
class Device(BaseModel):
mac = CharField()
ip = CharField()
class Metrics(BaseModel):
device = ForeignKeyField(Device, related_name="metrics")
sensor = CharField()
analog = FloatField(null = True)
timestamp = DateTimeField()
I would like to know the simplest way to get all the Devices that have a Metric with a field sensor="temperature".
I can solve it with various querys and some iteration, but I wonder if there is a more direct way to do it.
Thanks
One way:
Device.select().join(Metric).where(Metric.sensor == 'temperature')
Another way:
Device.select().where(fn.EXISTS(
Metric.select().where((Metric.sensor == 'temperature') & (Metric.device == Device.id))
))
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.
Hello to the stackoverflow team,
I have the following two django tables:
class StraightredFixture(models.Model):
fixtureid = models.IntegerField(primary_key=True)
soccerseason = models.IntegerField(db_column='soccerSeason') # Field name made lowercase.
hometeamid = models.IntegerField()
awayteamid = models.IntegerField()
fixturedate = models.DateTimeField()
fixturestatus = models.CharField(max_length=24)
fixturematchday = models.IntegerField()
hometeamscore = models.IntegerField()
awayteamscore = models.IntegerField()
class Meta:
managed = False
db_table = 'straightred_fixture'
class StraightredTeam(models.Model):
teamid = models.IntegerField(primary_key=True)
teamname = models.CharField(max_length=36)
teamcode = models.CharField(max_length=5)
teamshortname = models.CharField(max_length=24)
class Meta:
managed = False
db_table = 'straightred_team'
In the views.py I know I can put the following and it works perfectly:
def test(request):
fixture = StraightredFixture.objects.get(fixtureid=136697)
return render(request,'straightred/test.html',{'name':fixture.hometeamid})
As I mentioned above, this all works well but I am looking to return the teamname of the hometeamid which can be found in the StraightredTeam model.
After some looking around I have been nudged in the direction of "select_related" but I am unclear on how to implement it in my existing tables and also if it is the most efficient way for this type of query. It feels right.
Please note this code was created using "python manage.py inspectdb".
Any advice at this stage would be greatly appreciated. Many thanks, Alan.
See model relationships.
Django provides special model fields to manage table relationships.
The one suiting your needs is ForeignKey.
Instead of declaring:
hometeamid = models.IntegerField()
awayteamid = models.IntegerField()
which I guess is the result of python manage.py inspectdb, you would declare:
home_team = models.ForeignKey('<app_name>. StraightredTeam', db_column='hometeamid', related_name='home_fixtures')
away_team = models.ForeignKey('<app_name>. StraightredTeam', db_column='awayteamid', related_name='away_fixtures')
By doing this will, you tell the Django ORM to handle the relationship under the hood, which will allow you to do such things as:
fixture = StraightredFixture.objects.get(fixtureid=some_fixture_id)
fixture.home_team # Returns the associated StraightredTeam instance.
team = StraightredTeam.objects.get(team_id=some_team_id)
team.home_fixtures.all() # Return all at home fixtures for that team.
I am not sure if this makes sense for Managed=False, but I suppose the sane way of doing it in Django would be with
home_team = models.ForeignKey('StraightRedFixture', db_column='fixtureid'))
And then just using fixture.home_team instead of doing queries by hand.
there are two tables:
class TBLUserProfile(models.Model):
userid = models.IntegerField(primary_key=True)
relmusicuid = models.IntegerField()
fansnum = models.IntegerField()
class TSinger(models.Model):
fsinger_id = models.IntegerField()
ftbl_user_profile = models.ForeignKey(TBLUserProfile, db_column='Fsinger_id')
I want to get Tsinger info and then order by TBLUserProfile.fansnum, I know how to write sql query: select * from t_singer INNER JOIN tbl_user_profile ON (tbl_user_profile.relmusicuid=t_singer.Fsinger_id) order by tbl_user_profile.fansnum, but I don't want to use model raw function. relmusicuid is not primary key otherwise I can use ForeignKey to let it work. How can I use django model to achieve this?
You can do like this :
Tsinger.objects.all().order_by('ftbl_user_profile__fansnum')
For information about Django JOIN :
https://docs.djangoproject.com/en/1.8/topics/db/examples/many_to_one/
Sorry for probably simple question but I'm a newby in Django and really confused.
I have an ugly legacy tables that I can not change.
It has 2 tables:
class Salespersons(models.Model):
id = models.IntegerField(unique=True, primary_key=True)
xsin = models.IntegerField()
name = models.CharField(max_length=200)
surname = models.CharField(max_length=200)
class Store(models.Model):
id = models.IntegerField(unique=True, primary_key=True)
xsin = models.IntegerField()
brand = models.CharField(max_length=200)
So I suppose I can not add Foreign keys in class definitions because they change the tables.
I need to execute such sql request:
SELECT * FROM Salespersons, Store INNER JOIN Store ON (Salespersons.xsin = Store.xsin);
How can I achieve it using Django ORM?
Or I'm allowed to get Salespersons and Store separately i.e.
stores = Store.objects.filter(xsin = 1000)
salespersons = Salespersons.objects.filter(xsin = 1000)
Given your example query, are your tables actually named Salespersons/Store?
Anyway, something like this should work:
results = Salespersons.objects.extra(tables=["Store"],
where=["""Salespersons.xsin = Store.xsin"""])
However, given the names of the tables/models it doesn't seem to me that an inner join would be logically correct. Unless you always have just 1 salesperson per store with same xsin.
If you can make one of the xsin fields unique, you can use a ForeignKey with to_field to generate the inner join like this:
class Salespersons(models.Model):
xsin = models.IntegerField(unique=True)
class Store(models.Model):
xsin = models.ForeignKey(Salespersons, db_column='xsin', to_field='xsin')
>>> Store.objects.selected_related('xsin')
I don't see why you can't use the models.ForeignKey fields even if the database lacks the constraints -- if you don't explicitly execute the SQL to change the database then the tables won't change. If you use a ForeignKey then you can use Salespersons.objects.select_related('xsin') to request that the related objects are fetched at the same time.
I have two simple models in my Django app. Here's what they look like:
class Host(models.Model):
url = models.URLField(max_length= 200)
ssl = models.BooleanField(default = False)
class Query(models.Model):
host = models.ForeignKey(Host)
date = models.DateTimeField(auto_now_add = True)
latency = models.FloatField(null = True)
success = models.BooleanField(default = False)
error = models.CharField(max_length= 2000, null = True)
When i access the Host model, I only have access to the two fields url and ssl. When querying the Host model, I would like three extra fields to computed and returned dyanmicaly. These are the average_latency which would be the average of the not-null latency field of all the child Query records so i can access it something like this:
t = Tracker.objects.get(id = 1)
t.url
t.average_latency
Could someone please explain how I can do this or point me to some examples/documentation?
Thank you.
You can just use class properties:
class Host(models.Model):
.
.
.
#property
def average_latency(self):
# calculate latency from Query model ...
return latency
Bear in mind that this is a read-only property.
You can check django-denorm, it's pretty much about what you're trying to achievie. I also have some flashbacks that there are other similar django apps.