DJANGO - Get values from model by join of two tables - python-3.x

I'm trying to get all data from a table by a model, i can get all data from the table this works ok, but i need get data from other table mapped by a foreign key to another table, this means i have a field called ID_USUARIO in Parcela Model and i want to get all data that have my actual query with the value from the other table called FULLNAME in Usuario Model.
How can i do that?
Usuario Model
class Usuario(Model):
ID_USER = models.AutoField(primary_key=True)
FULLNAME = models.CharField(max_length=500)
EMAIL = models.EmailField()
PASSWORD = models.CharField(max_length=450)
Parcela Model
class Parcela(Model):
"""docstring for Parcela."""
ID = models.AutoField(primary_key=True)
ID_USUARIO = models.ForeignKey(Usuario, on_delete=models.CASCADE)
ID_PARCELA = models.BigIntegerField()
A_DEAD_LEAVES = models.FloatField()
A_SOIL_DEPTH = models.FloatField()
A_LIGHT_FUEL = models.FloatField()
A_DUFF = models.FloatField()
A_MID_HEA_FUEL = models.FloatField()
A_SOIL_ROCK_COLOR = models.FloatField()
B_DOMINANT_VEG_TYPE = models.CharField(max_length=200)
B_FCOV = models.FloatField()
B_FOLIAGE_ALTERED = models.FloatField()
B_FREQ_LIVING = models.FloatField()
B_NEW_SPROUTS = models.FloatField()
C_DOMINANT_VEG_TYPE = models.CharField(max_length=200)
C_FCOV = models.FloatField()
C_FOLIAGE_ALTERED = models.FloatField()
C_FREQ_LIVING = models.FloatField()
C_LAI_CHANGE = models.FloatField()
D_DOMINANT_VEG_TYPE = models.CharField(max_length=200)
...
This is the query i'm doing
export = Parcela.objects.select_related('ID_USUARIO')
Result of query
ID,ID_USUARIO,ID_PARCELA,A_DEAD_LEAVES,A_SOIL_DEPTH,A_LIGHT_FUEL,A_DUFF,A_MID_HEA_FUEL,A_SOIL_ROCK_COLOR,B_DOMINANT_VEG_TYPE,B_FCOV,B_FOLIAGE_ALTERED,B_FREQ_LIVING,B_NEW_SPROUTS,C_DOMINANT_VEG_TYPE,C_FCOV,C_FOLIAGE_ALTERED,C_FREQ_LIVING,C_LAI_CHANGE,D_DOMINANT_VEG_TYPE,D_FCOV,D_GREEN_UNALTERAD,D_BLACK_BROWN,D_FREQ_LIVING,D_LAI_CHANGE,D_CHAR_HEIGHT,E_DOMINANT_VEG_TYPE,E_FCOV,E_GREEN_UNALTERAD,E_BLACK_BROWN,E_FREQ_LIVING,E_LAI_CHANGE,E_CHAR_HEIGHT,COORDINATE_X,COORDINATE_Y,DATE_CAPTURED,DATE_SAVED,PHOTO_1,PHOTO_2,PHOTO_3,PHOTO_4,PHOTO_5,SEVERITY
2,1,1,20.0,30.0,10.0,20.0,15.0,6.0,Cactus,12.0,11.0,13.0,3.0,Pasto,2.0,6.0,2.0,3.1,Arbol,1.2,14.0,8.0,4.0,0.5,2.0,Hongos,3.0,1.9,11.0,10.2,20.1,18.4,624811.32,665561.23,2019-08-27 16:56:20,2019-08-27 16:56:20,,,,,,Moderada
3,1,1,20.0,30.0,10.0,20.0,15.0,6.0,Cactus,12.0,11.0,13.0,3.0,Pasto,2.0,6.0,2.0,3.1,Arbol,1.2,14.0,8.0,4.0,0.5,2.0,Hongos,3.0,1.9,11.0,10.2,20.1,18.4,624811.32,665561.23,2019-08-27 16:56:20,2019-08-27 16:56:20,,,,,,Moderada
4,1,1,20.0,30.0,10.0,20.0,15.0,6.0,Cactus,12.0,11.0,13.0,3.0,Pasto,2.0,6.0,2.0,3.1,Arbol,1.2,14.0,8.0,4.0,0.5,2.0,Hongos,3.0,1.9,11.0,10.2,20.1,18.4,624811.32,665561.23,2019-08-27 22:46:52,2019-08-25 15:46:12,,,,,,Moderada
5,1,2,100.0,2.0,2.1,1.2,1.0,1.1,Margaritas,40.0,0.3,1.25,2.65,Pinos,2.0,6.0,2.0,3.1,Guayacan,1.2,14.0,8.0,4.0,0.5,2.0,Roble,3.0,1.9,11.0,10.2,20.1,18.4,624811.32,665561.23,2019-08-24 22:46:52,2019-08-28 15:46:12,,,,,,Alta
6,2,3,100.0,2.0,2.1,1.2,1.0,1.1,Cedro,40.0,0.3,1.25,2.65,Rosas,2.0,6.0,2.0,3.1,Savila,1.2,14.0,8.0,4.0,0.5,2.0,Eucalipto,3.0,1.9,11.0,10.2,20.1,18.4,624811.32,665561.23,2019-08-24 22:46:52,2019-08-28 15:46:12,,,,,,No Quemada

