samedi 29 novembre 2014

python - Django ORM-produit-vectoriel Stack Overflow


I have the following schema:


class PCs(models.Model):
model = models.ForeignKey(Products, primary_key=True)
speed = models.IntegerField(max_length=256, blank = True, null=True)
ram = models.IntegerField(max_length=256, blank = True, null=True)
hd = models.IntegerField(max_length=256, blank = True, null=True)
price = models.IntegerField(max_length=256, blank = True, null=True)


class Printers(models.Model):
model = models.ForeignKey(Products, primary_key=True)
color = models.BooleanField()
type = models.CharField(max_length=256, blank = True, null=True)
price = models.IntegerField(max_length=256, blank = True, null=True)

I'm trying to run the following SQL query:


SELECT *
FROM PCs P, Printers T
WHERE p.price + t.price <= 1000

But I'm completely lost on how to do this with Django's ORM. Is the only way to do this but getting all the objects from both PCs and Printers and checking all possible combinations?




ORM:


pcs = PCs.objects.filter(price__lte=1000)
printers = Printers.objects.filter(price__lte=1000)

In pcs and printer we can found answer to the question. And our SQL inquiry is no correctly. Or make a related_name, and make one query from product.




A possible solution is to use raw SQL, see documentation here.


Unfortuantely, the django ORM doesn't provide a clean way to join 2 tables that don't have some kind of relationship. Just because it isn't clean doesn't mean you can't do it!


Note that I can't actually tell what your raw sql table names are, so you'll have to fill that in yourself. If I had to guess they would be app_name_p_cs and app_name_printers. You can use ./manage.py dbshell to go find out.


You could try something like:


pcs = PCs.objects.raw(
"SELECT "
" pc_table.model_id, "
" pc_table.speed, "
" pc_table.ram, "
" pc_table.hd, "
" pc_table.price, "
" printer_table.model_id as printer_model_id, "
" printer_table.color as printer_color, "
" printer_table.type as printer_type, "
" printer_table.price as printer_price "
"FROM "
" pc_table, printer_table "
"WHERE "
" pc_table.price + printer_table.price <= 1000 "
)

pairs = []
for pc in pcs:
printer = Printers(
model_id=pc.printer_model_id,
color=pc.printer_color,
type=pc.printer_type,
price=pc.printer_price,
)
pairs.append((pc, printer))

As you can see, the extra values from the printer fields are just tacked on to the pc object you get with your ORM query, you just have to construct the printer object manually after that. I think it is a good idea to name the printer fields for the query so that the ORM does not confuse them for pc fields.


Also note that depending on what you plan to do with the result of this query, it may not even be necessary to construct the Printers objects at all.



I have the following schema:


class PCs(models.Model):
model = models.ForeignKey(Products, primary_key=True)
speed = models.IntegerField(max_length=256, blank = True, null=True)
ram = models.IntegerField(max_length=256, blank = True, null=True)
hd = models.IntegerField(max_length=256, blank = True, null=True)
price = models.IntegerField(max_length=256, blank = True, null=True)


class Printers(models.Model):
model = models.ForeignKey(Products, primary_key=True)
color = models.BooleanField()
type = models.CharField(max_length=256, blank = True, null=True)
price = models.IntegerField(max_length=256, blank = True, null=True)

I'm trying to run the following SQL query:


SELECT *
FROM PCs P, Printers T
WHERE p.price + t.price <= 1000

But I'm completely lost on how to do this with Django's ORM. Is the only way to do this but getting all the objects from both PCs and Printers and checking all possible combinations?



ORM:


pcs = PCs.objects.filter(price__lte=1000)
printers = Printers.objects.filter(price__lte=1000)

In pcs and printer we can found answer to the question. And our SQL inquiry is no correctly. Or make a related_name, and make one query from product.



A possible solution is to use raw SQL, see documentation here.


Unfortuantely, the django ORM doesn't provide a clean way to join 2 tables that don't have some kind of relationship. Just because it isn't clean doesn't mean you can't do it!


Note that I can't actually tell what your raw sql table names are, so you'll have to fill that in yourself. If I had to guess they would be app_name_p_cs and app_name_printers. You can use ./manage.py dbshell to go find out.


You could try something like:


pcs = PCs.objects.raw(
"SELECT "
" pc_table.model_id, "
" pc_table.speed, "
" pc_table.ram, "
" pc_table.hd, "
" pc_table.price, "
" printer_table.model_id as printer_model_id, "
" printer_table.color as printer_color, "
" printer_table.type as printer_type, "
" printer_table.price as printer_price "
"FROM "
" pc_table, printer_table "
"WHERE "
" pc_table.price + printer_table.price <= 1000 "
)

pairs = []
for pc in pcs:
printer = Printers(
model_id=pc.printer_model_id,
color=pc.printer_color,
type=pc.printer_type,
price=pc.printer_price,
)
pairs.append((pc, printer))

As you can see, the extra values from the printer fields are just tacked on to the pc object you get with your ORM query, you just have to construct the printer object manually after that. I think it is a good idea to name the printer fields for the query so that the ORM does not confuse them for pc fields.


Also note that depending on what you plan to do with the result of this query, it may not even be necessary to construct the Printers objects at all.


0 commentaires:

Enregistrer un commentaire