View to Download FileField From Django - python

I have files which are saved to the MEDIA_ROOT - and I am displaying the file paths as URLs in a table in my UI. I would like for these files to download when the user clicks the link in the table. However, when that happens I get an error because I don't have a URL or View defined to handle this I suppose. Problem is, I'm not really sure where to start - any suggestions. Below is my model, and the .html which displays the table and the link.
models.py
class Orders(models.Model):
...
order_file = models.FileField(upload_to='web_unit', null=True, blank=True)
...
def __str__(self):
return self.reference
index.html
<div class="table-responsive">
<table id="main_table" class="table table-striped table-bordered" cellspacing="0" style="width="100%">
<thead>
<tr>
....
</thead>
<tbody>
{% for orders in orders %}
<tr>
<td>
<!-- Update book buttons -->
<button type="button" class="update-book btn btn-sm btn-primary" style="color: #FFCF8B; border-color: #FFCF8B; background-color: #FFF;" data-id="{% url 'order_update' orders.pk %}">
<span class="fa fa-pencil"></span>
</button>
</td>
....
<td>Download</td> #this is the link
</tr>
{% endfor %}
</tbody>
</table>
When the link in the table is clicked - I'd like for the file to be downloaded - I need help on how to define the URL and the View to make this happen.
This has been marked as a duplicate a few times now - but I don't believe it is. The link that I have been referred to only shows a view. I don't understand how I am to trigger that view using a url since there will be many download links in the same screen. How does the view know which file link I have clicked on? Wouldn't that need to leverage the URL somehow?

