How to insert item to the middle of a Django queryset? - django-queryset

I'm trying to sort the queryset in an order that it's sorted by "state" then "city" but I want the city "Other" to always be the last item of each state.
I think I can do it by selecting by "state" then append the "Other" at the end then combine all querysets for each state. Is there an easier way to do this? Thanks.

from django.db.models import Case, When, Value, CharField
SomeModel.objects.annotate(
custom_city_order=Case(
When(city="Other", then=Value("ZZZ")),
output_field=CharField(),
)
).order_by('state', 'custom_city_order')
This will help you to put a custom value on annotation and then you can order by this annotated value. So, according to your need you can set the value and make order of it.

Related

Odoo 10 - Duplicate supplier info for a given product_template

I have:
a) given product_template_id (i.e. id 100) and
b) a duplicated product_template_id (i.e. id 200) created using copy() method
copy() method copies only product.template model, so suppliers for that specific product are not copied.
I would like to duplicate all suppliers for that model, but now I am wondering which is the right way to do it in Odoo.
If I understood the model properly suppliers prices for a given product are stored in product_supplierinfo table, where each record that points to a given product_tmpl_id specifices a supplier price/qty for a given product_template.
Which would be the way in Odoo to search for all records that point to a given product_tmpl_id (i.e. 100), duplicate them changing product_tmpl_id to the new one (i.e. 200)?
Excerpt from the ORM Documentation:
copy (bool) -- whether the field value should be copied when the record is duplicated (default: True for normal fields, False for One2many and computed fields, including property fields and related fields)
The field you're referring to is seller_ids, whose field definition is below:
seller_ids = fields.One2many('product.supplierinfo', 'product_tmpl_id', 'Vendors')
The copy attribute is not explicitly defined, so it is False by default (as explained in the documentation above). If you want this field to copy along with the other values during the standard product "Duplicate" (copy method), you can do this:
class ProductTemplate(models.Model):
_inherit = 'product.template'
# This only changes the copy attribute of the existing seller_ids field.
# All other attributes (string, comodel_name, etc.) remain as they are defined in core.
seller_ids = fields.One2many(copy=True)
Alternatively
If you want to only have the field copied sometimes, you can extend the copy method to look for a specific context value and only copy based on that.
# This may take some tweaking, but here's the general idea
#api.multi
def copy(self, vals):
new_product = super(YourClass, self).copy(vals)
if vals.get('copy_sellers'):
new_product.seller_ids = self.seller_ids.copy({'product_id': new_product.id})
return new_product
# Whatever you have calling the copy method will need to include copy_sellers in vals
vals.update({'copy_sellers': True})
product.copy(vals)

Rethinkdb - filtering by value in another table

In our RethinkDB database, we have a table for orders, and a separate table that stores all the order items. Each entry in the OrderItems table has the orderId of the corresponding order.
I want to write a query that gets all SHIPPED order items (just the items from the OrderItems table ... I don't want the whole order). But whether the order is "shipped" is stored in the Order table.
So, is it possible to write a query that filters the OrderItems table based on the "shipped" value for the corresponding order in the Orders table?
If you're wondering, we're using the JS version of Rethinkdb.
UPDATE:
OK, I figured it out on my own! Here is my solution. I'm not positive that it is the best way (and certainly isn't super efficient), so if anyone else has ideas I'd still love to hear them.
I did it by running a .merge() to create a new field based on the Order table, then did a filter based on that value.
A semi-generalized query with filter from another table for my problem looks like this:
r.table('orderItems')
.merge(function(orderItem){
return {
orderShipped: r.table('orders').get(orderItem('orderId')).pluck('shipped') // I am plucking just the "shipped" value, since I don't want the entire order
}
})
.filter(function(orderItem){
return orderItem('orderShipped')('shipped').gt(0) // Filtering based on that new "shipped" value
})
it will be much easier.
r.table('orderItems').filter(function(orderItem){
return r.table('orders').get(orderItem('orderId'))('shipped').default(0).gt(0)
})
And it should be better to avoid result NULL, add '.default(0)'
It's probably better to create proper index before any finding. Without index, you cannot find document in a table with more than 100,000 element.
Also, filter is limit for only primary index.
A propery way is to using getAll and map
First, create index:
r.table("orderItems").indexCreate("orderId")
r.table("orders").indexCreate("shipStatus", r.row("shipped").default(0).gt(0))
With that index, we can find all of shipper order
r.table("orders").getAll(true, {index: "shipStatus"})
Now, we will use concatMap to transform the order into its equivalent orderItem
r.table("orders")
.getAll(true, {index: "shipStatus"})
.concatMap(function(order) {
return r.table("orderItems").getAll(order("id"), {index: "orderId"}).coerceTo("array")
})

Some help on a Union LINQ expression please

