DRF post to a field without showing it in the API form - serialization

I have a Django Rest Framework API. I want to have a field 'result' that is on the model, but not shown on the API form, yet still appears in the json when I list the data or view the detail.
So I want to see this on my POST form:
And this on my GET request:
How can this be done?
serialisers.py:
from rest_framework import serializers
from .models import Expression
class ExpressionSerializer(serializers.ModelSerializer):
def __init__(self, *args, **kwargs):
self.operator_mapping = {
"add": " + ",
"minus": " - ",
"divide": " / ",
"multiply": " * "
}
super(ExpressionSerializer, self).__init__(*args, **kwargs)
class Meta:
model = Expression
fields = ["expression", "result"]
def create(self, validated_data):
expression_obj = Expression.objects.create(**validated_data)
return expression_obj
def update(self, instance, validated_data):
instance.expression = validated_data.get('expression', instance.expression)
instance.result = validated_data.get('result', instance.result)
instance.save()
return instance
views.py:
from rest_framework import generics, status
from rest_framework.response import Response
from rest_framework.views import APIView
from lxml import etree
from .serialisers import ExpressionSerializer
from .models import Expression
class ExpressionAPIView(APIView):
def __init__(self):
self.operator_mapping = {
"add": " + ",
"minus": " - ",
"divide": " / ",
"multiply": " * "
}
self.queryset = Expression.objects.all()
self.serializer_class = ExpressionSerializer
def get(self, request):
return Response({'data': request.data})
def post(self, request):
root = etree.XML(request.data['expression'])
result = self.evaluate_expression(root)[0]
exp_parsed = self.expression_to_string(root) + f" = {result}"
serializer_data = {'expression': exp_parsed, 'result': result}
serializer = self.serializer_class(
data=serializer_data,
)
serializer.is_valid(raise_exception=True)
serializer.save()
return Response(serializer.validated_data, status=status.HTTP_201_CREATED)
def expression_to_string(self, root):
expression = ""
for child in root:
if child.tag != "root" and child.tag != "expression":
if child.tag == "number":
num = int(child.text)
if child != root[-1]:
expression += f"{num} {self.operator_mapping[root.tag]} "
else:
expression += f"{num}"
else:
if child != root[-1]:
expression += f"({self.expression_to_string(child)}) {self.operator_mapping[root.tag]} "
else:
expression += f"({self.expression_to_string(child)})"
else:
expression += f"{self.expression_to_string(child)}"
return expression
def evaluate_expression(self, root):
numbers = []
for child in root:
if child.tag == "number":
num = int(child.text)
numbers.append(num)
elif child.tag in ["add", "minus", "divide", "multiply"]:
_ = self.evaluate_expression(child)
def eval_sublist(_, operator):
x = _[0]
for i in range(1, len(_)):
x_str = f"{x}{operator}{_[i]}"
x = eval(x_str)
return x
numbers.append(eval_sublist(_, self.operator_mapping[child.tag]))
else:
numbers.extend(self.evaluate_expression(child))
return numbers

You can define the result field as being read only on your serializer.
That can be achieved through either defining the extra serializer parameters read_only_fields inside the Meta class or by explicitly defining the result field and adding a read_only=True flag to it.

Related

python-telegram-bot conversation-handler confustion