Yes, you are doing it correctly. One must use select_related to do join in django. you can verify the generated query
result = Parcela.objects.select_related('ID_USUARIO')
print(str(result.query))
# You can access ID_USARIO fields like this
print(result.first().ID_USARIO.FULLNAME)
To get rows in parcela table with a name, you can do reverse lookup. Then the query will be
result = Usuario.objects.get(FULLNAME='<name_to_filter>')
parcela_rows = result.parcela_set.all()

Related

How to store multiple values inside a foreign key field?

I need to add multiple categories to a brand field. Here is the code
class Brand_Category(models.Model):
"""
this model is use to store the data of products category
"""
name = models.CharField(max_length=50, unique=True, verbose_name="Brand Category Name")
slug = models.SlugField(max_length=140, unique=True, blank=True)
created_at = models.DateTimeField(auto_now_add=True, null=True, blank=True)
class Brand(models.Model):
"""
This model is use to store the data of products sub category
"""
user = models.ForeignKey(User, related_name='brand_user', on_delete=models.CASCADE,null=True,blank=True, default=None)
name = models.CharField(max_length=50, unique=True, verbose_name="Brand Name")
brand_img = models.FileField(verbose_name='Upload Image')
category = models.ForeignKey(Brand_Category, related_name='brand_category', on_delete=models.PROTECT, null=True)
slug = models.SlugField(max_length=140, unique=True, blank=True)
created_at = models.DateTimeField(auto_now_add=True, null=True, blank=True)
I have a brand form where I am adding multiple categories.
This categories are stored in the brand_category model, and i would like to save the id of multiple categories into one brand field. how can i add that?
i have found about onetomany field in django but it seems to have deprecated, and the other soultions are not similar to my problem. However, a cateogry is not strictly related to any brand.
Here is the insertion code
brand_name = request.POST["brand_name"]
image = request.FILES['image']
brand_category = request.POST.getlist("brand_category")
brand = models.Brand.objects.create(
user = request.user,
name = brand_name,
brand_img = image,
category_id = brand_category,
).save()
Try using many to many relationships as the brand_category_field. With this relationship you can have one brand related to multiple categories and yet a category can not be restricted to a single brand.
Foreign Key is One to Many Relation. In your case, one category can have many Many Brands so if the brand has to be in another category also means in that case you have to change the relationship from Foreign key relation to Many-to-Many Relation.
Check the below link for reference
https://docs.djangoproject.com/en/4.0/topics/db/examples/many_to_many/
class Brand(models.Model):
"""
This model is use to store the data of products sub category
"""
user = models.ForeignKey(User, related_name='brand_user', on_delete=models.CASCADE,null=True,blank=True, default=None)
name = models.CharField(max_length=50, unique=True, verbose_name="Brand Name")
brand_img = models.FileField(verbose_name='Upload Image')
category = models.ManyToManyField(Brand_Category,related_name='brand_category')
slug = models.SlugField(max_length=140, unique=True, blank=True)
created_at = models.DateTimeField(auto_now_add=True, null=True, blank=True)

Left Join in Django

I have the following models:
class Patient(models.Model):
patient_first_name = models.CharField(max_length=50)
patient_last_name = models.CharField(max_length=50)
patient_name = models.CharField(max_length=100)
patient_email = models.EmailField(max_length=100)
gender = models.CharField(max_length=50)
class PatientMedicalRecord(models.Model):
patient = models.ForeignKey(Patient)
mrn = models.CharField(max_length=50, unique=True)
patient_height = models.IntegerField(blank=True, null=True)
patient_weight = models.IntegerField(blank=True, null=True)
age_risk = models.BooleanField(default=False)
I want to query on patient table for getting all the patient. also i need MRN column value from PatientMedicalRecord table which contain record for particular patient if exists.
How can i do this with djnago ORM?
Following are sql query gives me perfect result.
SELECT a.id,--remaining field, b.mrn FROM patient as a LEFT JOIN patient_medical_record as b ON a.id=b.patient_id;
How can i do this with django annotate ?
You can fetch related objects using the object_set. In your example, here is how you would do it:
patient = Patient.objects.get(pk=1) # You can use any attribute to get the Patient object
patient_medical_records = patient.patientmedicalrecord_set.all()
patient_mrns = []
for record in patient_medical_records:
patient_mrns.append(record.mrn)
You can also defined a related_name property in your model for the relationship to query relationships with. For example:
class PatientMedicalRecord(models.Model):
patient = models.ForeignKey(Patient, on_delete=models.CASCADE, related_name='patient_records')
Then you would query it like this:
patient = Patient.objects.get(pk=1)
patient_medical_records = patient.patient_records.all()