First, don't do {% for orders in orders %}; instead do {% for order in orders %}
Then this should work (assuming order_file is the field name you didn't show in the model)
<td>Download</td>

Related

How to pass values from html to python

I have a 4 buttons on first page which put me through to another page(All those 'buttons' are connected to database in mysql) and on this second page I have some data from mysql tables which I wanna display depending on what I have chosen in the first page. Right now I just display everything I have and I don't really know how to change that. I was looking for solutions but none worked.
views.py
def kategorie_list(request):
obj = Kategorie.objects.all()
context ={'obj': obj}
return render(request, "kategorie/lista.html", context)
def uslugodawcy_list(request):
obj = Uslugodawcy.objects.all()
context ={'obj': obj}
return render(request, "uslugodawcy/uslugodawcy_lista.html", context)
first html page
{% for Kategorie in obj %}
<p> <a class="btn btn-primary" href="/uslugodawcy"><button type="nw" style="height: 65px; width: 170px"> <font size="4">{{Kategorie.idkategorie}} . {{Kategorie.nazwakategorii}}</font> </button> </a> </p>
{% endfor %}
second
{% for Uslugodawcy in obj %}
<p> <a class="btn btn-primary" href="/promocje"><button type="nw" style="height: 65px; width: 170px"> <font size="4">{{Uslugodawcy.iduslugodawcy}} . {{Uslugodawcy.nazwa_uslugodawcy}} </font> </button> </a> </p>
{% endfor %}
There are many approaches. In outline:
Style a link as a button. . If the href is http://djangoserver/url?foo=bar then request.GET['foo'] will be available and equal to "bar".
Make all the buttons relate to a form that you are displaying and POSTing, so all of them do a SUBMIT but have diffferent values that you can find in request.POST. <button form="form-id" type="submit" ...>
Use Javascript to cause clicking the button to fill in fields on the form (which may be hidden fields, so the user has no other way of changing them.

Django: update only items that are checked

I'd like to build a table with multiple items that have checkboxes, if those checkboxes are checked I want to update just those items via button click.
I already got an update view that does that, but only for one item and only if the save button for this item is pressed (every table item got it's own button). My code looks like this:
<table>
<thead>
<tr>
<th colspan="4">
<button type "submit">My Submit Button</button>
</th>
</tr>
<tr>
<th colspan="2">My Title</th>
<th>Movie title</th>
<th>Movie description</th>
<th>And so on</th>
</tr>
</thead>
<tbody>
<tr>
<th>
<input type="checkbox" class="custom-control-input">
</th>
<th>Data</th>
<th>Data</th>
<th>Data</th>
<th>Data</th>
<th>
<button>Button to edit this row item</button>
</th>
<th>
<button type="submit" form="movie{{ forloop.counter }}">Button to save the changes</button>
</th>
</tr>
<tr>
<th>
<input type="checkbox" class="custom-control-input">
</th>
<th>Data</th>
<th>Data</th>
<th>Data</th>
<th>Data</th>
<th>
<button>Button to edit this row item</button>
</th>
<th>
<button type="submit" form="movie{{ forloop.counter }}">Button to save the changes</button>
</th>
</tr>
</tbody>
<!-- the form for saving exactly one movie -->
<form class="hide" id="movie{{ forloop.counter }}" action="{% url 'myapp:movieDataUpdate' pk=movie.pk %}" method="post">
{% csrf_token %}
</form>
</table>
This is my existing view/urls/form for the Save Button on each row:
urls.py
from django.conf.urls import url
from . import views
app_name = "myapp"
urlpatterns = [
url(r'^$', views.AllMovies.as_view(), name="index"), views.UpdateMovieDataView.as_view(), name='movieDataUpdate'),
]
views.py
class UpdateMovieDataView(UpdateView):
model = Movie
form_class = UpdateMovieDataForm
success_url = reverse_lazy('myapp:index')
def form_valid(self, form):
self.object.slug = slugify(form.cleaned_data['title'])
return super(UpdateMovieDataView, self).form_valid(form)
forms.py
class UpdateMovieDataForm(forms.ModelForm):
class Meta:
model = Movie
fields = ['title', 'date', 'director', 'runtime', 'genre', 'status']
I hope someone could help me here, tried to figure it out, but didn't succeeded yet. Maybe someone with a lot more experience can help :)
You can add javascript on it (jQuery is easy to start).
You first add jQuery to your html page (download here).
Then you add an id to your checkbox (example below):
<input id="my_checkbox1" type="checkbox" class="custom-control-input">
And then, add a javascript code (at html) that detect the checkbox change, and make an AJAX to your server.
<script>
$("#my_checkbox1").change(function() {
if(this.checked) {
$.post("{% url 'myapp:movieDataUpdate' pk=movie.pk %}", {},
function(data, status){
console.log("Data: " + data + "\nStatus: " + status);
});
}
# If you want, make an else
});
</script>
Some sources used here:
jQuery checkbox checked state changed event
https://www.w3schools.com/jquery/jquery_ajax_get_post.asp

python + flask passing data from html back to python script (specifically the value of a label)

I am using python and flask to make a web app. I am new to it, but have gotten most of what I am trying to accomplish done. Where I am stuck, is that I have a label whose value is a python variable( {{id}} ) This id is the id of a row I need to update in a sqlite database. My code is below. when I click the approve button, it takes me to a route which does the update query, but I have no way to pass the {{id}} with it. This would have been much easier if I could have just used javascript for the update query, but everything I've found using javascript, is for web sql, not sqlite, even though some of them say they are for sqlite.
</script>
<table border='1' align="center">
{% for post in posts %}
<tr>
<td>
<label>{{post.id}}</label>
<h1 id ='grill1'>{{post.photoName}}</h1>
<span>
<img id = 'photo1' src='{{post.photo}}' alt="Smiley face" height="200" width="200">
</span><br>
<h5 id ='blurb1'>
{{post.blurb}}
</h5>
<br>
<div style=" padding:10px; text-align:center;">
<input type="button" value="Approve" name="approve" onclick="window.location='/approve;">
<input type="button" value="Deny" onclick="window.location='/deny';"><br>
</div>
</td>
</tr>
{% endfor %}
</table>
Why not just do:
...
<input type="button" value="Approve" name="approve" onclick="window.location='/approve/{{post.id}};">
<input type="button" value="Deny" onclick="window.location='/deny/{{post.id}}';">
...
Then your flask route for approve and / or deny can just take a parameter for the post to approve or deny. i.e.:
#app.route("/approve/<int:post_id>")
def approve(post_id):
"""approve this post!"""

404 Not Found (The resource could not be found) - Trouble with GAE and Datastore

I am new to Python, GAE and the datastore model. So there are lots of things which I do not know yet, so please be patient :)
I am working on a web service that allows people to post 'name' and 'desc' (description) of an item and it will be included in a table on the same page. However when I clicked the submit button I got the error: 404 Not Found, The resource could not be found.
I am expecting a lot of things to be wrong in my code shown below (I only include short snippets of my code which I think is relevant to make it easier for reading), and my biggest problem is I have no idea which parts are wrong or which specific questions to ask. But I hope I can use this chance to learn more about everything that's involved in my code (Jinja, HTML, GQL etc), and how I can fit them all together.
class Events(ndb.Model):
name = ndb.StringProperty()
desc = ndb.StringProperty()
class Promote(webapp2.RequestHandler):
def get(self):
query = ndb.gql("SELECT * "
"FROM Events "
)
template_values = {"events" : query,}
template = jinja_environment.get_template('promote.htm')
self.response.out.write(template.render(template_values))
def post(self):
event = Events(name = self.request.get('name'), desc = self.request.get('desc'))
event.put()
self.redirect('/promote')
app = webapp2.WSGIApplication([('/', Main),
('/publicsearch', PublicSearch),
('/promote', Promote)],
debug=True)
This is my html code for that page.
<div class="jumbotron">
<div class = "container">
<form action="/promote" method="post">
<fieldset>
<div class="row-fluid">
<p> Promote your event here! </p>
<div class="row-fluid">
<div class="span6">
<p> Name of event: <br>
<textarea class="input-block-level" name="name" rows="1" cols = "50"> </textarea></p>
<p> Event description: <br>
<textarea class="input-block-level" name="desc" rows="3" cols = "50"> </textarea></p>
<p><input type="submit" value="Submit">
</div>
</div>
</div>
</div>
</div>
<h4> Events feed </h4>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th width="30%">Name</th>
<th>Description</th>
</tr>
</thead>
<tbody>
{% for event in events %}
<tr>
<td>{{ event.name }} </td>
<td>{{ event.desc }} </td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
Your form is trying to post to a handler with a url of /wishlist however the only handler for POST methods you have registered is for /promote.
These things need to match up. Either change the form or the handler mapping.
Also while you are at it check that your app.yaml makes sense. Have a look in the logs whilst you are at it, you will see what URL is being requested.

How can I pass parameters from one view to another

I can't get this to work: I navigate to the page I want, but I'm doing something wrong with the variables it seems.
views.py:
#view_config(http_cache=1,route_name='hoofdpagina', renderer='templates/hoofdpagina.pt')
def hoofdpagina(request):
page = DBSession.query(MyModel) #.filter_by(id='1').all()
if 'form.submitted' in request.params:
name= request.params['name']
page2=Page(name)
DBSession.add(page2)
return HTTPFound(location=request.route_url('view_page',pagename=name))
return dict(page=page)
#view_config(route_name='diagnose', renderer='templates/diagnose.pt')
def diagnose(request):
return request
kak = ['test1','test2','test3t']
content = {"test1","test2","test3"}
return {'content' :content, 'test' :kak}
hoofdpagina.pt:
<form class="span12" action="/diagnose" method="POST">
<table class="table table-hover">
<thead class="header">
<tr>
<th>D Nr.</th>
<th>Datum</th>
<th>Patient</th>
<th>Prior</th>
</tr>
</thead>
<tr tal:repeat="Page page" >
<td tal:content="Page.dosiernummer"></td>
<td tal:content="Page.dosiernummer"></td>
<td tal:content="Page.datum"></td>
<td tal:content="Page.naamPatient"></td>
<td tal:content="Page.prioriteit"></td>
</tr>
</table>
</form>
<form action="/diagnose" method="post">
<input type="submit" value="Save" name="form.submitted" ></input>
<label name="name">et werkt slet</label>
</form>
I can show all the variables of page in my table. But when I press the submit button I can't get the content of the "name" label to my diagnose page. I don't know how I can show the value.
ps: question is based on this post: Pyramid app: How can I pass values into my request.route_url?
Instead of you'd need an input of some sort:
<input type="text" name="name" value="et werkt slet">
or type="hidden" if you don't want it displayed.
I'm still learning Pyramid as well, but I also wonder if from your code that the submit action is going to post to def hoofdpagina anyway. I think you might have to move your POST handling to:
#view_config(route_name='diagnose', renderer='templates/diagnose.pt')
def diagnose(request):
if 'form.submitted' in request.params:
name= request.params['name']
page2=Page(name)
DBSession.add(page2)
return HTTPFound(location=request.route_url('view_page',pagename=name))
a sollution is working with url dispatching like this:
_init_.py:
config.add_route('diagnose1', '/diagnose1/{dosierid}')
views.py
#view_config(route_name='diagnose1', renderer='templates/diagnose.pt')
def diagnose1(request):
tabeldata=''
dosierid = request.matchdict['dosierid']
now you have your id from one view to another.
In the init.py you have to add url dispatching (config.add_route).
Your can get the data out of the url and pass on to another page like this.

Categories

Resources