i'am new to python-telegram-bot library and i can't get this conversation handler do want i want!the first question always replace with /start or ... in result i tried to fix it but i couldn't i appratiate if you can help me with it.
this code ask several questions to user and at the end show the result but the result is not what i want and the final question was not even triged and i and very confiused! this is the code:
import logging
from telegram import ReplyKeyboardMarkup, KeyboardButton
from telegram.ext import (Updater, CommandHandler,
MessageHandler, Filters, ConversationHandler)
import const
import ccxt
TELEGRAM_TOKEN = const.telegram_token()
B_API_KEY = const.binance_api_key()
B_SECRET_KEY = const.binance_secret_key()
exchange = ccxt.binance({
'apiKey': B_API_KEY,
'secret': B_SECRET_KEY,
})
logging.basicConfig(
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO)
QUESTION_1, QUESTION_2, QUESTION_3 ,QUESTION_4 ,QUESTION_5, QUESTION_6 , QUESTION_0 , QUESTION_7= range(8)
# Function to start the conversation handler
def start(update, context):
context.user_data['first_crypto'] = update.message.text
update.message.reply_text('Question 1:enter first crypto symbol (Ex: BNB): ')
return QUESTION_0
def question_second_crypto(update, context):
context.user_data['second_crypto'] = update.message.text
update.message.reply_text('Question 2:enter second crypto symbol (Ex: USD): ')
return QUESTION_1
def question_kind(update, context):
context.user_data['kind'] = update.message.text
update.message.reply_text('Question 3: what stategy? (long/short)')
return QUESTION_2
def question_leverage(update, context):
context.user_data['leverage'] = update.message.text
update.message.reply_text('Question 4: choose Leverage:')
return QUESTION_3
def question_entry_price(update, context):
context.user_data['entry_price'] = update.message.text
update.message.reply_text('Question 5: what is your entry price? (Ex: 300$): ')
return QUESTION_4
def question_targets(update, context):
context.user_data['targets'] = update.message.text
update.message.reply_text('Question 6: target to triger alert? (Ex: 310$):')
return QUESTION_5
def question_sl(update, context):
context.user_data['stop_loss'] = update.message.text
update.message.reply_text('Question 7: stop_loss (290$):')
return end(update, context)
def end(update, context):
first_crypto = context.user_data['first_crypto']
second_crypto = context.user_data['second_crypto']
leverage = context.user_data['leverage']
entry_price = context.user_data['entry_price']
targets = context.user_data['targets']
stop_loss = context.user_data['stop_loss']
update.message.reply_text(f'Your answers have been recorded:\n'
f'first_crypto: {first_crypto}\n'
f'second_crypto: {second_crypto}\n'
f'leverage: {leverage}\n'
f'entry price:{entry_price}\n'
f'targets:{targets}\n'
f'stop_loss:{stop_loss}')
return ConversationHandler.END
def main():
updater = Updater(TELEGRAM_TOKEN, use_context=True)
dp = updater.dispatcher
conv_handler = ConversationHandler(
entry_points=[CommandHandler('start', start)],
states={
QUESTION_0: [MessageHandler(Filters.text, question_second_crypto)],
QUESTION_1: [MessageHandler(Filters.text, question_kind)],
QUESTION_2: [MessageHandler(Filters.text, question_leverage)],
QUESTION_3: [MessageHandler(Filters.text, question_entry_price)],
QUESTION_4: [MessageHandler(Filters.text, question_targets)],
QUESTION_5: [MessageHandler(Filters.text, question_sl)],
},
fallbacks=[MessageHandler(Filters.regex('^End$'), end)],
allow_reentry=True
)
dp.add_handler(conv_handler)
updater.start_polling()
updater.idle()
if __name__ == '__main__':
main()
the result was like this:
Your answers have been recorded:
first_crypto: /start
second_crypto: 1
leverage: 3
entry price:4
targets:5
stop_loss:6
the first_crypto: /start must be 1 and the stop_loss is never trigered.

No adapter found for objects of type: 'itemadapter.adapter.ItemAdapter'