SQLAlchemy delete all entries of many to many relationship

So I have this program that notes down recipes. a recipe has a number of ingredients and they have a many to many relationship. There is a table of ingredients and they are linked through the recipe_ingredients table to a recipe.
I made the following code to update a recipe (lets say I removed all the ingredients and added a new one), however, instead of clearing the old ingredients, it just appends everything. Am I doing something wrong here?
Update recipe code:
#app.route('/recipe', methods=['POST'])
#expects_json(recipeSchema)
def updateRecipe():
recipeToUpdate = session.query(classes.Recipe).filter(classes.Recipe.id==flask.request.json["id"]).first()
if recipeToUpdate is not None:
newRecipe = flask.request.json
if "name" in newRecipe.keys():
recipeToUpdate.name = newRecipe["name"]
if "amountofpeople" in newRecipe.keys():
recipeToUpdate.amountofpeople = newRecipe["amountofpeople"]
if "ingredients" in newRecipe.keys():
newIngredientsArray = []
for ingredient in newRecipe["ingredients"]:
if "id" in ingredient.keys():
newIngredient = session.query(classes.Ingredient).filter(classes.Ingredient.id==ingredient["id"]).first()
newRecipeIngredient = classes.RecipeIngredients(recipe_id=recipeToUpdate.id, ingredient_id=newIngredient.id, ingredient_amount=1)
if "ingredient_amount" in ingredient.keys():
newRecipeIngredient.ingredient_amount = ingredient["ingredient_amount"]
newIngredientsArray.append(newRecipeIngredient)
recipeToUpdate.ingredients[:] = newIngredientsArray
session.commit()
return mapRecipes(recipeToUpdate)
else:
return {"id": id, "Error": "Not found"}
Recipe:
class Recipe(Base):
__tablename__ = 'recipes'
id = Column(Integer, Sequence('recipe_id_seq'), primary_key=True, autoincrement=True)
amountofpeople = Column(Integer)
name = Column(String)
ingredients = relationship("RecipeIngredients", back_populates="recipe")
Ingredient:
class Ingredient(Base):
__tablename__ = 'ingredients'
id = Column(Integer, primary_key=True)
name = Column(String)
amount = Column(Integer)
unit = Column(Enum(Units))
recipe = relationship('RecipeIngredients', back_populates="ingredient")
Recipe_ingredients:
class RecipeIngredients(Base):
__tablename__ = 'recipe_ingredients'
id = Column(Integer, primary_key=True)
recipe_id = Column(Integer, ForeignKey('recipes.id'))
ingredient_id = Column(Integer, ForeignKey('ingredients.id'))
ingredient_amount = Column(Integer)
recipe = relationship('Recipe', back_populates="ingredients")
ingredient = relationship('Ingredient', back_populates="recipe")
I found a solution, however, I am not sure that it is the right one:
I added: session.query(classes.RecipeIngredients).filter(classes.RecipeIngredients.recipe_id==recipeToUpdate.id).delete()
This will first remove all the previous relations before making new ones. but I wonder if there might be a cleaner way by defining a sync in the classes.
#app.route('/recipe', methods=['POST'])
#expects_json(recipeSchema)
def updateRecipe():
recipeToUpdate = session.query(classes.Recipe).filter(classes.Recipe.id==flask.request.json["id"]).first()
if recipeToUpdate is not None:
newRecipe = flask.request.json
if "name" in newRecipe.keys():
recipeToUpdate.name = newRecipe["name"]
if "amountofpeople" in newRecipe.keys():
recipeToUpdate.amountofpeople = newRecipe["amountofpeople"]
if "ingredients" in newRecipe.keys():
session.query(classes.RecipeIngredients).filter(classes.RecipeIngredients.recipe_id==recipeToUpdate.id).delete()
newIngredientsArray = []
for ingredient in newRecipe["ingredients"]:
if "id" in ingredient.keys():
newIngredient = session.query(classes.Ingredient).filter(classes.Ingredient.id==ingredient["id"]).first()
newRecipeIngredient = classes.RecipeIngredients(recipe_id=recipeToUpdate.id, ingredient_id=newIngredient.id, ingredient_amount=1)
if "ingredient_amount" in ingredient.keys():
newRecipeIngredient.ingredient_amount = ingredient["ingredient_amount"]
newIngredientsArray.append(newRecipeIngredient)
recipeToUpdate.ingredients[:] = newIngredientsArray
session.commit()
return mapRecipes(recipeToUpdate)
else:
return {"id": id, "Error": "Not found"}