I need some help constructing a LINQ expression. I tend to use Lambda syntax.
I have 2 tables
OrderItem >- LibraryItem
OrderItem has a number of columns:
Id
FkLibraryItemId
Text
FkOrderId
LibraryItem has a number of Columns:
Id
Text
Type
Usually when selecting an "OrderItem", one picks a "Library Item". The "Id" and "Text" value are placed into the item record.
Sometimes a user may add a one off "OrderItem" which does not need storing in the "LibraryItem" table. It is simply stored in "OrderItem", but without a "FkLibraryItemId". So I have records in "OrderItem" that do not exist in "LibraryItem".
I need the LINQ to pull out all the relevant "LibraryItem" records of "Type=X" in addition to the "OrderItem" records for the relevant Order Id.
Many thanks in advance.
UPDATE:
I think I am talking about something like:
LibraryItem.Select(new{Id,Text}).Union(Order.Select(new{Id, Text})
context.OrderItems.Include("LibraryItems")
.Where(o => o.OrderId == orderId
&&(o.LibraryItem != null ? o.LibraryItem.Type == "X" : true))
Linq-to-SQL has a different syntax for Include, which basically eager-loads the reference objects (probably LoadWith, I don't remember at the moment).
Actually you can also do it with left inner join.

How to make the group header different than the table entries in NSOutlineView

Is there any way to use a different column for the first column in the group? By default it uses the same as the "Group Title" (the one with the "expand" triangle).
E.g. I want to bind the "Group" row to departmentTitle and the first column of the items in the group should have employeeTitle.
Like this:
-> departmentTitle
-->employeeTitle
-->employeeTitle
-->employeeTitle
-->employeeTitle
By default they use the same column like this:
-> departmentTitle
-->departmentTitle
-->departmentTitle
-->departmentTitle
-->departmentTitle
How can I change them from using the same column? I can just set it to "title" and make a return self.employeeTitle method but then I have to make that KVO compliant and mess up my model with workaround stuff. Am I missing something? Thanks
i might be late to answer this question, but here's what i did (it's not the most ellegant way of doing it, i'm certain)
you could have a property called "title" and bind the column to it.
also, define a property "departmentTitle" and "employeeTitle" which you'd initialize depending on whether an object is group or child object.
then define the "title" property's getter to return either "departmentTitle" or "employeeTitle" depending on your needs. it would look something like this:
- (NSString) title {
if (isLeaf) {
return self.employeeTitle;
}
else {
return self.departmentTitle;
}
}
as i said, it's not an ellegant solution but it worked like a charm for me.

best practice Treeview populating from differents kinds of objects

I would like to populate a Treeview.
Here is what I have in DB :
table : Box
BoxID
BoxName
table Book :
BookID
BookName
BoxID (fk Box.BoxID)
table Chapter:
ChapterID
ChapterName
BookID (fk Book.BookID)
As you may know a treeview is made up of treenode object.
A treenode object have a text property and a tag property.
The "text" property is the text that it's display on the screen for this node and the "tag" is an "hidden" value (usually uses to identify a node)
So in my case; the fields ending with ID will be used in the "tag" property and the fields ending with Name will be used in the "text" property
example :
so for a book; I will use the BookID field for the "tag" property and BookName field for the "text" property
note : I use a dbml so I have a Book object, Box object and Chapter object and I use linq to get them from the db.
So my question is; what is the best practice to build this tree?
I have a solution but it's really ugly because it looks like I'm duplicating the code.
The problem is that the values I need to extract for the text and tag properties are identified by differents fields name in the db
So for the book level, I need to get the BookID field to populate the tag property of my node; for the box level, I need to get the BoxID field to populate the tag property , ....
How can I make a kind of generic way to do it ?
I hope I made myself clear enough, don't hesitate to ask me questions :)
Thx in advance
Here is what I have for the moment
I get the list of box with a linq (dbml) request.
List<Box> MyListofBox = getMyListofBox();
Treenode tnBox = null;
Treenode tnBook =null;
foreach(Box b in MyListofBox )
{
tnBox = new TreeNode();
tnBox.tag = b.BoxID;
tnBox.text = b.BoxName;
List<Book> MyListofBook = getMyListofBookByBoxID(b.BoxID)
foreach(Book boo in MyListofBook )
{
tnBook = new TreeNode();
tnBook.tag = boo.BookID;
tnBook.text = boo.BookName;
tnBox.nodes.add(tnBook);
}
mytreeview.nodes.add(tnBox);
}
but of course I don't like this solution...
do you have a better way ?
I would extract the you need from the database in the form of a struct, possibly via the anonnoumous type that has been added to C# together with linq. Then I would populate insert this data into the place in the tree.
From what I get, you are trying to get each property separately, which will not work so well, because then you will have to make a call to the database for each separate property, which is very wasteful.
Addition based on what you have added
I do not believe the code can be more compact - the names you call are similar, but not the same and the way you do it was what I was trying to explain earlier.
You could
Define an key/value interface that both Box and Book implement
Define a delegate that returns a TreeNode and create delegate methods that accept Box and Book
However, I think the code is fine as written. Sometimes you just have to code it and there's little point in further abstracting or optimizing it.
The only issue I see in the code is that you're making a database call in a loop. Whether or not that's a problem depends on the application.

Resources