嵌套JSONField上的Django order_by

时间:2019-03-07 06:02:34

标签: json django postgresql

我的JSONField模型上有Product,在此模型中,我有嵌套字段。

例如:

"data": {
    'products':{
            "name": "ProductA", 
            "color": "Brown", 
            "price": {
                "end_user": 54,
                "credit_cart": 60
            },
            "name": "ProductB", 
            "color": "Red", 
            "price": {
                "end_user": 100,
                "credit_cart":120
             },

     }
}

我要订购嵌套的end_user字段。

这是我的尝试

Products.objects.order_by(RawSQL("data->>%s", ("data__price__end_user",)))

我找到了答案:

queryset = queryset.annotate(
                end_user=RawSQL("data->'products'->'price'->'->'end_user'", [])
            ).order_by('end_user')

2 个答案:

答案 0 :(得分:0)

从Django 1.11开始,使用KeyTextTransform似乎有可能

Django => 1.11

from django.contrib.postgres.fields.jsonb import KeyTextTransform

qs = RatebookEntry.objects.all()
qs = qs.annotate(manufacturer_name=KeyTextTransform('manufacturer_name', 'data'))
qs = qs.order_by('manufacturer_name')
# or...
qs = qs.order_by('-manufacturer_name')

Django <1.11

from django.contrib.postgres.fields.jsonb import KeyTransform

class KeyTextTransform(KeyTransform):
    operator = '->>'
    nested_operator = '#>>'
    _output_field = TextField()
  

来源:https://stackoverflow.com/a/50046631/3345051

     

新实现(2.1):https://code.djangoproject.com/ticket/24747

答案 1 :(得分:0)

这是工作吗?

//Adding a custom Shipping Fee to cart based conditionally on weight and cart amount
add_action('woocommerce_cart_calculate_fees', 'custom_conditional_shipping_fee', 10, 1);
function custom_conditional_shipping_fee( $cart_object ){

    #### SETTINGS ####

    // Your targeted "heavy" product weight
    $target_weight = 1;

    // Your targeted cart amount
    $target_cart_amount = 20;

    // Price by Kg;
    $price_kg = 2;

    // Amount set in 'flat rate' shipping method;
    $flat_rate_price;


    // Initializing variables
    $fee = 0;
    $calculated_weight = 0;

    // For cart SUBTOTAL amount EXCLUDING TAXES
    WC()->cart->subtotal_ex_tax >= $target_cart_amount ? $passed = true : $passed = false ;

    // For cart SUBTOTAL amount INCLUDING TAXES (replace by this):
    // WC()->cart->subtotal >= $target_cart_amount ? $passed = true : $passed = false ;

    // Iterating through each cart items
    foreach( $cart_object->get_cart() as $cart_item ){

        // Item id ($product ID or variation ID)
        if( $cart_item['variation_id'] > 0)
            $item_id = $cart_item['variation_id'];
        else
            $item_id = $cart_item['product_id'];

        // Getting the product weight
        $product_weight = get_post_meta( $item_id , '_weight', true);

        // Line item weight
        $line_item_weight = $cart_item['quantity'] * $product_weight;

        // When cart amount is up to 1kg, Adding weight of heavy items
        if($passed && $product_weight < $target_weight)
            $calculated_weight += $line_item_weight;
    }

    #### Making the fee calculation ####

    // Cart is up to 250 with heavy items
    if ( $passed && $calculated_weight != 0 ) {
        // Fee is based on cumulated weight of heavy items
        $fee = ($calculated_weight * $price_kg) - $flat_rate_price;
    }
    // Cart is below 250
    elseif ( !$passed ) {
        // Fee is based on cart total weight
        $fee = ($cart_object->get_cart_contents_weight( ) * $price_kg) - $flat_rate_price;
    }

    #### APPLYING THE CALCULATED FEE ####

    // When cart is below 250 or when there is heavy items
    if ($fee > 0){
        // Rounding the fee
        $fee = round($fee);
        // This shipping fee is taxable (You can have it not taxable changing last argument to false)
        $cart_object->add_fee( __('Shipping weight fee', 'woocommerce'), $fee, true);
    }
}

或者这样:

from django.db.models.expressions import RawSQL
RatebookDataEntry.objects.all().order_by(RawSQL("data->>%s", ("data__products__price__end_user",)))