2016-05-07 17 views
5

बंद गोलाई मैं इस कोड है से बचने के लिए:Django एफ() विभाजन - कैसे

q = MyModel.objects.order_by('-value1').annotate(
      res=ExpressionWrapper(
       (F('value1')/F('value2')), 
       output_field=FloatField()), 
      ) 

for i in q:           
    print(i.value1, i.value2, i.res) 

तो, उत्पादन होगा:

5 10 0.0 
1 2 0.0 

लेकिन मैं

5 10 0.5 
1 2 0.5 

की जरूरत वाई एफ() परिणाम गोलाकार? यह कैसे नहीं करें?

धन्यवाद!

+0

क्या आपने 'float (F ('value1'))' 'प्रयास किया है? – trantu

+2

'एफ' अभिव्यक्तियों के बारे में बात यह है कि पायथन मूल्यों के बारे में नहीं जानता है, लेकिन ऑपरेशन (इस मामले में विभाजन) को डेटाबेस में हाथ रखता है। PostgreSQL और MySQL के लिए, पूर्णांक विभाजन का परिणाम एक पूर्णांक में होता है, जैसे कि पाइथन 2.x – schwobaseggl

+0

@trantu float() तर्क एक स्ट्रिंग या संख्या होना चाहिए, 'एफ' – tim

उत्तर

3

परिणाम जो आप उम्मीद कर रहे हैं वह कच्चे प्रश्न के साथ वास्तव में हासिल करना वास्तव में आसान है और वास्तव में, मेरा मतलब शुद्ध डीजेंगो के साथ हासिल करना वाकई मुश्किल है।

from django.db.models import FloatField, ExpressionWrapper, F 

template = '%(function)s(%(expressions)s AS FLOAT)' 
fv1 = Func(F('value1'), function='CAST', template=template) 
fv2 = Func(F('value2'), function='CAST', template=template) 
ew = ExpressionWrapper(fv1/fv2, output_field = FloatField()) 


q = MyModel.objects.order_by('-value1').annotate(res = ew) 

आप इसे सुरुचिपूर्ण होने का आरोप नहीं लगाएंगे लेकिन यह माइस्क्ल और पोस्टग्रेस्क्ल दोनों पर काम करता है।

कुछ पृष्ठभूमि प्रदान करने के लिए। गोलाकार डेटाबेस द्वारा पूर्णांक विभाजन कर रहा है क्योंकि आपके पास फ़ील्ड इन्स हैं। यदि आप दशमलव विभाजन चाहते हैं तो आपको उन्हें दशमलव तक डालना होगा। दुर्भाग्य से कास्टिंग Django के साथ बहुत आसान नहीं है।

पोस्टग्रेस्क्ल में फ्लोट करने के लिए वास्तव में एक शानदार तरीका है। value1 :: float लेकिन इसे अंदर django (कम से कम जहां तक ​​मुझे पता है) से उपयोग नहीं किया जा सकता है

10

बस एक कारक को दशमलव संख्या में बदलने के लिए गुणा के लिए F() का समर्थन करें।

from decimal import Decimal 

q = MyModel.objects.order_by('-value1').annotate(
      res=ExpressionWrapper(
       (F('value1') * Decimal('1.0')/F('value2')), 
       output_field=FloatField()), 
      ) 

मैं इस और अधिक सुरुचिपूर्ण रास्ता खोजने तो मान 1 मैदान पर कच्चे एसक्यूएल कास्ट बारे में और उसके बाद विभाजन कार्य करें:

संयुक्त अभिव्यक्ति तो कैसा लगेगा।

+0

गलती खोजने की कोशिश नहीं कर रहा है (मैंने आपको एक अपवर्तित दिया है) लेकिन इसने टाइप टाइपर: अनबाउंड विधि select_format() को फ़्लोटफिल्ल्ड इंस्टेंस के साथ पहले तर्क के रूप में जाना चाहिए (इसके बजाय SQLCompiler इंस्टेंस मिला है) – e4c5

+0

@ e4c5 क्या आप कुछ और दे सकते हैं विशिष्ट जानकारी (django ver, डीबी समर्थित आदि)? मैंने इसे Django 1.8 और पोस्टग्रेस के साथ परीक्षण किया है और यह वर्णित के रूप में कार्य करता है। सही एसक्यूएल का उत्पादन करता है: 'django.db.connection [-1] ['sql'] == चुनें ... ((" shop_product "।" Value1 "* 1.0) /" shop_product "।" Value2 ") AS" res "से ... '। 'res' में 0.6666666666666666 जैसे दशमलव दशमलव परिणाम होते हैं जब value1 == 2 और value2 == 3. – joanbm

+0

django 1.9 postgresql 9.5 क्षमा करें मैं अब त्रुटि को पुन: उत्पन्न नहीं कर सकता क्योंकि मैंने डीबी – e4c5