I'm a new Django programmer. I write a API call with rest_framework in Django. when call this API, my program connect to KUCOIN and get list of all cryptocurrency. I want save symbol and name this cryptocurrencies in database. For save data to database, I use 'for loop' and in every for loop iteration, I query to database and save data. my code :
for currencie in currencies:
name = currencie['name']
symbol = currencie['symbol']
active = (False, True)[symbol.endswith('USDT')]
oms = 'kucoin'
try:
obj = Instrument.objects.get(symbol=symbol, oms=oms)
setattr(obj, 'name', name)
setattr(obj, 'active', active)
obj.save()
except Instrument.DoesNotExist:
obj = Instrument(name=name, symbol=symbol,
active=active, oms=oms)
obj.save()
query to database in every for loop iteration have problem ,How can I solve this problem?
Exist any way in Django to save data in database in with one query.
All my code:
class getKucoinInstrument(APIView):
def post(self, request):
try:
person = Client.objects.filter(data_provider=True).first()
person_data = ClientSerializer(person, many=False).data
api_key = person_data['api_key']
api_secret = person_data['secret_key']
api_passphrase = person_data['api_passphrase']
client = kucoin_client(api_key, api_secret, api_passphrase)
currencies = client.get_symbols()
for currencie in currencies:
name = currencie['name']
symbol = currencie['symbol']
active = (False, True)[symbol.endswith('USDT')]
oms = 'kucoin'
try:
obj = Instrument.objects.get(symbol=symbol, oms=oms)
setattr(obj, 'name', name)
setattr(obj, 'active', active)
obj.save()
except Instrument.DoesNotExist:
obj = Instrument(name=name, symbol=symbol,
active=active, oms=oms)
obj.save()
return Response({'response': 'Instruments get from kucoin'}, status=status.HTTP_200_OK)
except Exception as e:
print(e)
return Response({'response': 'Internal server error'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
Thank you for you help.
Yes! Take a look at bulk_create() documentation. https://docs.djangoproject.com/en/4.0/ref/models/querysets/#bulk-create
If you have a db that supports ignore_conflicts parameter (all do, except Oracle), you can do this:
new_currencies = []
for currencie in currencies:
name = currencie['name']
symbol = currencie['symbol']
active = (False, True)[symbol.endswith('USDT')]
oms = 'kucoin'
new_currencies.append(Instrument(name=name, symbol=symbol,
active=active, oms=oms))
Instrument.objects.bulk_create(new_currencies, ignore_conflicts=True)
1-liner:
Instrument.objects.bulk_create(
[
Instrument(
name=currencie['name'], symbol=currencie['symbol'],
active=currencie['symbol'].endswith('USDT'), oms='kucoin'
)
for currencie in currencies
],
ignore_conflicts=True
)
Related
Below is the view function of property view, and I would like to add pagination to this.
class PropertyView(Resource):
def get(self):
try:
data = request.json
verifyJwt= request.headers.get('Authorization')
token = jwt.decode(verifyJwt,"secret",algorithm="HS256")
print(token.get('email'))
data = request.json
user_email= User.query.filter_by(email=token.get('email')).first()
print(user_email,"TEST")
if user_email != "null" :
property_data = Property.query.order_by(Property.id.desc()).all()
property_list = []
for property_obj in property_data:
property_list.append({'id': property_obj.id, 'address': property_obj.address, "latitude": property_obj.latitude, "longitude":property_obj.longitude, "cdr_date": property_obj.cdr_date, "building_grossfloor_area": property_obj.building_grossfloor_area, "multi_family": property_obj.multi_family, "artist_studios": property_obj.artist_studios, "max_building_height": property_obj.max_building_height, "stories": property_obj.stories, "retail_commercial_sf": property_obj.retail_commercial_sf, "parking_spaces": property_obj.parking_spaces, "bike_spaces": property_obj.bike_spaces, "architect": property_obj.architect, "developer": property_obj.developer, "site_area": property_obj.site_area, "picture_1": property_obj.picture_1, "picture_2": property_obj.picture_2, "original_name": property_obj.original_name})
response_data = property_list
return ResponseGenerator(data=response_data,
status=status.HTTP_201_CREATED).make_success_response()
except Exception as e:
logger.exception(e)
return ResponseGenerator(message='Exception: {}'.format(e),
status=status.HTTP_400_BAD_REQUEST).make_error_response()
So after searching google and making so many correction, I was able to apply proper pagination in a simple way possible also with search filter.
Pasting so that it might help others.
class PropertyView(Resource):
def post(self):
try:
value = data.get('per_page')
per_page = value
value1 = data.get('page_num')
page_num = value1
search = data.get('search')
search = "%{}%".format(search)
property_data = Property.query.order_by(Property.id.desc()).all()
total = len(property_data)
page = request.args.get('page', 1, type=int)
if search !='':
property_data = Property.query.filter(or_(Property.address.like(search), Property.architect.like(search), Property.developer.like(search))).order_by(Property.id.desc()).paginate(page=page_num, per_page=per_page, error_out=True).items
num = len(property_data)
else:
property_data = Property.query.order_by(Property.id.desc()).paginate(page=page_num, per_page=per_page, error_out=True).items
num = len(property_data)
(print("Check Pagination",property_data,page_num,per_page))
property_list = []
for property_obj in property_data:
property_list.append({'id': property_obj.id, 'address': property_obj.address, "latitude": property_obj.latitude, "longitude":property_obj.longitude, "cdr_date": property_obj.cdr_date, "building_grossfloor_area": property_obj.building_grossfloor_area, "multi_family": property_obj.multi_family, "artist_studios": property_obj.artist_studios, "max_building_height": property_obj.max_building_height, "stories": property_obj.stories, "retail_commercial_sf": property_obj.retail_commercial_sf, "parking_spaces": property_obj.parking_spaces, "bike_spaces": property_obj.bike_spaces, "architect": property_obj.architect, "developer": property_obj.developer, "site_area": property_obj.site_area, "picture_1": property_obj.picture_1, "picture_2": property_obj.picture_2, "original_name": property_obj.original_name, "p_status": property_obj.p_status})
else:
print("Not authorised to view this data.")
I am trying to update a handful of fields if the record has been marked as deleted. When I debug, I can see that the values are being assigned in the view, but not being updated in the DB. I'm not sure what I'm missing.
views.py
contact_formset = ContactFormSet(request.POST, prefix='contact')
for contact in contact_formset.deleted_forms:
contact = contact.cleaned_data
print(contact)
instance = contact['id_cnt']
contact_id = instance.id_cnt
contact_object = get_object_or_404(AppContactCnt, id_cnt=contact_id)
contact_object.deleted_cnt = True
contact_object.date_deleted_cnt = '2020-11-23'
contact_object.deleted_by_cnt = 'adeacon'
contact_object.save()
Included the delete code with the edit code. Seemed to do the trick:
if '_edit_contact_formset' in request.POST:
contact_formset = ContactFormSet(request.POST, prefix='contact')
for contact_form in contact_formset:
if contact_form.is_valid() and contact_form.has_changed():
contact_data = contact_form.cleaned_data
# print(contact_data)
customer_obj = get_object_or_404(AppCustomerCst, id_cst=id)
contact_form.instance.idcst_cnt = customer_obj
contact_form.instance.idtrp_cnt = '-1'
if contact_data['DELETE'] is True:
print('delete me')
contact_form.instance.deleted_cnt = True
contact_form.instance.date_deleted_cnt = '2020-11-23'
contact_form.instance.deleted_by_cnt = 'adeacon'
messages.info(request, 'Contact deleted successfully')
contact_form.save()
formset = ContactFormSet(
queryset=AppContactCnt.objects.filter(idcst_cnt=id).exclude(deleted_cnt=True).select_related('idctp_cnt'),
prefix='contact')
if contact_data['DELETE'] is not True:
messages.info(request, 'Contacts updated successfully!')
I have a requirement to create an automated password reset script. I created a custom field in order to try and track this and also hope I can access some of the standard fields. This script should find users with the following criteria:
The latest of any of the following 3 dates that are >= 90 days ago : Sign_Up, Forgot_Password, or custom:pwdCreateDate
I can't seem to find any boto3 cognito client ways of getting the information on this except for forgot password which shows up in admin_list_user_auth_events and that response doesn't include username in the response. I suppose since you provide username to get the events you can figure out a way to find the latest forgot password from the events and tie it to the username.
Has anyone else implemented any boto3 automation to set the account to force password reset based on any of these fields?
here is where i landed, take it with the understanding that coginito has some limitations which make true flawless password rotation difficult. Also know if you can make the script more efficient you should because in lambda you probably time out with more than about 350 users due to the 5RPS on the admin API.
Prerequisites : set the lambda function to 5 concurrency or you will exceed the limit of 5RPS. 1 mutable field in your cognito userpool attributes to put a date in. a custom lambda zip file that includes pandas saved to s3.
import os
import sys
# this adds the parent directory of bin so we can find the module
parent_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), os.path.pardir))
sys.path.append(parent_dir)
#This addes venv lib/python2.7/site-packages/ to the search path
mod_path = os.path.abspath(parent_dir+"/lib/python"+str(sys.version_info[0])+"."+str(sys.version_info[1])+"/site-packages/")
sys.path.append(mod_path)
import boto3
import datetime
import pandas as pd
import time
current_path = os.path.dirname(os.path.realpath(__file__))
# Use this one for the parent directory
ENV_ROOT = os.path.abspath(os.path.join(current_path, os.path.pardir))
# Use this one for the current directory
#ENV_ROOT = os.path.abspath(os.path.join(current_path))
sys.path.append(ENV_ROOT)
#if __name__ == "__main__":
def lambda_handler(event, context):
user_pool_id = os.environ['USER_POOL_ID']
idp_client = boto3.client('cognito-idp')
users_list = []
page_token = None
dateToday = datetime.datetime.today().date()
def update_user(user) :
idp_client.admin_update_user_attributes(
UserPoolId = user_pool_id,
Username = user,
UserStatus = 'RESET_REQUIRED',
UserAttributes = [
{
'Name': 'custom:pwdCreateDate',
'Value': str(dateToday)
}
]
)
users = idp_client.list_users(
UserPoolId = user_pool_id
)
for user in users['Users']: users_list.append(user['Username'])
page_token = users['PaginationToken']
while 'PaginationToken' in users :
users = idp_client.list_users(
UserPoolId = user_pool_id,
PaginationToken = page_token
)
for user in users["Users"]: users_list.append(user["Username"])
if 'PaginationToken' in users :
page_token = users['PaginationToken']
attrPwdDates = []
for i in range(len(users_list)) :
userAttributes = idp_client.admin_get_user(
UserPoolId = user_pool_id,
Username = users_list[i]
)
for a in userAttributes['UserAttributes'] :
if a['Name'] == 'custom:pwdCreateDate' :
attrPwdDates.append(datetime.datetime.strptime(a['Value'], '%Y-%m-%d %H:%M:%S.%f').date())
time.sleep(1.0)
list_of_userattr_tuples = list(zip(users_list, attrPwdDates))
df1 = pd.DataFrame(list_of_userattr_tuples,columns = ['Username','Password_Last_Set'])
authPwdDates = []
for i in range(len(users_list)) :
authEvents = idp_client.admin_list_user_auth_events(
UserPoolId = user_pool_id,
Username = users_list[i]
)
for event in authEvents['AuthEvents'] :
if event['EventType'] == 'ForgotPassword' and event['EventResponse'] == 'Pass' :
authPwdDates.append(event['CreationDate'].date())
break
time.sleep(1.0)
list_of_userauth_tuples = list(zip(users_list, authPwdDates))
df2 = pd.DataFrame(list_of_userauth_tuples,columns = ['Username','Password_Last_Forgot'])
df3 = df1.merge(df2,how='left', on = 'Username')
df3[['Password_Last_Set','Password_Last_Forgot']] = df3[['Password_Last_Set','Password_Last_Forgot']].apply(pd.to_datetime)
cols = ['Password_Last_Set','Password_Last_Forgot']
df4 = df3.loc[df3[cols].max(axis=1)<=pd.Timestamp.now() - pd.Timedelta(90, unit='d'), 'Username']
for i,r in df4.iterrows() :
update_user(r['Username'])
an existing module is present i.e hr.payslip,In that module i have added a field from my module . now i want to display the value of that field in hr.payslip module.
models/emailpayslip.py
#api.multi #Decorate a record-style method where 'self' is a recordset. The method typically defines an operation on records.
def send_email(self):
ir_model_data = self.env['ir.model.data']
payslip_obj = self.env['hr.payslip']
ids = self.env.context.get('active_ids', [])
ctx = dict()
employee_name = ''
for id_vals in ids:
payslip_browse = payslip_obj.browse(id_vals)
global email
email = payslip_browse.employee_id.work_email
store_email.sql_example(self,email)#calling method of store_email model
if payslip_browse.employee_id.work_email:
template_id = ir_model_data.get_object_reference('Payslip', 'email_template_payslip')[1]
ctx.update({
'default_model': 'hr.payslip',
'default_res_id': payslip_browse.id,
'default_use_template': bool(template_id),
'default_template_id': template_id,
'default_composition_mode': 'comment',
'email_to': payslip_browse.employee_id.work_email,
})
mail_id = self.env['mail.template'].browse(template_id).with_context(ctx).send_mail(payslip_browse.id, True)
This model is used to create a new table in database and store email to which the payslip is send and date of payslip send
class store_email(models.Model):
_name = "store.email"
sendemail = fields.Char(
string='Send Email',
default=lambda self: self._get_default_name(),
)
no_of_times = fields.Integer(string='No of Times')
date_of_email_send = fields.Date(
string="Date of Email",
default=lambda self: fields.datetime.now())
#api.model
def _get_default_name(self):
return "test"
#api.multi
def sql_example(self,temp):
dob = datetime.today()
self.env.cr.execute("SELECT * FROM store_email WHERE sendemail = %s",(temp,))
res = self.env.cr.fetchall()
if res == []:
count = 1
self.env.cr.execute("INSERT INTO store_email (sendemail,no_of_times,date_of_email_send) VALUES (%s,%s,%s)",(temp,count,dob))
self.env.cr.commit()
else:
for x in res:
count = x[7] + 1
self.env.cr.execute("UPDATE store_email SET date_of_email_send=%s,no_of_times=%s WHERE sendemail=%s",(dob,count,temp))
self.env.cr.commit()
Model to add a field in hr.payslip ,Which show last payslip send date
class Add_Field(models.Model):
_inherit = "hr.payslip"
last_payslip_send = fields.Date(string='Last Payslip Send')
#api.multi
def last_send_payslip(self):
self.env.cr.execute("SELECT * FROM store_email WHERE sendemail=%s",(email,))
res = self.env.cr.fetchall()
my addfile.xml
add_newfield
screenshort of the page where i have added the field
this page cntain the screenshort
You can use compute or default function to load value in to field or you can also pass value while creating record
default function example:
name = fields.Char(
string='Name',
default=lambda self: self._get_default_name(),
)
#api.model
def _get_default_name(self):
return "test"
Refer this link for computed fields
I am using flask session to achieve multi-user concurrency in my chatbot which is embedded in FB messenger and backend implemented in python.
Below is code:
#app.route("/", methods=['GET','POST'])
def webhook():
state = session.get('state')
session.modified = True
print("state:",state)
q_number = session.get('q_number')
age = session.get('age')
print('age:',age)
sex = session.get('sex')
symptoms = session.get('symptoms', [])
prev = session.get('prev')
conditions = session.get('conditions')
data = request.get_json()
##pprint(data["entry"])
sender_id = data["entry"][0]["messaging"][0]["sender"]["id"]
# get user info
r = requests.get('https://graph.facebook.com/v3.1/'+sender_id+
'?fields=first_name,last_name&access_token='+ACCESS_TOKEN)
if data["object"] == "page":
user_input = data['entry'][0]['messaging'][0]['message']['text']
#print(type(user_input))
user_input = user_input.lower()
#print(user_input)
question = get_question(sender_id,user_input,state, q_number, age, sex, symptoms, prev, conditions)
send_message(sender_id, question)
return "ok", 200
session.get is not working in flask and i am unable to fetch the values. so i cant able to send the state,age,sex,q_number,symptoms,prev,conditions to other function.. Please help me to overcome this.