I am trying to get the ID of Options however I do not now what I can do to get it?
I am new to Django - I have got the question ID through a parameter however I am not trying to pass another parameter. Is there a filter or get command that can be used?
I am trying to edit an existing option however it doesn't know which option it is looking for as there is more than one. The only way to identify is through its ID
Model
class Option(models.Model):
OptionID = models.AutoField(primary_key=True, unique=True)
OptionText = models.CharField(max_length=256, null=True)
QuestionsID = models.ForeignKey(Question, on_delete=models.CASCADE)
def __str__(self):
return str(self.OptionID)
View
#login_required(login_url='loginPage')
def question_editOption(request, id):
question = Question.objects.get(QuestionsID = id)
options = Option.objects.filter(QuestionsID = question)
current_user = request.user
c = current_user.userID
if current_user.is_admin:
if request.method == 'POST':
edited = request.POST.get('Q')
if request.POST['Q']:
obj = Option.objects.filter(QuestionsID = id, ).update(OptionText = edited)
messages.success(request, "Edited")
return redirect('dashboardAdmin')
# elif not request.POST['Q']:
# obj = Question.objects.filter(QuestionsID = id).update(QuestionText = oldVal)
# messages.error("Question Is Null!")
# return redirect('question/edit/<int:id>/')
else:
messages.error("User is not admin")
return redirect('dashboardPage')
context = {'question' : question,
'options' : options}
return render(request, 'editOption.html', context)
HTML
<!DOCTYPE html>
<html>
<head>
<title>Admin Panel</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.6.1/css/all.css" integrity="sha384-gfdkjb5BdAXd+lj+gudLWI+BXq4IuLW5IT+brZEZsLFm++aCMlF1V92rMkPaX4PP" crossorigin="anonymous">
<style>
body,
html {
margin: 0;
padding: 0;
height: 100%;
background: #7abecc !important;
}
.user_card {
width: 350px;
margin-top: auto;
margin-bottom: auto;
background: #74cfbf;
position: relative;
display: flex;
justify-content: center;
flex-direction: column;
padding: 10px;
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
-webkit-box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
-moz-box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
border-radius: 5px;
}
.form_container {
margin-top: 20px;
}
#form-title{
color: #fff;
}
#questionTitle {
text-align: left;
}
.login_btn {
width: 100%;
background: #33ccff !important;
color: white !important;
}
.login_btn:focus {
box-shadow: none !important;
outline: 0px !important;
}
.login_container {
padding: 0 2rem;
}
.input-group-text {
background: #f7ba5b !important;
color: white !important;
border: 0 !important;
border-radius: 0.25rem 0 0 0.25rem !important;
}
.input_user,
.input_pass:focus {
box-shadow: none !important;
outline: 0px !important;
}
#messages{
background-color: grey;
color: #fff;
padding: 10px;
margin-top: 10px;
}
</style>
</head>
<body>
<div class="container h-100">
<div class="d-flex justify-content-center h-100">
<div class="user_card">
<div class="d-flex justify-content-center">
<h3 id="form-title">Edit Option</h3>
</div>
<div class="d-flex justify-content-center form_container">
<form method="POST" action="">
{% csrf_token %}
<input type="text" id="{{ options.OptionText }}" name="Q" value="{{ options.OptionText }}">
<div class="d-flex justify-content-center mt-3 login_container">
<input class="btn login_btn" type="submit" value="Submit">
</div>
</form>
</div>
{% for message in messages %}
<p id='messages'>{{message}} </p>
{% endfor %}
</div>
</div>
</div>
</div>
</body>
</html>
def question_editOption(request, id):
question = Question.objects.get(QuestionsID = id)
options = Option.objects.filter(QuestionsID = question[0])
Without the error message I'm not 100% sure what the fix will be.
But when I define an object and passing it through as the pk for another field I usually have to actually access the object by accessing the first index being [0]
I assume the id in your function is the primary key being passed from the URL?
Related
I am trying to see how many users answered each option however it will give me the result of how many people answered the first option. Result object is where all answered are saved to.
Do I need to make a loop in the html? Would this not work as you cant call Result in to html and filter it ? How would I go around doing this. I see the counter is staying to the first value and keeps looping for each option, but I am confused on a fix for this.
HTML
<!DOCTYPE html>
<html>
<head>
<title>Admin Panel</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.6.1/css/all.css" integrity="sha384-gfdkjb5BdAXd+lj+gudLWI+BXq4IuLW5IT+brZEZsLFm++aCMlF1V92rMkPaX4PP" crossorigin="anonymous">
<style>
body,
html {
margin: 0;
padding: 0;
height: 100%;
background: #7abecc !important;
}
.user_card {
width: 350px;
margin-top: auto;
margin-bottom: auto;
background: #74cfbf;
position: relative;
display: flex;
justify-content: center;
flex-direction: column;
padding: 10px;
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
-webkit-box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
-moz-box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
border-radius: 5px;
}
.form_container {
margin-top: 20px;
}
#form-title{
color: #fff;
}
#questionTitle {
text-align: left;
}
.login_btn {
width: 100%;
background: #33ccff !important;
color: white !important;
}
.login_btn:focus {
box-shadow: none !important;
outline: 0px !important;
}
.login_container {
padding: 0 2rem;
}
.input-group-text {
background: #f7ba5b !important;
color: white !important;
border: 0 !important;
border-radius: 0.25rem 0 0 0.25rem !important;
}
.input_user,
.input_pass:focus {
box-shadow: none !important;
outline: 0px !important;
}
#messages{
background-color: grey;
color: #fff;
padding: 10px;
margin-top: 10px;
}
</style>
</head>
<body>
<div class="container h-100">
<div class="d-flex justify-content-center h-100">
<div class="user_card">
<div>(-- <br/></div>
<div class="d-flex justify-content-center">
<h3 id="form-title">Question Statistics</h3>
</div>
<div class="d-flex justify-content-center form_container">
<form method="POST" action="">
{% csrf_token %}
<div class="input-group mb-3">
<h6 id="questionTitle"> {{question.QuestionText}} </h6>
</div>
<div> <h7> The Amount Of Users Who Answered Were: {{counter}} </h7> </div>
</br>
{% for option in options %}
<label for="{{ option.OptionID }}">{{ option.OptionText }} <br> This Option Was Chosen by: {{counter2}} Users</label> <br>
{% endfor %}
<div class="d-flex justify-content-center mt-3 login_container">
<input class="btn login_btn" type="submit" value="Submit">
</div>
</form>
</div>
{{form.errors}}
{% for message in messages %}
<p id='messages'>{{message}} </p>
{% endfor %}
</div>
</div>
</div>
</div>
</body>
</html>
Model
class Result(models.Model):
ResponseID = models.AutoField(primary_key=True, unique=True)
userID = models.ForeignKey(Account, on_delete=models.CASCADE)
QuestionsID = models.ForeignKey(Question, on_delete=models.CASCADE)
ChosenOptionID = models.ForeignKey(Option, on_delete=models.CASCADE)
def __str__(self):
return str(self.ResponseID)
VIEWS for statstic
def question_statistics(request, id):
question = Question.objects.get(QuestionsID = id)
options = Option.objects.filter(QuestionsID = question)
r = Result.objects.filter(QuestionsID = id)
counter = 0
for x in r:
counter+=1
a = Result.objects.filter(ChosenOptionID = options)
counter2 = 0
for y in options:
a = Result.objects.filter(ChosenOptionID = y)
for x in a:
counter2+=1
current_user = request.user
if current_user.is_admin:
pass
else:
messages.error("User is not admin")
return redirect('dashboardPage')
context = {'question' : question,
'options' : options,
'results' : r,
'counter' : counter,
'counter2' : counter}
return render(request, 'questionStatistic.html', context)
Your 'counter2': counter should be 'counter2': counter2. It's returning the answer to the first question because the variable you're calling is the counter for the first question.
I want to display percent instead of an integer.
Now it simply shows the value as integer when hovering on the data point of the chart (the tooltip).
I think I need to set in the formatter formula like this:
let test = value / SUM(all_values)
return test.toFixed(0) + '%'
But, I could not find it in their documentation, the best I found is this one which always gives me 100%, per every data point:
tooltip: {
y: {
formatter: function(value, opts) {
let percent = opts.w.globals.seriesPercent[opts.seriesIndex][opts.dataPointIndex];
return percent.toFixed(0) + '%'
}
}
}
You're right that you'll need to use the tooltip formatter, but the array you're using to get the percentage values isn't correct.
If you log the values opts.w.globals.seriesPercent you'll find that it's all 100's:
[[100, 100, 100, ..., 100]]
(I suspect this might be because it's intended to be used with other chart types.)
You can still get the percentage though, it'll just need to be worked out.
Using your same method to format the tooltip, but getting the values from opts.series instead:
tooltip: {
y: {
formatter: function(value, opts) {
const sum = opts.series[0].reduce((a, b) => a + b, 0);
const percent = (value / sum) * 100;
return percent.toFixed(0) + '%'
},
},
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<!-- Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.1.3/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script src="app/app.js"></script>
<script>
let apiLabels = [];
let apiData = [];
let currentTimestamp = (Math.floor(Date.now() / 1000)).toString();
//use this URL for daily fetch
//let url = "https://aave-api-v2.aave.com/data/rates-history?reserveId=0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb480xb53c1a33016b2dc2ff3653530bff1848a515c8c5&resolutionInHours=24&from="+currentTimestamp;
let url = "https://aave-api-v2.aave.com/data/rates-history?reserveId=0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb480xb53c1a33016b2dc2ff3653530bff1848a515c8c5&resolutionInHours=24&from=1639813032";
// months list
const monthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
// fetch from api
var xhr = new XMLHttpRequest();
xhr.addEventListener("readystatechange", function () {
if (this.readyState === 4) {
let myData = JSON.parse(this.responseText);
console.log(myData);
for (let i = 0; i < myData.length; i++) {
//let formedDate = (myData[i]['x']['year']+'-'+myData[i]['x']['month']+'-'+myData[i]['x']['date']).toString();
let formedDate = monthNames[myData[i]['x']['month']] + ' ' + myData[i]['x']['date'];
console.log(formedDate);
let formedLiquidData = (myData[i]['liquidityRate_avg'] * 100).toFixed(2);
console.log(formedLiquidData+"%");
apiLabels.push(formedDate);
apiData.push(formedLiquidData);
}
const data = {
labels: apiLabels,
datasets: [
{
label: "USDC",
borderColor: "rgb(180,11,107)",
data: apiData
}
]
};
const config = {
type: "line",
data: data,
options:{
scales: {
y: {
ticks: {
callback: function (value, index, values) {
return value + '%';
}
}
},
},
},
};
const myChart = new Chart(document.getElementById("myChart"), config);
}
});
xhr.open(
"GET",
url
);
xhr.send();
</script>
</div>
<div id="app"></div>
<title>brew</title>
<style>
body {
background-color: white;
}
.center-form {
width: 80%;
margin: auto;
}
#title {
color: teal;
text-align: center;
}
.waitlist {
position: relative;
z-index: 3;
width: 146px;
height: 30px;
margin-top: 60px;
border-style: solid;
border-width: 1px;
border-color: #081852;
background-color: transparent;
box-shadow: -10px 10px 0 0 #081852;
color: #081852;
font-size: 12px;
line-height: 30px;
font-weight: 400;
text-align: center;
letter-spacing: 0.21px;
position: fixed;
right: 3%;
top: -5%;
}
.waitlist-button {
display: inline-block;
padding: 9px 15px;
background-color: #3898EC;
color: white;
border: 0;
line-height: inherit;
text-decoration: none;
cursor: pointer;
border-radius: 0;
}
.box-prices {
padding: 20px;
width: 200px;
height: auto;
color: #000;
/* background-color: #fff; */
border: 4px solid #1c1c53;
border-radius: 2px;
}
.dropbtn {
background-color: navy;
color: white;
padding: 16px;
font-size: 16px;
border: none;
}
.dropdown-content {
display: none;
position: absolute;
background-color: #f1f1f1;
min-width: 160px;
box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
z-index: 1;
}
.dropdown-content a {
color: black;
padding: 12px 16px;
text-decoration: none;
display: block;
}
.dropdown-content a:hover {
background-color: #ddd;
}
.dropdown:hover .dropdown-content {
display: block;
}
.dropdown:hover .dropbtn {
background-color: #0b95f1;
}
footer {
display: flex;
justify-content: space-between;
}
.myChart {
width: 50%;
height: 40px;
}
/* Decorative */
a {
text-decoration: none;
color: #555;
}
footer {
background-color: #82cdf8;
padding: 20px 40px;
}
.right {
float: left;
text-align: center;
}
.article {
color: white;
}
</style>
</head>
<body>
<img src="https://uploads-ssl.webflow.com/61768faf04d20bf3487b5a2a/6176a6363e64b8d84e32d0b7_brew-icon-256px-v2.png"
loading="eager" width="55" height="55" alt="Brew" class="img-logo" position="absolute" top="-3%" left="7;">
<!-------------- title------------------------>
<div class="container">
<div class="row">
<div class="col-md-12 mt-2">
<h1 style="color: #1c98">
Stablecoin Deposits on Aave
</h1>
<a data-w-id="14f1dfb2-926f-581f-7faa-3f62171b1db3" href="" class="waitlist waitlist-button">Join the
waitlist</a>
</div>
</div>
</div>
<!------------------------AAVE PRICE ------------>
<div class="container">
<div class="row mt-5">
<div class="col-md-6">
<div class="aave-prices">
<p>AAVE PRICE</p>
<p>$172.8</p>
<p>16%</p>
</div>
</div>
<!------------------------AAVE DESCRIPTION ------------>
<div class="col-md-6">
<h1>What is AAVE ?</h1>
<p>Aave is an open source and non-custodial liquidity protocol for earning
interest on deposits and borrowing assets.</p>
</div>
</div>
<!------------------------AAVe CHAIN ------------>
<div class="row">
<div class="col-md-12 mt-3">
<button class="dropbtn">CHAIN</button>
<div class="dropdown-content">
Polygon
Ethereum
Avalance
</div>
</div>
</div>
</div>
<!------graph----->
<div>
<canvas id="myChart" height="50" weidth="50"></canvas>
</div>
<!-- calculator -->
<div class="container mt-5" style="border: 1px solid black; border-radius: 5px;">
<div class="row">
<div class="col-md-12">
<h1 id="title">How Much You Can Earn ?</h1>
</div>
</div>
<br>
<div class="row">
<div class="col-md-6">
<form>
<div class="form-group mt-2">
<label class="form-group">Amount</label>
<input class="form-control mt-2" type="text" id="principal" placeholder="$">
</div>
<div class="form-group mt-2">
<label class="form-group">Interest rate: 4%</label>
</div>
<div class="form-group mt-2">
<label class="form-group">Compound Freequency: Daily</label>
</div>
<div class="form-group mt-2">
<label class="form-group">Payout Freequency: Monthly</label>
</div>
<button class="btn btn-block btn-info mt-3" type="button" onclick="calculate()">Calculate</button>
</form>
</div>
<div class="col-md-6">
<form style="padding-top: 70px;">
<div class="form-group mt-2">
<label class="form-group">Interest rate: 5%</label>
</div>
<div class="form-group mt-2">
<label class="form-group">Compound Freequency: Daily</label>
</div>
<div class="form-group mt-2">
<label class="form-group">Payout Freequency: Monthly</label>
</div>
</form>
</div>
</div>
<br>
<div class="row">
<div class="col-md-6">
<h5 class="total">Result USD</h5>
<h1 id="USD"></h1>
</div>
<div class="col-md-6">
<h5 class="total">Result USDT</h5>
<h1 id="USDC"></h1>
</div>
</div>
</div>
<!-- calculator end -->
<div>
<canvas id="myChart_subbagain" height="50" weidth="50" top="80%"></canvas>
</div>
<!----footer-->
<div class="col-md-12 mt-5">
<footer>
<div class="col-md-6">
<img src="/dawnload.png" alt="" width="150">
</div>
<div class="col-md-6">
<section class="right">
Join Brew Today
<article>USDC is not a legal tender recognised by US or any other government. Unlike a bank account, your
deposit is not insured. While Brew will make every effort to ensure that your deposit earn the best interest
rates in the most secure way possible, please note that any investment entails risk. Interest Rates are
subject to change anytime as per the market conditions.</article>
</section>
</div>
</footer>
</div>
</body>
<script type="text/javascript">
function calculate() {
var principle = 0;
var interest = 5 / 100;
var numberOfPeriod = 12;
var time = 10;
var CI = 0;
principle = document.getElementById("principal").value;
// CI = ((p * (1 + i) ^ n) - p);
CI = principle * (1 + interest / numberOfPeriod) ^ (numberOfPeriod * time);
document.getElementById("USD").innerHTML = CI;
document.getElementById("USDC").innerHTML = CI;
}
</script>
<!------cal graph-->
</html>
What I am trying to do is to create an invoice pdf file with several table rows. Table rows would be created using for loop in Django. The problem is data inside for loop tag is not visible on the pdf file.
You can check the screenshots below. Django properly renders invoice.html template so the code is valid, but the pdf file contains empty frame without any table rows. To render pdf from html I am using xhtml2pdf.
how django render the invoice.html template
how pdf file looks like
invoice.html
<html>
<head>
{% load static %}
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta charset="UTF-8">
<style>
#font-face {
font-family: Roboto;
src: url('{% static 'fonts/Roboto-Regular.ttf' %}');
}
#font-face {
font-family: Roboto-bold;
src: url('{% static 'fonts/Roboto-Bold.ttf' %}');
font-weight: bold;
}
#page {
size: a4 portrait;
#frame header_frame { /* Static Frame */
-pdf-frame-content: frame_header_left;
left: 50pt; width: 245pt; top: 30pt; height: 150pt;
}
#frame header_frame { /* Static Frame */
-pdf-frame-content: frame_header_right;
left: 300pt; width: 245pt; top: 50pt; height: 150pt;
}
#frame content_frame { /* Content Frame */
-pdf-frame-content: frame_invoice_number;
left: 50pt; width: 512pt; top: 170pt; height: 30pt;
}
#frame col1 {
-pdf-frame-content: frame_col1;
left: 50pt; width: 245pt; top: 220pt; height: 130pt;
}
#frame col2 {
-pdf-frame-content: frame_col2;
left: 300pt; width: 245pt; top: 220pt; height: 130pt;
}
#frame frame_services {
-pdf-frame-content: frame_services;
left: 50pt; width: 512pt; top: 380pt; height: 250pt;
-pdf-frame-border: 1;
}
#frame content_frame {
-pdf-frame-content: frame_summary;
left: 465pt; width: 100pt; top: 590pt; height: 50pt;
}
#frame content_frame {
-pdf-frame-content: frame_vat;
left: 50pt; width: 512pt; top: 590pt; height: 150pt;
}
#frame content_frame {
-pdf-frame-content: frame_signatures_left;
left: 50pt; width: 140pt; top: 725pt; height: 70pt;
}
#frame content_frame {
-pdf-frame-content: frame_signatures_right;
left: 400pt; width: 140pt; top: 725pt; height: 70pt;
left: 400pt; width: 140pt; top: 725pt; height: 70pt;
}
#frame content_frame {
-pdf-frame-content: footer_content;
left: 50pt; width: 512pt; top: 775pt; height: 50pt;
}
}
body {
background-color: white;
font-family: "Roboto", sans-serif;
}
.right{
font-size: 10px;
text-align: right;
}
.left{
text-align: left;
}
.invoice-number {
font-size: 18px;
font-family: "Roboto-bold", sans-serif;
}
.col-titles {
font-size: 16px;
text-decoration: underline;
font-family: "Roboto-bold", sans-serif;
}
.footer {
font-size: 8px;
text-align: center;
}
p{
font-size: 10px;
line-height: 0;
}
table {
border-bottom: 1px solid #ddd;
text-align: center;
}
td, td {
border-bottom: 1px solid #ddd;
vertical-align: middle;
}
.summary{
border-bottom: 1px solid #ddd;
}
.signatures {
border-top: 1px solid black;
font-size: 8px;
text-align: center;
}
th {
height: 36px;
}
td {
height: 25px;
}
</style>
</head>
<body>
<div>
<div>
<div id="frame_header_left" class="left">
<img src="{% static 'invoices/logo.png' %}" alt="logo" width="150" height="112">
</div>
<div id="frame_header_right" class="right">
<p>Miejsce wystawienia: Żabno</p>
<p>Data badania: {{ invoice.data_badania }}</p>
<p>Data wystawienia: {{ invoice.data_wystawienia_faktury }}</p>
</div>
</div>
<div id="frame_invoice_number">
<div class="invoice-number">
<h2>Faktura nr: {{ invoice.numer }}</h2>
</div>
</div>
<div id="frame_col1">
<p class="col-titles">Sprzedawca</p>
<div>
<p>MEDIKAP</p>
<p>ul. Plac Grunwaldzki 15B, 33-240 Żabno</p>
<p>NIP: 999999999</p>
<p>REGON: 9999999</p>
<p>Bank: ING Bank Śląski</p>
<p>Nr konta: 12 1234 1234 1243 1243 214 1244</p>
</div>
</div>
<div id="frame_col2">
<p class="col-titles">Nabywca</p>
<div>
<p> {{ invoice.firma}} </p>
<p> ul. {{ invoice.firma.ulica }} </p>
<p> {{ invoice.firma.kod_pocztowy }} {{ invoice.firma.miasto}}</p>
<p> NIP: {{ invoice.firma.nip }}</p>
<p> REGON: {{ invoice.firma.regon }}</p>
<p> forma płatności: {{ invoice.get_forma_platnosci_display}}</p>
</div>
</div>
<div id="frame_services">
<table>
<tr>
<th style="width: 50px;"> # </th>
<th style="width: 600px;"> Nazwa usługi</th>
<th style="width: 100px;"> Ilość</th>
<th style="width: 100px;"> Rabat[%]</th>
<th style="width: 100px;"> Cena usługi</th>
<th style="width: 100px;"> Wartość</th>
<th style="width: 100px;"> Wartość z rabatem:</th>
</tr>
{% for service in services_items %}
<tr>
<td> test </td>
<td> test </td>
</tr>
{% endfor %}
</table>
</div>
<div id="frame_summary" class="summary">
<p> : {{ service.get_total_value }} PLN</p>
<p> Wartość z uwzględnieniem {{ invoice.rabat}}% rabatu: {{ discounted_value|floatformat:"-2" }} PLN</p>
</div>
<div id="frame_vat">
<p> Podstawa zwolnienia z VAT: </p>
<p> Zwolnienie ze względu na zakres wykonywanych czynności (art. 43 ust.1) pkt 19 Ustawy o VAT</p>
</div>
<div id="frame_signatures_left">
<p class="signatures"> podpis osoby upoważnionej do odbioru faktury</p>
</div>
<div id="frame_signatures_right">
<p class="signatures"> podpis osoby upoważnionej do wystawienia faktury</p>
</div>
<div id="footer_content" >
<p class="footer">MEDIKAP Maria K.</p>
<p class="footer">Plac Grunwaldzki 15B, 33-240 Żabno</p>
<p class="footer">e-mail: gabinet.medikap#gmail.com tel: 539 993 332</p>
<p class="footer">NIP: 9930212793 REGON: 852441210</p>
</div>
</div>
</body>
</html>
views.py/DetailsInvoice
class DetailsInvoice(generic.View):
template_name = 'invoices/invoice_detail.html'
form_class = DetailInvoiceForm
success_url = reverse_lazy("invoices:list")
def get(self, request, invoice_id):
current_invoice = get_object_or_404(Invoice, id=invoice_id)
form = self.form_class(instance=current_invoice)
request.session['invoice_id'] = current_invoice.id
services = Service.objects.all()
all_service_items = ServiceItem.objects.all().filter(faktura = current_invoice).order_by('usluga')
context = {
'invoice': current_invoice,
'form' : form,
'services' : services,
'services_items' : all_service_items,
}
return render(request, self.template_name, context)
def post(self, request, invoice_id):
current_invoice = get_object_or_404(Invoice, id=invoice_id)
form = self.form_class(request.POST, instance=current_invoice)
all_service_items = ServiceItem.objects.all().filter(faktura=current_invoice)
context = {
'invoice' : current_invoice,
}
pdf = render_to_pdf('invoices/invoice.html', context)
services_assigned_to_invoice = current_invoice.uslugi.all()
if 'update-data' in request.POST and form.is_valid():
for service in all_service_items:
service_item = get_object_or_404(ServiceItem, id=service.id)
quantity_input = request.POST.get('quantity-' + str(service.id))
discount_input = request.POST.get('discount-' + str(service.id))
service_item.ilosc = int(quantity_input)
service_item.rabat = int(discount_input)
service_item.save()
form.save()
for service_item in all_service_items:
if service_item.usluga not in services_assigned_to_invoice:
service_item.delete()
for single_service in services_assigned_to_invoice:
new_service_item, created = ServiceItem.objects.get_or_create(usluga=single_service, faktura=current_invoice)
messages.success(request, 'Pomyślnie zaktualizowane dane')
return HttpResponseRedirect(self.request.META.get('HTTP_REFERER'))
if 'view-pdf' in request.POST:
return HttpResponse(pdf, content_type='application/pdf')
if 'download-pdf' in request.POST:
response = HttpResponse(pdf, content_type='application/pdf')
filename = f"Faktura {current_invoice.numer}.pdf"
content = "attachment; filename={}".format(filename)
response['Content-Disposition'] = content
return response
else:
return redirect('invoices:list')
rendering function
def render_to_pdf(template_src, context_dict={}):
template = get_template(template_src)
html = template.render(context_dict)
result = BytesIO()
pdf = pisa.pisaDocument(BytesIO(html.encode("utf-8")), result, link_callback=link_callback)
if not pdf.err:
return HttpResponse(result.getvalue(), content_type='application/pdf')
return None
You are not passing the same context variables to your PDF as the ones you are passing to your HTML template. To your HTML template you are passing:
context = {
'invoice': current_invoice,
'form' : form,
'services' : services,
'services_items' : all_service_items,
}
While to your PDF you are only passing:
context = {
'invoice' : current_invoice,
}
services_items is the one your PDF template seems to be missing. So because for service in services_items is an empty/non-existent list in your PDF template, it doesn't render any rows. In the future you can check this by adding an {% empty %} section to your for loop:
{% for service in services_items %}
<tr>
<td> test </td>
<td> test </td>
</tr>
{% empty %}
No items!
{% endfor %}
This is the array
[
{
"TO":"test#gmail.com",
"FROM":"nathanoluwaseyi#gmail.com",
"SUBJECT":"subject 1",
"NAME":"Oluwaseyi Oluwapelumi",
"MESSAGE-DATE":[
[
"Hey eniayomi heeyyy",
"2019-12-03 20:49:07"
]
]
},
{
"TO":"test#gmail.com",
"FROM":"pelz#gmail.com",
"SUBJECT":"Thanks for contacting R",
"NAME":"",
"MESSAGE-DATE":[
[
"Thanks for contacting me! Once i check my email, i shall definitely get back.",
"2019-08-18 19:48:10"
],
[
"will check it.",
"2019-08-18 19:48:10"
]
]
}
]
i need it to display on the angular frontend.
this is the mail.component.html file
<div class="card-body p-0">
<div class="float-left" style="width: 330px; height: 430px; border-right: 1px solid #dad9d9; overflow-x: hidden; overflow-y: auto;">
<div class="p-2 profile-card" style="width: 315px; height: 100px; border-bottom: 1px solid #dad9d9;" *ngFor="let mail of dataservice.data; let i = index;" (click)="viewMail(mail.MESSAGE_DATE,mail.FROM,mail.NAME,mail.DATE,i)" [ngClass]="{'highlight': selectedIndex === i}">
<div class="row">
<div class="col-md-3 pt-2">
<div class="rounded-circle shadow" style="background-image: url('images/avt.jpg'); background-repeat: round; height: 70px; width: 70px;">
<div style="height: 20px; width: 20px; border: 3px solid white;" class="rounded-circle bg-success"></div>
</div>
</div>
<div class="col-md-7 p-0 pl-3 pt-4" style="line-height: 12px;">
<p style="font-size:18px;"><b>{{mail.FROM}}</b></p>
<p style="font-size:13px;">{{mail.NAME }}.</p>
</div>
<div class="col-md-2 p-0 pt-3" style="line-height:11px;">
<p class="text-secondary" style="font-size:12px;">20m <i class="fa fa-star fa-md" aria-hidden="true"></i></p>
</div>
</div>
</div>
this is the data.service.ts file
mail_det() {
this.message = 'Welcome!';
console.log(this.message);
this.staff_email=sessionStorage.getItem('email');
console.log(this.staff_email)
this.http.get(this.domain_protocol + this.f_domain_name+'/api/v1.0/get_user_detail/?id='+this.staff_email)
.subscribe((res) => {
this.data = res
console.log(this.data)
})
}
this is the mail.component.ts file
viewMail(mail, mailer, mailee, user_date, _index: number) {
this.router.navigate(['mail/'+ mailer])
console.log(mail)
console.log(mailer)
console.log(user_date)
this.message = ''
sessionStorage.setItem('mailer', mailer)
sessionStorage.setItem('mailee', mailee);
sessionStorage.setItem('user_date', user_date)
console.log(sessionStorage.getItem('mailer'))
this.user_message = mail;
this.mailee = mailee;
this.user_date = user_date;
this.selectedIndex = _index;
}
i am doing something wrong. The only thing i get to show is the mail.FROM and mail.SUBJECT. I know this is because of the array in the mesage part. I dont know how to go about that.
In Data.service.ts
mail_det() {
this.message = 'Welcome!';
console.log(this.message);
this.staff_email=sessionStorage.getItem('email');
console.log(this.staff_email)
this.http.get(this.domain_protocol + this.f_domain_name+'/api/v1.0/get_user_detail/?id='+this.staff_email);
}
in mail.component.ts
public data: Array<any> = [];
constructor(public dataSrv: DataService <-- this is the class name of the data service you created; import it)
ngOnInit(){
this.dataSrv.mail_det().subscribe(result =>{
console.log(result); <-- your api response;
this.data = result;
}, error => {console.log(error);
});
}
in mail.component.html
<div class="card-body p-0">
<div class="float-left" style="width: 330px; height: 430px; border-right: 1px solid #dad9d9; overflow-x: hidden; overflow-y: auto;">
<div class="p-2 profile-card" style="width: 315px; height: 100px; border-bottom: 1px solid #dad9d9;" *ngFor="let mail of data; let i = index;" (click)="viewMail(mail.MESSAGE_DATE,mail.FROM,mail.NAME,mail.DATE,i)" [ngClass]="{'highlight': selectedIndex === i}">
<div class="row">
<div class="col-md-3 pt-2">
<div class="rounded-circle shadow" style="background-image: url('images/avt.jpg'); background-repeat: round; height: 70px; width: 70px;">
<div style="height: 20px; width: 20px; border: 3px solid white;" class="rounded-circle bg-success"></div>
</div>
</div>
<div class="col-md-7 p-0 pl-3 pt-4" style="line-height: 12px;">
<p style="font-size:18px;"><b>{{mail.FROM}}</b></p>
<p style="font-size:13px;">{{mail.NAME }}.</p>
</div>
<div class="col-md-2 p-0 pt-3" style="line-height:11px;">
<p class="text-secondary" style="font-size:12px;">20m <i class="fa fa-star fa-md" aria-hidden="true"></i></p>
</div>
</div>
</div>
I'm really stuck in this subject and maybe someone can help me out. I can always generate a token with stripe successfully but somehow my charge function doesn't wan't to work. I'm using the stripe element from their official documentation.
How can I find out where I have to search for the mistake because I don't get any error from the code. In the stripe dashboard I can see the generated tokens, that's why I think until this point there is everything right but I guess my mistake is in the view function. More precise I think the view function doesn't get the generated token from the javascript. Many thanks for your help in advance!
stripe_form.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
{% load static %}
<link rel="stylesheet" href="{% static 'css/stripe.css' %}">
<title>Document</title>
</head>
<body>
<div id="collapseStripe" class="wrapper">
<script src="https://js.stripe.com/v3/"></script>
<form action="" method="post" id="payment-form">
{% csrf_token %}
<div class="form-row">
<label for="card-element">
Credit or debit card
</label>
<div id="card-element" class="StripeElement StripeElement--empty">
<div class="__PrivateStripeElement" style="margin: 0px !important; padding: 0px !important; border: none !important; display: block !important; background: transparent !important; position: relative !important; opacity: 1 !important;"><iframe frameborder="0" allowtransparency="true" scrolling="no" name="__privateStripeFrame4" allowpaymentrequest="true" src="https://js.stripe.com/v3/elements-inner-card-bfbabea0af3ed365b5fe9ce78692fd3c.html#style[base][color]=%2332325d&style[base][fontFamily]=%22Helvetica+Neue%22%2C+Helvetica%2C+sans-serif&style[base][fontSmoothing]=antialiased&style[base][fontSize]=16px&style[base][::placeholder][color]=%23aab7c4&style[invalid][color]=%23fa755a&style[invalid][iconColor]=%23fa755a&componentName=card&wait=false&rtl=false&keyMode=test&origin=https%3A%2F%2Fstripe.com&referrer=https%3A%2F%2Fstripe.com%2Fdocs%2Fstripe-js%2Felements%2Fquickstart&controllerId=__privateStripeController1" title="Secure payment input frame" style="border: none !important; margin: 0px !important; padding: 0px !important; width: 1px !important; min-width: 100% !important; overflow: hidden !important; display: block !important; height: 19.2px;"></iframe><input class="__PrivateStripeElement-input" aria-hidden="true" aria-label=" " autocomplete="false" maxlength="1" style="border: none !important; display: block !important; position: absolute !important; height: 1px !important; top: 0px !important; left: 0px !important; padding: 0px !important; margin: 0px !important; width: 100% !important; opacity: 0 !important; background: transparent !important; pointer-events: none !important; font-size: 16px !important;"></div>
</div>
<!-- Used to display form errors. -->
<div id="card-errors" role="alert"></div>
</div>
<button>Submit Payment</button>
</form>
</div>
<div id="stripe-token-handler" class="is-hidden">Success! Got token: <span class="token"></span></div>
{% load static %}
<script src="{% static 'js/stripe.js' %}"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script type="text/javascript">
function toggleDisplay() {
var x = document.getElementById("collapseStripe");
if (x.style.display === "none") {
x.style.display = "block";
} else {
x.style.display = "none";
}
};
</script>
</body>
</html>
views.py
import stripe
stripe.api_key = settings.STRIPE_SECRET_KEY
def charge (request):
publishKey = settings.STRIPE_PUBLISHABLE_KEY
if request.method == 'POST':
try:
token = request.POST['stripeToken']
charge = stripe.Charge.create(
amount=999,
currency='usd',
description='Example charge',
source=token,
)
return redirect(request, 'registration/stripe_form.html')
except stripe.CardError as e:
message.info(request, "Your card has been declined.")
return render(request, 'registration/stripe_form.html')
stripe.js
var stripe = Stripe('pk_test_');
// Create an instance of Elements.
var elements = stripe.elements();
// Custom styling can be passed to options when creating an Element.
// (Note that this demo uses a wider set of styles than the guide below.)
var style = {
base: {
color: '#32325d',
fontFamily: '"Helvetica Neue", Helvetica, sans-serif',
fontSmoothing: 'antialiased',
fontSize: '16px',
'::placeholder': {
color: '#aab7c4'
}
},
invalid: {
color: '#fa755a',
iconColor: '#fa755a'
}
};
// Create an instance of the card Element.
var card = elements.create('card', {style: style});
// Add an instance of the card Element into the `card-element` <div>.
card.mount('#card-element');
// Handle real-time validation errors from the card Element.
card.addEventListener('change', function(event) {
var displayError = document.getElementById('card-errors');
if (event.error) {
displayError.textContent = event.error.message;
} else {
displayError.textContent = '';
}
});
// Handle form submission.
var form = document.getElementById('payment-form');
form.addEventListener('submit', function(event) {
event.preventDefault();
stripe.createToken(card).then(function(result) {
if (result.error) {
// Inform the user if there was an error.
var errorElement = document.getElementById('card-errors');
errorElement.textContent = result.error.message;
} else {
// Send the token to your server.
stripeTokenHandler(result.token);
}
});
});
// Submit the form with the token ID.
function stripeTokenHandler(token) {
// Insert the token ID into the form so it gets submitted to the server
var form = document.getElementById('payment-form');
var hiddenInput = document.createElement('input');
hiddenInput.setAttribute('type', 'hidden');
hiddenInput.setAttribute('name', 'stripeToken');
hiddenInput.setAttribute('value', token.id);
form.appendChild(hiddenInput);
// Submit the form
form.submit();
}
var successElement = document.getElementById('stripe-token-handler');
document.querySelector('.wrapper').addEventListener('click', function() {
successElement.className = 'is-hidden';
});
// Not in demo.
function stripeTokenHandler(token) {
successElement.className = '';
successElement.querySelector('.token').textContent = token.id;
}