I am making a small app where the client can make an appointment in a calendar, but I don't know how to save the appointment inside the database then show it to them after by date.
Full Edit:
I've created the calendar with some junk appointments as you can see below:
I want to save the appointment inside the database, so when any client hits on any date after submitting it, an ajax request will be sent to my views where I can handle the request, here is the view.py:
#abonent_panel_route.route('/panel/make/appointment/')
#abonent_panel_route.route('/panel/make/appointment/', methods=['GET', 'POST'])
def get_appo():
# user = User.query.filter_by(id=current_user.id).first_or_404()
import json
getData = str(request.args.getlist('data'))
data = json.loads(getData)
if data :
print "\n\n\n\n" + str(data['title']) + "\n\n\n\n"
return jsonify({'success': data})
else:
print "\n\n\n\n" + str(len(data)) + "\n\n\n\n"
return jsonify({'error': 'No data!'})
And here is the javascript code:
$(document).ready(function() {
var initialLocaleCode = 'ru';
var d = new Date();
var strDate = d.getFullYear() + "/" + (d.getMonth()+1) + "/" + d.getDate();
$('#calendar').fullCalendar({
header: {
left: 'prev,next today',
center: 'title',
right: 'month,agendaWeek,agendaDay,listMonth'
},
defaultDate: strDate,
height: 650,
locale: initialLocaleCode,
navLinks: true, // can click day/week names to navigate views
selectable: true,
selectHelper: true,
select: function(start, end) {
var title = prompt('Event Title:');
var eventData;
if (title) {
eventData = {
title: title,
start: start,
end: end
};
$('#calendar').fullCalendar('renderEvent', eventData, true); // stick? = true
$(this).css({'background-color':'red'});
$.ajax({
type: 'POST',
url: '{{url_for("panel_abonent.get_appo")}}',
data: [eventData]
})
.done(function(data){
if(data.error){
console.log(eventData);
}
else {
console.log(eventData);
}
});
}
$('#calendar').fullCalendar('unselect');
},
editable: true,
eventLimit: true,
events: [
{
title: 'All Day Event',
start: strDate
},
{
title: 'Long Event',
start: '2017-04-18',
end: '2017-04-20'
},
{
id: 999,
title: 'Repeating Event',
start: '2017-04-20'
},
{
id: 999,
title: 'Repeating Event',
start: '2017-04-29'
},
]
});
$.each($.fullCalendar.locales, function(localeCode) {
$('#locale-selector').append(
$('<option/>')
.attr('value', localeCode)
.prop('selected', localeCode == initialLocaleCode)
.text(localeCode)
);
});
$('#locale-selector').on('change', function() {
if (this.value) {
$('#calendar').fullCalendar('option', 'locale', this.value);
}
});
});
Inside the console , I can see a list of data of the picked date, like title, start and end time, here it is:
Object {title: "asfawg", start: r, end: r}
start : r{
"_ambigTime":true,
"_ambigZone":true,
"_d" : "Thu Apr 06 2017 06:00:00 GMT+0600 (+06)",
"_fullCalendar":true,
"_i":"2017/4/19",
"_isAMomentObject":true,
"_isUTC":true,
"_isValid":true,
"_locale":e,
"_offset":0,
"_pf":Object,
"__proto__":Object,
"title":"asfawg"
}
In view.py, I've converted the dictionary to a list to make it easy to fetch the data from the list, so you have a key and the value, as you've seen above where I print the title print "\n\n\n\n" + str(data['title']) + "\n\n\n\n" I should get the value of the title which is asfawg, but I got nothing and the request always return No data. and the length of the list returns 0.
Please , anybody tells me where is the mistake that I've made.
I solved the problem, the eventData itself was a dictionary not a list.
So if i want to fetch the start date for example inside ajax request then to send it to my view.py, i would do something like:
data: {
'data': title,
'start': eventData['start']['_d'],
'end': eventData['end']['_d']
}
And I've changed a little bit my views, i added a function that took any json argument and return it as a json dictionary, i used flask_restful to do the job, here is the function:
def parse_arg_from_requests(arg, **kwargs):
from flask_restful import reqparse
parse = reqparse.RequestParser()
parse.add_argument(arg, **kwargs)
args = parse.parse_args()
return args[arg]
Next is very simple, just get the arguments one by one like the following order:
data = parse_arg_from_requests('data')
start = parse_arg_from_requests('start')
end = parse_arg_from_requests('end')
return render_template('panel/panel.html')
Related
I've been scratching my head for quite a while on this so any help is much appreciated.
Let's say I have a model called Transaction.
class Transaction(models.Model):
time = models.DateTimeField(auto_now_add=True, blank=True)
client = models.ForeignKey(User , on_delete=models.Cascade)
value = models.IntegerField()
I want to generate a chart using chart.js.
So far i am able to do this for all the objects using this JS:
<script>
$(function () {
var $xChart = $("#xChart");
$.ajax({
url: $xChart.data("url"),
success: function (data) {
var ctx = $xChart[0].getContext("2d");
new Chart(ctx, {
type: 'line',
data: data,
options: {
responsive: true,
legend: {
position: 'top',
},
title: {
display: true,
text: 'xChart'
}
}
});
}
});
});
</script>
And this FBV for the ajax call:
def x_chart(request):
def random_color():
return "#"+''.join([choice('ABCDEF0123456789') for i in range(6)])
labels=[]
data=[]
enddate = datetime.now()
startdate = datetime.now().date() - relativedelta(days=3)
transactions = Transaction.objects.filter(time__range=[startdate,enddate])
grouped_transactions = transactions.values("time__day").annotate(total=Sum('value'))
for key in grouped_transactions:
labels.append(key['time__day'])
data.append(key['total'])
return JsonResponse(
data={
'labels': labels,
'datasets': [
{
'label': 'All Transactions,
'backgroundColor': str(random_color()),
'data': data,
}
],
}
)
I want to create a dataset from each Transaction.client field and then pass it as Json to the ajax request. How would i be able to do that since the lables are the dates and some clients don't have transactions in certain dates but some do.
Thanks
You need to specify the user in your filter. Use request.user.
def x_chart(request):
def random_color():
return "#"+''.join([choice('ABCDEF0123456789') for i in range(6)])
labels=[]
data=[]
enddate = datetime.now()
startdate = datetime.now().date() - relativedelta(days=3)
the_client = request.user
transactions = Transaction.objects.filter(client=the_client,time__range=[startdate,enddate])
grouped_transactions = transactions.values("time__day").annotate(total=Sum('value'))
for key in grouped_transactions:
labels.append(key['time__day'])
data.append(key['total'])
return JsonResponse(
data={
'labels': labels,
'datasets': [
{
'label': 'All Transactions,
'backgroundColor': str(random_color()),
'data': data,
}
],
}
)
I'm developing a Flask app and at the moment everything works fine, but I'm unable to redirect the browser to the desired page. I can't even redirect to an external URL.
In the page /proposals there's a button which calls a JavaScript login function:
let provider;
let accounts;
let accountAddress = "";
let signer;
function submit_proposal() {
console.log("oh hey there");
// signer.signMessage("hello");
rightnow = (Date.now() / 1000).toFixed(0);
sortanow = rightnow - (rightnow % 600);
signer
.signMessage(
"Signing in to transparency.smartindex.cash at " + sortanow,
accountAddress,
"test password!"
)
.then((signature) => {
handleAuth(accountAddress, signature);
});
}
function handleAuth(accountAddress, signature) {
console.log(accountAddress);
console.log(signature);
fetch("login", {
method: "post",
headers: { "Content-Type": "application/json" },
body: JSON.stringify([accountAddress, signature]),
})
.then((response) => {
return response.json();
})
.then((data) => {
console.log(data);
});
}
ethereum.enable().then(function () {
provider = new ethers.providers.Web3Provider(web3.currentProvider);
provider.getNetwork().then(function (result) {
if (result["chainId"] != 10000) {
document.getElementById("msg").textContent = "Switch to SmartBCH!";
} else {
// okay, confirmed we're on mainnet
provider.listAccounts().then(async function (result) {
console.log(result);
accountAddress = result[0]; // getting uesrs publickey
// contract address and contract abi is used to create the contract instance
const contractAddress = "0xF05bD3d7709980f60CD5206BddFFA8553176dd29";
const contractABI = [
// balanceOf
{
constant: true,
inputs: [{ name: "_owner", type: "address" }],
name: "balanceOf",
outputs: [{ name: "balance", type: "uint256" }],
type: "function",
},
// decimals
{
constant: true,
inputs: [],
name: "decimals",
outputs: [{ name: "", type: "uint8" }],
type: "function",
},
];
// creating contract instance
const contract = new ethers.Contract(
contractAddress,
contractABI,
provider
);
// getting the contract decimals and balance
const decimals = await contract.decimals();
let balance = await contract.balanceOf(accountAddress);
balance = parseFloat(ethers.utils.formatUnits(balance, decimals));
if (balance < 5000) {
// if SIDX balance < 5000, insufficient balance
document.getElementById("msg").textContent =
"You need at least 5000 SIDX tokens to submit a proposal";
} else {
// else allow user to submit proposal
const submitProposalButton =
document.getElementById("submit_proposal");
submitProposalButton.disabled = false;
signer = provider.getSigner();
}
});
}
});
})
This is the Flask function which handles the login and tries to redirect to /submit_proposal:
#app.route('/login', methods=['POST', 'GET'])
def login():
if current_user.is_authenticated:
return redirect(url_for('submit_proposal'))
w3 = Web3(Web3.HTTPProvider('https://smartbch.greyh.at'))
if not w3.isConnected():
w3 = Web3(Web3.HTTPProvider('https://smartbch.fountainhead.cash/mainnet'))
public_address = request.json[0]
signature = request.json[1]
domain = "transparency.smartindex.cash"
rightnow = int(time.time())
sortanow = rightnow - rightnow % 600
original_message = 'Signing in to {} at {}'.format(domain, sortanow)
message_hash = defunct_hash_message(text=original_message)
signer = w3.eth.account.recoverHash(message_hash, signature=signature)
if signer == public_address:
ABI = open("/home/administrador/Descargas/BCH/transparency_portal/ABIs/ERC20-ABI.json", "r") # Standard ABI for ERC20 tokens
abi = json.loads(ABI.read())
contract = w3.eth.contract(address="0xF05bD3d7709980f60CD5206BddFFA8553176dd29", abi=abi)
SIDX_balance = contract.functions.balanceOf(signer).call() / 10 ** 18
if SIDX_balance < 5000:
flash('You need at least 5000 SIDX token to submit a proposal')
return url_for('proposals')
else:
if db.session.query(Users).filter(Users.public_address == signer).first() is None:
user = Users(public_address=signer)
db.session.add(user)
db.session.commit()
user = Users.query.filter_by(public_address=signer).first()
login_user(user)
# return redirect(url_for('submit_proposal'))
else:
abort(401, 'Could not authenticate signature')
return redirect(url_for('submit_proposal'))
Despite the redirects fails, I get this message in the console:
127.0.0.1 - - [25/Dec/2021 15:47:09] "GET /submit_proposal HTTP/1.1" 200 -
The user is logged correctly (I've check it), so I can manually so to /submit_proposal.
This is the /submit_proposal view:
#app.route('/submit_proposal')
#login_required
def submit_proposal():
with open('data/SIDX_STATS.json') as sidx_stats_file:
sidx_stats = json.load(sidx_stats_file)
print(request)
return render_template("submit_proposal.html", title="Submit a proposal", sidx_stats=sidx_stats)
Request output is <Request 'http://127.0.0.1:5000/submit_proposal' [GET]>.
It seems to be correct, but the browser does nothing. Even I tried to just redirect to an external page, but again, browser does nothing. This is not the first time I cannot get redirect to work, so I guess that the error is not on the login function.
EDIT:
Please, someone with some JavaScript knowledge can guide me to do something like this?
function submit_proposal() {
console.log("oh hey there");
// signer.signMessage("hello");
rightnow = (Date.now() / 1000).toFixed(0);
sortanow = rightnow - (rightnow % 600);
signer
.signMessage(
"Signing in to transparency.smartindex.cash at " + sortanow,
accountAddress,
"test password!"
)
.then((signature) => {
handleAuth(accountAddress, signature);
})
.then((response)=>{
if(response.redirected){
window.location.href = response.url;
}
})
.catch(function(e){
})
}
What I'm trying to do is, once the function submit_proposal is called, wait for a server response with the redirection.
I've got a Django website and I'm trying to integrate Stripe using Django the Stripe API on the backend and Vue.js on the frontend. However, when I try to run the checkout link that's supposed to redirect me to the payment processing page, I get the following error:
Error: IntegrationError: stripe.redirectToCheckout: You must provide one of lineItems, items, or sessionId.
at new r (https://js.stripe.com/v3/:1:6143)
at Js (https://js.stripe.com/v3/:1:165350)
at $s (https://js.stripe.com/v3/:1:165646)
at https://js.stripe.com/v3/:1:166758
at Qs (https://js.stripe.com/v3/:1:166769)
at nc (https://js.stripe.com/v3/:1:167275)
at Ec.redirectToCheckout (https://js.stripe.com/v3/:1:188030)
at http://localhost:8000/dashboard/myaccount/teams/plans/:342:39
Here's the Vue.js method responsible for this:
<script src="https://js.stripe.com/v3/"></script>
<script>
const PlansApp = {
data() {
return {
}
},
delimiters: ['[[', ']]'],
methods: {
subscribe(plan) {
console.log('Subscribe:', plan);
const stripe = Stripe('{{ stripe_pub_key }}');
fetch('/dashboard/myaccount/teams/api/create_checkout_session/', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': '{{ csrf_token }}'
},
body: JSON.stringify({
'plan': plan
})
})
.then(function(response) {
return response.json()
})
.then(function(session) {
console.log(session)
return stripe.redirectToCheckout({ sessionId: session.sessionId })
})
.then(function(result) {
if (result.error) {
console.log('Error:', result.error.message)
}
})
.catch(function(error) {
console.log('Error:', error);
});
}
}
}
Vue.createApp(PlansApp).mount('#plans-app')
</script>
And here's the Django code that creates the session on the backend:
#login_required
def create_checkout_session(request):
stripe.api_key = settings.STRIPE_SECRET_KEY
data = json.loads(request.body)
plan = data['plan']
if plan == 'basic':
price_id = settings.STRIPE_BASIC_PRICE_ID
else:
price_id = settings.STRIPE_PRO_PRICE_ID
try:
checkout_session = stripe.checkout.Session.create(
client_reference_id = request.user.userprofile.active_team_id,
success_url = '%s%s?session_id={CHECKOUT_SESSION_ID}' % (settings.WEBSITE_URL, reverse('team:plans_thankyou')),
cancel_url = '%s%s' % (settings.WEBSITE_URL, reverse('team:plans')),
payment_method_types = ['card'],
mode = 'subscription',
line_items = [
{
'price': price_id,
'quantity': 1
}
]
)
return JsonResponse({'sessionId': checkout_session['id']})
except Exception as e:
return JsonResponse({'error': str(e)})
I'm struggling to find out why I'm getting the error that I'm getting and would be grateful for any help!
I guest the problem come from the 'success_url' and the 'cancel_url'.
Try to add http:// or https:// in your url
Cordially
here is the 'token' generated on back end
def get(self, request):
if self.user.is_authenticated:
# the logged user's data is stored
else:
token = get_random_string() #this function was imported from other file
here I am sending the token to requested url as Json file
but can't take it on front end and send it to back end when the user is requested to the url
before the user already requested!
please help me out!!!
here is the Vue file in front end
searchProduct(keyword){
if(this.selectedCatId != '' && this.selectedCatId != 'all'){
this.$router.push({name: 'search', query:{
k:keyword,
cpn: this.$route.query.cpn ? this.$route.query.cpn : 1,
cid: this.selectedCatId}
})
}else{
this.$router.push({name: 'search', query:{
k: keyword,
cpn: this.$route.query.cpn ? this.$route.query.cpn : 1}
})
}
this.$axios.get('requested url'+this.searchKeyword+'&pagenum=1&productsPerPage=10', {
params: {
usertoken: localStorage.getItem('unregUserSearchToken')
}
})
.then(function (response) {
localStorage.setItem('unregUserSearchToken', response.data.search_token)
console.log(response);
})
searchProduct(keyword) {
this.$axios.get('requested url' + this.searchKeyword + '&pagenum=1&productsPerPage=10', {
params: {
usertoken: localStorage.getItem('unregUserSearchToken')
}
}).then(function (response) {
localStorage.setItem('unregUserSearchToken', response.data.search_token)
console.log(response);
if (this.selectedCatId !== '' && this.selectedCatId !== 'all') {
this.$router.push({
name: 'search',
query: {
k: keyword,
cpn: this.$route.query.cpn ? this.$route.query.cpn : 1,
cid: this.selectedCatId
}
})
} else {
this.$router.push({
name: 'search',
query: {
k: keyword,
cpn: this.$route.query.cpn ? this.$route.query.cpn : 1
}
})
}
})
}
You need to wait for the http request response before proceeding with the route jump operation, so as to ensure that the storage cache is correctly retrieved in the new page.
Geckoboard offers this documentation to connect to their datasets API, which you can see the implementation below.
var API_KEY = 'API_KEY';
var gb = require('geckoboard')(
API_KEY
);
gb.datasets.findOrCreate(
{
id: 'sales.by_day',
fields: {
quantity: {
type: 'number',
name: 'Number of sales'
},
gross: {
type: 'money',
name: 'Gross value of sales',
currency_code: "USD"
},
date: {
type: 'date',
name: 'Date'
}
}
},
function (err, dataset) {
if (err) {
console.error(err);
return;
}
dataset.put(
[
{ date: '2016-01-01', quantity: 819, gross: 2457000 },
{ date: '2016-01-02', quantity: 409, gross: 1227000 },
{ date: '2016-01-03', quantity: 164, gross: 492000 }
],
function (err) {
if (err) {
console.error(err);
return;
}
console.log('Dataset created and data added');
}
);
}
);
I'd like to see if there is a way to post this additional data via python (not using node.js). Would something like this be possible or must I use mode?
[
{ date: '2017-01-01', quantity: 1213, gross: 23423 },
{ date: '2017-01-02', quantity: 111, gross: 1313123 },
{ date: '2017-01-03', quantity: 333, gross: 21314 }
]
Update: Geckoboard now has their own official Python client library for their Datasets API https://github.com/geckoboard/geckoboard-python
It's definitely possible to use Python with Geckoboard's Datasets API. You can use any language or platform that can perform HTTPS requests with JSON - though Geckoboard has only released official library's for Ruby and Node so far.
Edit: I made a quick example below, but later found this: https://github.com/helium/geckoboard-python/
In short you just need to:
PUT with the a schema object to https://api.geckoboard.com/datasets to create a dataset
PUT with the a data array to https://api.geckoboard.com/datasets/:id to replace all data in a dataset
POST with the a data array to https://api.geckoboard.com/datasets/:id to append to the data in a dataset
DELETE to https://api.geckoboard.com/datasets/:id to delete a dataset
These requests are outlined at -- https://developer.geckoboard.com/api-reference/curl/
I haven't written much Python, so this may not be very Pythonic, but here's a way you could create a Geckoboard library in Python to do this for you, using the requests library underneath:
import requests
class Geckoboard(object):
def __init__(self, api_key):
self.api_key = api_key
def create(self, name, schema):
url = 'https://api.geckoboard.com/datasets/%s' % name
return requests.put(url, json=schema, auth=(self.api_key, ''))
def delete(self, name):
url = 'https://api.geckoboard.com/datasets/%s' % name
return request.delete(url, auth=(self.api_key, ''))
def replace(self, name, data):
url = 'https://api.geckoboard.com/datasets/%s/data' % name
return requests.put(url, json=data, auth=(self.api_key, ''))
def append(self, name, data):
url = 'https://api.geckoboard.com/datasets/%s/data' % name
return requests.post(url, json=data, auth=(self.api_key, ''))