Add a download functionality in django change view - javascript

I already added a button alongside the save buttons for my django change view:
{% extends 'admin/change_form.html' %}
{% load static %}
{% load i18n %}
{% block submit_buttons_bottom %}
<div class="submit-row">
<input type="submit" value="Download" id="download_profile" name="_continue">
<input type="submit" value="{% trans 'Save' %}" class="default" name="_save">
<input type="submit" value="{% trans 'Save and add another' %}" name="_addanother">
<input type="submit" value="{% trans 'Save and continue editing' %}" name="_continue">
<!-- inmport script -->
<script src="{% static '/js/downloadData.js' %}"></script>
<script src="{% static '/js/collapsibleSection.js' %}"></script>
<script src="{% static '/js/investmentAdminScript.js' %}"></script>
{% endblock %}
and I already started adding the script to retrieve individual data per row to download them.
'use strict';
window.addEventListener('load', () => {
const downloadButton = document.querySelector('#download_profile');
downloadButton.addEventListener('click', e => {
if (!confirm('Data will be saved before downloading. Are you sure you want to continue?')) {
e.preventDefault();
return;
}
// get module
const fieldsets = document.querySelectorAll('fieldset');
fieldsets.forEach(thisFieldset => {
const dataRows = thisFieldset.querySelectorAll('.form-row');
dataRows.forEach(dataRow => {
// retrieve each input field and add a download to .xlsx function
});
});
});
});
However, it gets complicated very fast. Is there a better way to do this?

Found a single JS file that allows you to format .xlsx files and start a download with one function
https://github.com/egeriis/zipcelx
Since you're using django, download the "standalone.js" file and add it to your static files. Reference it in your template in a script tag. Now you'll have access to the "zipcelx()" function
Here's a "getting started" example I made
const config = {
filename: "practice-file",
sheet: {
data: [
// Row 1
[
{value: "row1 value1",type:"string"},
{value: "1000",type: 'number'}
],
// Row 2
[
{value: "row2 value1", type: 'string'},
{value: "row2 value2", type: "string"}
]
]
}
}
// call zipcelx to immediately start the download in client's browser
zipcelx(config)
Example of the File Generated
Don't know how large your data sets are, might get tedious with having to format your data in such a way. Some helper functions should do the trick if that became a problem.
Hope this helped!

Related

Adding - button on Image ( JavaScript )

I am building a BlogApp and I am trying to add button on Image. I am showing image from django database in javascript (HTML).
I am trying to add clickable button on Image.
views.py
def user_stories(request):
posts = BlogPost.objects.filter(user=request.user)
template.html
<script>
var blogposts = new BlogPost('blogposts', {
blogposts: [
// {% for post in posts %}
BlogPost.buildTimelineItem(
'{{ post }}',
'{{ user.profile.file.url }}',
'{{ post.user }}',
'{{post.id}}',
timestamp(),
[
[
'{{post.id }}-1',
'photo',
3,
'{{ post.image.url }}',
'',
false,
false,
timestamp(),
],
]
),
// {% endfor %}
],
});
</script>
BlogPostJS.buildTimelineItem = (id, photo, name, link, lastUpdated, items) => {
const timelineItem = {
id,
photo,
name,
link,
lastUpdated,
items: []
};
each(items, (itemIndex, itemArgs) => {
timelineItem.items.push(BlogPostJS.buildBlogPostItem.apply(BlogPostJS, itemArgs));
});
return timelineItem;
};
{{ post.image.url }} is showing image, AND i am trying to add on it.
I also tried by adding :- '{{ post.image.url }}<button type='submit' </button>', BUT it is not showing on image.
I have no idea , how can i add button on image.
Any help would be Appreciated.
Any help would be Appreciated.
your problem is in BlogPost.buildTimelineItem you either need to modify it to include the button, or postprocess the result and add the button manually once the post is rendered. What you tried passes an invalid url because the function accepts image url which I suppose is rendered into an <img> tag.

jquery load() is not loading my django view in another view