I want to change the names of images downloaded from a webpage. I want to use standard names given by the website as opposed to cleaning the request url for it.
I have the following pipeline.py
from itemadapter import ItemAdapter
from scrapy.pipelines.images import ImagesPipeline
class ScrapyExercisesPipeline:
def process_item(self, item, spider):
adapter = ItemAdapter(item)
return adapter
class DownfilesPipeline(ImagesPipeline):
def file_path(self, request, response=None, info=None, item=None):
adapter = ScrapyExercisesPipeline().process_item()[0]
image_name: str = f'{adapter}.jpg'
return image_name
This produces the following error:
raise TypeError(f"No adapter found for objects of type: {type(item)} ({item})")
TypeError: No adapter found for objects of type: <class 'itemadapter.adapter.ItemAdapter'> (<ItemAdapter for ScrapyExercisesItem(name='unknown267', images=['https://bl-web-assets.britishland.com/live/meadowhall/s3fs-public/styles/retailer_thumbnail/public/retailer/boots_1.jpg?qQ.NHRs04tdmGxoyZKerRHcrhCImB3JH&itok=PD5LxLmS&cb=1657061667-curtime&v=1657061667-curtime'])>)
scraper.py:
import scrapy
from scrapy_exercises.items import ScrapyExercisesItem
class TestSpider(scrapy.Spider):
name = 'test'
#allowed_domains = ['x']
start_urls = ['https://www.meadowhall.co.uk/eatdrinkshop?page=1']
def start_requests(self):
for url in self.start_urls:
yield scrapy.Request(
url=url,
callback=self.parse,
cb_kwargs = {'pg':0}
)
def parse(self, response,pg):
pg=0
content_page = response.xpath("//div[#class='view-content']//div")
for cnt in content_page:
image_url = cnt.xpath(".//img//#src").get()
image_name = cnt.xpath(".//img//#alt").get()
if image_url != None:
pg+=1
items = ScrapyExercisesItem()
if image_name == '':
items['name'] = 'unknown'+f'{pg}'
items['images'] = [image_url]
yield items
else:
items['name'] = image_name
items['images'] = [image_url]
yield items
settings.py
ITEM_PIPELINES = {
#'scrapy.pipelines.images.ImagesPipeline': 1,
'scrapy_exercises.pipelines.ScrapyExercisesPipeline':45,
'scrapy_exercises.pipelines.DownfilesPipeline': 55
}
from pathlib import Path
import os
BASE_DIR = Path(__file__).resolve().parent.parent
IMAGES_STORE = os.path.join(BASE_DIR, 'images')
IMAGES_URLS_FIELD = 'images'
IMAGES_RESULT_FIELD = 'results'
You are calling on a pipeline from within your pipeline while that pipeline is also registered in your settings to be run as a pipeline. It would be simpler to just extract the name field from your item in your DownFilesPipeLine and return it.
Change your pipelines.py file to:
from itemadapter import ItemAdapter
from scrapy.pipelines.images import ImagesPipeline
class DownfilesPipeline(ImagesPipeline):
def file_path(self, request, response=None, info=None, item=None):
return item['name'] + '.jpg'
You also need to turn off the ScrapyExercisesPipeline in your settings

showing error " list indices must be integers or slices, not str "

showing error like "list indices must be integers or slices, not str"
Here MY APIView
class UploadViewSet(APIView):
parser_classes = (MultiPartParser, FormParser)
permission_classes = (AllowAny,)
def post(self, request, *args, **kwargs):
file = request.POST.get("content")
data = StringIO(file)
reader = csv.reader(data, delimiter=',')
for row in reader:
new_company = Company(
name=row['name'],
hr_name=row['hr_name'],
hr_email=row['hr_email'],
hr_verified=row['hr_verified'],
user_id=row['user_id'],
primary_phone=row['primary_phone'],
comments=row['comments'],
)
new_company.save()
return Response({"status": "success"},status.HTTP_201_CREATED)

How to extract entity from Microsoft LUIS using python?