peewee, how to query specified table?

i have peewee model, it need to create a table everyday, not i want to query table MotorTable.query() Test20191021 but it always query the table today, how can i query the specified table?
DB = SqliteDatabase('test.db')
def motor_db_table(model_cls):
return 'Test{}'.format(time.strftime('%Y%m%d'))
class MotorTable(Model):
date = DateTimeField()
addr = CharField()
status = CharField()
class Meta:
database = DB
table_function = motor_db_table
There are a couple ways you could go about this. You could create the model class in a closure, e.g.
model_cache = {}
def get_model_for_date(dt):
tbl_name = 'Test' + dt.strftime('%Y%m%d')
if tbl_name not in model_cache:
class MotorTable(Model):
date = DateTimeField()
addr = TextField()
status = CharField()
class Meta:
database = DB
table_name = tbl_name
if not MotorTable.table_exists():
MotorTable.create_table()
model_cache[tbl_name] = MotorTable
return model_cache[tbl_name]
Alternatively, you could just explicitly set the table name each time using a wrapper:
def get_model(dt):
table_name = 'Test' + dt.strftime('%Y%m%d')
MotorTable._meta.set_table_name(table_name)
if not MotorTable.table_exists():
MotorTable.create_table()
return MotorTable

query multiple SQLalchemy ORM

I'm new in SQLalchemy I need to calculate multiple of some price in my one of the table. This is my tables:
class Order(DeclarativeBase):
__tablename__ = 'order'
id = Field(Integer, primary_key=True)
products = relationship("OrderProduct", back_populates="order", lazy='dynamic')
and
class OrderProduct(DeclarativeBase):
__tablename__ = 'order_products'
id = Field(Integer, primary_key=True)
order_id = Column(Integer, ForeignKey('order.id'), nullable=False)
order = relationship("Order", back_populates="products", protected=True)
product_id = Column(Integer, ForeignKey('product.id'), nullable=False)
product = relationship("Product", back_populates="order_product")
quantity = Field(Integer, nullable=False)
and
class Product(DeclarativeBase):
__tablename__ = 'product'
id = Field(Integer, primary_key=True)
price = Field(Integer)
order_product = relationship("OrderProduct", back_populates="product", protected=True)
I want to multiple price with this situation OrderProduct.quantity * Product.price and products in Order table is an array of Products
I write SQL query like this and it works:
SELECT SUM(price*quantity) FROM product
JOIN order_products ON product.id = order_products.product_id
JOIN order ON order_products.order_id = order.id;
I tried to make it in ORM like this but it takes me Product and I can calculate only price without multiple in quantity:
result = 0
for product in Product.query\
.join(OrderProduct).filter(Product.id == OrderProduct.product_id)\
.join(Order).filter(OrderProduct.order_id == self.id):
result = product.price + result
return result
I make this as #hybrid_property and its work well.
I use a framework that name is restfulpy. it has ORM for sqlalchemy, session in this framework is scoped_session, but it gives me SQL query in debuging mode instead of executing the query like this :
sum_price = {Query}SELECT sum(product.price * order_products.quantity) AS sum_1
FROM product JOIN order_products ON product.id = order_products.product_id JOIN "order" ON "order".id = order_products.order_id
WHERE product.id = order_products.product_id AND order_products.order_id = :order_id_1
Well, Can anyone help me out this problem?
with regards
I just realized that SQLalchemy is a great ORM! When you have a relation between two, three or ... tables, SQLalchemy make a join between them and you just query it!
I made it hard for me and my friends :) SQLalchemy is powerful than what I'm thinking!
This is the right answer:
#hybrid_property
def total_price(self):
return DBSession.query(
func.sum(Product.price * OrderProduct.quantity))\
.filter(OrderProduct.product_id == Product.id) \
.filter(OrderProduct.order_id == self.id).scalar()
DBSession is the same with session
from sqlalchemy import func
query = session.query(func.sum(Product.price*OrderProduct.quantity))
.join(OrderProduct).filter(Product.id == OrderProduct.product_id)
.join(Order).filter(OrderProduct.order_id == self.id)

Resources