So i have got my html and i would like to add my django view in div "radio2".
I am using JQuery function Load() but i have a problem because it returns error 404 with get request "http://127.0.0.1:8000/post/afafa/%7B%" and its not loading nothing in div
post_detail.html
<div class="post__recommendation__posts">
<div id="radio2" class="radio2">
</div>
{% for post in posts|slice:":3" %}
<div class="post__recommendation__post">
<div class="post__recommendation__post-image">
<img src={% static post.image.url %} alt="shakhur" />
</div>
<div class="post__recommendation__post-description">{{post.short_description}}</div>
</div>
{% endfor %}
</div>
Js function
$(document).ready(function (){
console.log("Loading page")
$(".radio-btn").click(function(){
console.log("radio - btn")
console.log($(this)[0].id)
$.ajax({
url: "/radio/",
type: 'POST',
data:{
radio: "radio",
input: $(this)[0].id
},
success: update_item()
})
})
})
function update_item() {
$('#radio2').load(
"{% url 'radio2' %}"
);
}
View
#csrf_exempt
def radio_test(request):
return render(request, 'blogapp/radio2.html')
radio2.html
<div class="radiodiv">
This is Radio2
</div>
my results in console
Not Found: /post/afafa/{%
[28/Sep/2020 15:52:19] "GET /post/afafa/%7B% HTTP/1.1" 404 3938
[28/Sep/2020 15:52:19] "POST /radio/ HTTP/1.1" 200 79
[28/Sep/2020 15:52:22] "GET /post/afafa/ HTTP/1.1" 200 10761
It seems that you're trying to use Django's templating engine in a static file.
This will not work because static files are not passed into the templating engine.
There are work-arounds. Easiest is to create a global variable in the main template and pass that into load:
<script>
var radio2_url = "{% url 'radio2' %}";
</script>
Put this before your other script.
Then in your js:
function update_item() {
$('#radio2').load(radio2_url);
}

How to insert data into a database every time I click Send from HTML button

I have an SMS function on my Django app, but I want to happen is record the message and timestamp each time I send a message. I need to store the value inside sms_message on another table every time I click send sms.
The entry on the other table will be like this:
id: 1
Description: As of {z.timestamp}, the Rainfall Warning is now at {z.level}. Please prepare for evacuation
Timestamp: XXXXX
Help, how to do it? Thanks!
#views.py
def send_sms(request):
aws_access_key_id = "XXXXXXXXXXXX"
aws_secret_access_key = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
aws_region_name = "us-east-1"
z = Rainfall.objects.latest('timestamp', 'level')
sender_id = "Test"
sms_message = f'As of {z.timestamp}, the Rainfall Warning is now at {z.level}. Please prepare for evacuation'
client = boto3.client(
"sns",
aws_access_key_id=aws_access_key_id,
aws_secret_access_key=aws_secret_access_key,
region_name=aws_region_name
)
topic = client.create_topic(Name="notifications")
topic_arn = topic['TopicArn'] # get its Amazon Resource Name
numbers = Mobile.objects.all()
for i in numbers:
client.subscribe(
TopicArn=topic_arn,
Protocol='sms',
Endpoint=i.mobile_number
)
response = client.publish(
Message=sms_message,
TopicArn=topic_arn,
MessageAttributes={
'string': {
'DataType': 'String',
'StringValue': 'String',
},
'AWS.SNS.SMS.SenderID': {
'DataType': 'String',
'StringValue': sender_id
}
}
)
messages.info(request, 'SMS sent successfully!')
return HttpResponseRedirect('/advisory/')
#sendsms.html
{% block content %}
{% if messages %}
{% for message in messages %}
{% if message.tags %} <script>alert("{{ message }}")</script> {% endif %}
{% endfor %}
{% endif %}
<form method="post" action="{% url 'send_sms' %}">
{% csrf_token %}
<button class="btn btn-danger btn-block btn-round">Send SMS</button>
</form>
{% endblock content %}

Access template options in module's construct method

In Apostrophe, I have a custom module where I would like to pass an option from the Nunjucks apos.area call to the construct method of the widget itself. Concretely, I want to adjust the output of getWidgetWrapperClasses based on the options passed to the module in the template. Is this possible?
Here's an example of what I would like to achieve:
lib/modules/example-widgets/index.js
module.exports = {
extend: "apostrophe-widgets",
label: "Example widget",
construct: function(self, options) {
self.getWidgetWrapperClasses = function(widget) {
// templateOptions would be the options object as defined
// in home.html below
return ["column", "column-" + templateOptions.width];
};
}
};
lib/modules/apostrophe-pages/views/pages/home.html
{% extends "layout.html" %}
{% block content %}
<div id="widgets">
{{ apos.area(data.page, "example", {
widgets: {
"example": {
width: "half"
}
}
}) }}
</div>
{% endblock %}
I solved this by not using the getWidgetWrapperClasses method, but instead extending the widget wrapper template and overriding a Nunjucks block in there. This is in fact a documented approach if you look in lib/modules/apostrophe-areas/views/widgetBase.html in Apostrophe's code.
I changed lib/modules/example-widgets/index.js like this:
module.exports = {
extend: "apostrophe-widgets",
label: "Example widget",
wrapperTemplate: "wrapper",
construct: function(self, options) {
// Do something
}
};
Then, I added a lib/modules/example-widgets/views/wrapper.html file. In that file, you can simply override the extraWrapperClasses block to add the classes you want, all the while having access to the template options through data.options.
{% extends "apostrophe-areas:widget.html" %}
{% block extraWrapperClasses %}column column-{{ data.options.width }}{% endblock %}

How to namespace with twig.js

I can see with twig.js that you can use namespacing for template paths:
https://github.com/justjohn/twig.js/wiki#user-content-namespaces
Where do you you specify the namespaces? Here it is in the documentation:
var template = Twig.twig({
data: your-template,
namespaces: { 'my-project': 'path/to/views/folder/' }
}).render();
That IS the specification...i.e. the next lines of the doc:
Ex:
{# your-template.twig #}
{% extends "my-project::template.twig" %}
The "my-project::" will now point to "path/to/views/folder/".

Categories