Following the example code in this link, I can extract the intent using "intent_result.intent_id", but how can I extract the entity/entities of the utterance?
'''
import azure.cognitiveservices.speech as speechsdk
print("Say something...")
intent_config = speechsdk.SpeechConfig(subscription="YourLanguageUnderstandingSubscriptionKey", region="YourLanguageUnderstandingServiceRegion")
intent_recognizer = speechsdk.intent.IntentRecognizer(speech_config=intent_config)
model = speechsdk.intent.LanguageUnderstandingModel(app_id="YourLanguageUnderstandingAppId")
intents = [
(model, "HomeAutomation.TurnOn"),
(model, "HomeAutomation.TurnOff")
]
intent_recognizer.add_intents(intents)
start_continuous_recognition() instead.
intent_result = intent_recognizer.recognize_once()
if intent_result.reason == speechsdk.ResultReason.RecognizedIntent:
print("Recognized: \"{}\" with intent id `{}`".format(intent_result.text, intent_result.intent_id))
elif intent_result.reason == speechsdk.ResultReason.RecognizedSpeech:
print("Recognized: {}".format(intent_result.text))
elif intent_result.reason == speechsdk.ResultReason.NoMatch:
print("No speech could be recognized: {}".format(intent_result.no_match_details))
elif intent_result.reason == speechsdk.ResultReason.Canceled:
print("Intent recognition canceled: {}".format(intent_result.cancellation_details.reason))
if intent_result.cancellation_details.reason == speechsdk.CancellationReason.Error:
print("Error details: {}".format(intent_result.cancellation_details.error_details))
# </IntentRecognitionOnceWithMic>
'''
from azure.cognitiveservices.language.luis.runtime import LUISRuntimeClient
from msrest.authentication import CognitiveServicesCredentials
from azure.cognitiveservices.language.luis.runtime.models import EntityModel
from collections import OrderedDict
from typing import Union
class LuisPredictionClass():
def __init__(self, endpoint, appIdLUIS, predictionResourcePrimaryKey):
self.endpoint = endpoint
self.appIdLUIS = appIdLUIS
self.predictionResourcePrimaryKey = predictionResourcePrimaryKey
self.client = LUISRuntimeClient(self.endpoint, CognitiveServicesCredentials(self.predictionResourcePrimaryKey))
def find_LUIS_result(self,Text):
luis_result = self.client.prediction.resolve(self.appIdLUIS,Text)
return luis_result
def extract_entity_value(self,entity: EntityModel) -> object:
if (entity.additional_properties is None or "resolution" not in entity.additional_properties ):
return entity.entity
resolution = entity.additional_properties["resolution"]
if entity.type.startswith("builtin.datetime."):
return resolution
if entity.type.startswith("builtin.datetimeV2."):
if not resolution["values"]:
return resolution
resolution_values = resolution["values"]
val_type = resolution["values"][0]["type"]
timexes = [val["timex"] for val in resolution_values]
distinct_timexes = list(OrderedDict.fromkeys(timexes))
return {"type": val_type, "timex": distinct_timexes}
if entity.type in {"builtin.number", "builtin.ordinal"}:
return self.number(resolution["value"])
if entity.type == "builtin.percentage":
svalue = str(resolution["value"])
if svalue.endswith("%"):
svalue = svalue[:-1]
return self.number(svalue)
if entity.type in {
"builtin.age",
"builtin.dimension",
"builtin.currency",
"builtin.temperature",
}:
units = resolution["unit"]
val = self.number(resolution["value"])
obj = {}
if val is not None:
obj["number"] = val
obj["units"] = units
return obj
value = resolution.get("value")
return value if value is not None else resolution.get("values")
def extract_normalized_entity_name(self,entity: EntityModel) -> str:
# Type::Role -> Role
type = entity.type.split(":")[-1]
if type.startswith("builtin.datetimeV2."):
type = "datetime"
if type.startswith("builtin.currency"):
type = "money"
if type.startswith("builtin."):
type = type[8:]
role = (
entity.additional_properties["role"]
if entity.additional_properties is not None
and "role" in entity.additional_properties
else ""
)
if role and not role.isspace():
type = role
return type.replace(".", "_").replace(" ", "_")
Now you can run it as:
LuisPrediction = LuisPredictionClass("<<endpoint>>", "<<appIdLUIS>>", "<<predictionResourcePrimaryKey>>")
luis_result = LuisPrediction.find_LUIS_result("<<YOUR STRING HERE>>")
if len(luis_result.entities) > 0:
for i in luis_result.entities:
print(LuisPrediction.extract_normalized_entity_name(i),' : ',LuisPrediction.extract_entity_value(i))

