Adonis Many to Many, Order by 'display_order' field in relationship table - adonis.js

Due to MANY-TO-MANY relationship between categories_1 and categories_2, different row in categories_1 might show different order of categories_2
Example:
categories_1 categories_2
A 1: a , 2: b , 3: c, 4: d
B 1: c , 2: a
where 1:, 2: ... are the orders.
Therefore I decide not to put the display_order as a field in the categories_2 but instead put it in the relation table categories_1_categories_2_relations because the orders of categories_2 depend on categories_1. However, by using .with('categories_2', function(builder) {} then .orderBy('display_order','asc') does not seem to allow me to read the fields in the relations table.
Is there a way that I can order the categories_2 by using the field display_order in the relation table?

I had the same issue... Had images in media table that can be assigned to home and order information was inside home_media table.
I solved it like this:
await Home.query().with('media', (builder) => {
builder.orderBy('order', 'asc')
})
But I think important thing that you missed is that I added inside my app/Models/Home.js this:
media() {
return this.belongsToMany('App/Models/Media')
.withPivot(['type', 'order'])
}
So I belive .withPivot is solution for you... Just add withPivot(['display_order']) to your categories model where you defined many to many relation.
More info here: http://adonisjs.com/docs/4.0/relationships#_withpivot

Related

Join two records from same model in django queryset

Been searching the web for a couple hours now looking for a solution but nothing quite fits what I am looking for.
I have one model (simplified):
class SimpleModel(Model):
name = CharField('Name', unique=True)
date = DateField()
amount = FloatField()
I have two dates; date_one and date_two.
I would like a single queryset with a row for each name in the Model, with each row showing:
{'name': name, 'date_one': date_one, 'date_two': date_two, 'amount_one': amount_one, 'amount_two': amount_two, 'change': amount_two - amount_one}
Reason being I would like to be able to find the rank of amount_one, amount_two, and change, using sort or filters on that single queryset.
I know I could create a list of dictionaries from two separate querysets then sort on that and get the ranks from the index values ...
but perhaps nievely I feel like there should be a DB solution using one queryset that would be faster.
union seemed promising but you cannot perform some simple operations like filter after that
I think I could perhaps split name into its own Model and generate queryset with related fields, but I'd prefer not to change the schema at this stage. Also, I only have access to sqlite.
appreciate any help!
Your current model forces you to have ONE name associated with ONE date and ONE amount. Because name is unique=True, you literally cannot have two dates associated with the same name
So if you want to be able to have several dates/amounts associated with a name, there are several ways to proceed
Idea 1: If there will only be 2 dates and 2 amounts, simply add a second date field and a second amount field
Idea 2: If there can be an infinite number of days and amounts, you'll have to change your model to reflect it, by having :
A model for your names
A model for your days and amounts, with a foreign key to your names
Idea 3: You could keep the same model and simply remove the unique constraint, but that's a recipe for mistakes
Based on your choice, you'll then have several ways of querying what you need. It depends on your final model structure. The best way to go would be to create custom model methods that query the 2 dates/amount, format an array and return it

Django - joining multiple tables (models) and filtering out based on their attribute

I'm new to django and ORM in general, and so have trouble coming up with query which would join multiple tables.
I have 4 Models that need joining - Category, SubCategory, Product and Packaging, example values would be:
Category: 'male'
SubCategory: 'shoes'
Product: 'nikeXYZ'
Packaging: 'size_36: 1'
Each of the Model have FK to the model above (ie. SubCategory has field category etc).
My question is - how can I filter Product given a Category (e.g. male) and only show products which have Packaging attribute available set to True? Obviously I want to minimise the hits on my database (ideally do it with 1 SQL query).
I could do something along these lines:
available = Product.objects.filter(packaging__available=True)
subcategories = SubCategory.objects.filter(category_id=<id_of_male>)
products = available.filter(subcategory_id__in=subcategories)
but then that requires 2 hits on database at least (available, subcategories) I think. Is there a way to do it in one go?
try this:
lookup = {'packaging_available': True, 'subcategory__category_id__in': ['ids of males']}
product_objs = Product.objects.filter(**lookup)
Try to read:
this
You can query with _set, multi __ (to link models by FK) or create list ids
I think this should work but it's not tested:
Product.objects.filter(packaging__available=True,subcategori‌​es__category_id__in=‌​[id_of_male])
it isn't tested but I think that subcategories should be plural (related_name), if you didn't set related_name, then subcategory__set instead od subcategories should work.
Probably subcategori‌​es__category_id__in=‌​[id_of_male] can be switched to .._id=id_of_male.

Django insert or update in one table should reflect in another table

I am trying to create a cart using django-carton App. I have two models: Halls and Caterer. I want to add either of these Halls or Caterer object in cart when I will call add() method. While using this API, I need to register my model in settings.py as below
CART_PRODUCT_MODEL = 'marriage_halls.models.Hall'
I can register only one model at a time. So I can't add Caterer object in the cart.To resolve this issue, I'm planning to create new 'product' model which will contain 3 columns viz. {name, price, city}. These are the columns which are common in both Hall and Caterer and I want to display them when I'll call show() method. My first question is, is it a correct way to do it?
If its a correct approach, What I want to do is, whenever I will add new Hall or Caterer in their respective tables through Django's admin interface, only these 3 column values should get inserted to Product table (INSERT new row in product table).
How can I achieve this?
Make Product a base class and use multi table inheritance.
https://docs.djangoproject.com/en/1.10/topics/db/models/#multi-table-inheritance

Why do you need a separate product_to_category database table?

I've been looking at the Opencart database structure and basically, they have a product table, a category table, and then a table with 2 columns which links a product_id to a category_id.
What is the reasoning behind this? Would it not make things simpler to just include the category_id as a column in the product table?
Because a product can belong to more than one category and signifies a many-to-many relationship. It is part of the normalization process.

Efficiently select latest items of different categories

Consider the following model:
class Data(Model):
created_at = models.DateTimeField()
category = models.CharField(max_length=7)
I want to select the latest object for all categories.
Following this question, i'm selecting the distinct categories and then making a separate query for each of them:
categories = Data.objects.distinct('category').values_list('category', flat=True)
for category in categories:
latest_obj = Data.objects.filter(category=category).latest('created_at')
The downside of the approach is that it makes lots of queries (1 for the distinct categories, and then a separate query per category).
Is there a way to do this with a single query?
Typically, you would use a group by in relational database. Django has an aggergation API
(https://docs.djangoproject.com/en/dev/topics/db/aggregation/#aggregation) which allows you to do the following:
from django.db.models import Max
Data.objects.values('category').annotate(latest=Max('created_at'))
This will perform a single query and return a list like this:
[{'category' : 'cat1', 'latest' : '01/01/01' },{'category' : 'cat2' 'latest' : '02/02/02' }]
But I guess you might want to retrieve the data record id as well within this list. Django does not make thinks simple for you in this case. The problem is django uses all fields in the value clause to make the grouping and you cannot return extra columns from the query.
EDIT: I originally proposed to add a second values() clause to the end of the query based on web resources but this does not add extra columns to the result set.