Scrapy yield from a non call back method

I am trying to scrape a html file that has a json object with all the required test case data , but processing of the json happens in "find" and "parseTestCaseDetails" method where iteratively i get the test case details , which i finally parse in "findInterestedFields" , so my requirement is to yield the details of test cases to a json file from the the last method called in the hierarchy i.e findInterestedFields , is it possible to achieve this??
Thanks in advance!
import scrapy
import datetime
import json
import re
import collections
import time
import os
import js2xml
from scrapy.selector import HtmlXPathSelector
class AltiplanoAVInprogressTCSpiderTest(scrapy.Spider):
name = "AltiplanoAVInprogressTCSpiderTest"
buildNumber = []
FormatedBuildTime = []
keys = []
testcaseName=''
testcaseSuit=''
testcaseDoc=''
def start_requests(self):
print os.environ["jenkinsdomain"]
urls = [
os.environ["jenkinsdomain"] + "/job/InprogressFlakyAndBlockedTestCaseDetails/lastSuccessfulBuild/"
]
for url in urls:
print url
yield scrapy.Request(url=url, callback=self.parse, errback=self.parseerror)
def parseerror(self, failure):
print failure
def parse(self, response):
hxs = HtmlXPathSelector(response)
buildNumberString = hxs.select('normalize-space(//*[#id="main-panel"]/h1/text())').extract_first()
self.buildNumber = buildNumberString.split("#")[-1].split("(")[0].strip()
buildTimeUnformatd = buildNumberString.split("(")[-1].split(")")[0].strip().replace("PM", "").replace("AM", "")
buildTimeUnformatd = buildTimeUnformatd.strip()
t = time.strptime(buildTimeUnformatd, "%b %d, %Y %I:%M:%S")
self.FormatedBuildTime = time.strftime('%d %b %y %H:%M IST', t)
static_testDetailsUrl = os.environ[
"jenkinsdomain"] + "XX/Inprogress-ANV.html"
yield scrapy.Request(url=static_testDetailsUrl, callback=self.parseTestDetails, errback=self.parseerror)
def find(self, key, dictionary):
for k, v in dictionary.iteritems():
if k == key:
yield v
self.parseTestCaseDetails(v)
elif isinstance(v, dict):
for result in self.find(key, v):
yield result
elif isinstance(v, list):
for d in v:
for result in self.find(key, d):
yield result
def parseTestCaseDetails(self, testcases):
# get the list of test cases and again parse them one by one to get the name and other fields
for testcase in testcases:
self.findInterestedFields(testcase)
def findInterestedFields(self, dictionary):
jsonLoad = json.dumps(dictionary, indent=4)
loaded_json = json.loads(jsonLoad)
readabledatetime = datetime.datetime.now().strftime("%d %b %y %H:%M IST")
for k, v in loaded_json.iteritems():
if k == "name":
testcaseName = v
if k == "fullName":
testcaseSuit = v
if k == "doc":
testcaseDoc = v
yield {"name":"avInprogresstestcases",'avInprogresstestcases':{
'testcaseName':testcaseName
}}
def parseTestDetails(self, response):
data = response.xpath('//script[4]/text()').extract_first().strip()
jstree = js2xml.parse(data)
testDetailsInJson = js2xml.jsonlike.getall(jstree)
jsonLoad = json.dumps(testDetailsInJson[0], indent=4)
loaded_json = json.loads(jsonLoad)
list(self.find('tests', loaded_json))