Django Forms: Capture clicked value from template - python

I have a template which has a code like
<td>{{ contact.Tag_ID }}</td>
to list the Tag_ID of items in a table. Now when I click on ot it goes to as os page which is a form with the Tag_ID field. I some how want to catch the Tag_ID when I click on it and pass it to the view ans set it as the initial value. I know how to set the initial value but cannot figure how to catch the Tag_ID or its associated data.

A simple solution would be to pass the value in the url:
<td>{{ contact.Tag_ID }}</td>
or
<td>{{ contact.Tag_ID }}</td>
In the second case, it is just an old-style query string, which you can use javascript to read. But, the better (django) way would be to use the first method, and do a pretty url.
In urls.py:
(r'^os/(?P<tag_id>[a-zA-Z0-9]*)/*', 'os_view_handler'),
Then in views.py:
def os_view_handler(request, tag_id=None):
...

url code:
<a class="item" href="{% url "your_views_funct" contact.Tag_ID %}">{{ contact.Tag_ID }}</a>
and add this to your urls.py:
(r'^os/(?P<tag_id>[a-zA-Z0-9]*)/*', 'your_views_funct'),

Without knowing too much about your app, I'm guessing you want a URL like /os/<ID>/
First of all, you should declare this URL in your app's url.py. Second of all, use the {% url %} tag in the template. https://docs.djangoproject.com/en/dev/ref/templates/builtins/ And thirdly, your view should be able to accept this ID as a parameter and act accordingly.

Related

deleting objects without refresh django

I am trying to delete selected objects in django it works but when I select an item then click delete button it does not delete but after it when I refresh the page selected object is deleted. Here is
views.py
#login_required
def delete_contact(request):
if request.is_ajax():
selected_contacts = request.POST['contact_id']
selected_contacts = json.loads(selected_contacts)
for i, contact in enumerate(selected_contacts):
if contact != '':
ClientContact.objects.filter(author_id__in=selected_contacts).delete()
return redirect('contacts')
in templates
<table class="table table-hover contact-list">
<thead>
</thead>
{% for contact in contacts %}
<tbody>
<tr data-id="{{ contact.id }}" class="clickable-row"
data-href="{% url 'contact-detail' contact.id %}"
style="cursor: pointer; ">
<th scope="row"><input type="checkbox" id="check"></th>
<td>{{ contact.client_name }}</td>
<td>{{ contact.client_company_name }}</td>
<td>{{ contact.email }}</td>
<td>{{ contact.work_phone }}</td>
<td>{{ contact.work_phone }}</td>
</tr>
</tbody>
{% endfor %}
</table>
{% csrf_token %}
</div>
</div>
</div>
</div>
{% include 'users/footer.html' %}
<script type="text/javascript">
$(document).ready(function () {
$(".delete-btn").click(function () {
var selected_rows = [];
$('.contact-list').find('tr').each(function () {
var row = $(this);
if (row.find('input[type="checkbox"]').is(':checked')) {
console.log(row.attr('data-id'));
selected_rows.push(row.attr('data-id'));
}
});
var selected_rows = JSON.stringify(selected_rows);
$.ajax({
url: "{% url 'contact-delete' %}",
type: 'POST',
data: {
'contact_id': selected_rows,
'csrfmiddlewaretoken': $("[name=csrfmiddlewaretoken]").val()
},
});
});
});
</script>
it works fine but with refreshing the page. How can I delete selected objects
as soon as I click the delete button.
Any help please?
Thank you!
You are deleting the objects, what you are missing is that after sending the request to Django, if the request is successful you need to update the HTML accordingly.
The HTML of your page is rendered when you request the view. At this point the for loop in your template gets executed and iterates over all existing contacts
{% for contact in contacts %}
{% endfor %}
Afterwards, when the user clicks the delete button a request is sent through AJAX to Django which effectively deletes the selected objects yet the HTML code is not updated automagically.
When you refresh the page, the template code is executed once more by Django and thus the for loop is run again but this time the list of contacts has changed, that's why you see the changes in this case.
You can solve your issue in different ways:
1) Instead of calling a Django view via AJAX, make a proper HTML+Django form that is posted to a Django view that after processing the form redirects to the same view again. This would require no Javascript or AJAX. You can read more about forms here. In this way your template is re-rendered after every post and therefore you will see your table updated.
2) Probably the worst option, but also the easiest to implement at this point, would be to refresh your page via Javascript after the AJAX request returns successfully. For this you can bind a function to the success property of your $.ajax call that triggers a refresh, something like location.reload();. Note that this is not a good choice since you are making all the effort to call the delete view using AJAX but you are not getting any of its benefits, getting only the worst of both worlds.
3) The third option is to edit your HTML (your DOM actually) using javascript when the AJAX call returns successfully. If you choose to follow this path (which is your intention I presume) and do not know how to do it I suggest that you post another question regarding specifically how to change the rendered HTML via Javascript.
django actually call for every related model pre_delete and post_delete signals. So calling some function for every related models was found not inefficient.
And I think, that not calling delete() method leads to destroy the integrity of data.
For example: we have model myModel with FileField. In case, when we call delete() from some of myModel's object, this object and related file will be deleted.
If we call delete of related to myModel's object, this object will be deleted, but file will remain.

Accessing model data in Django template

I am using the below lines to pass data to my template index.html, model1 being the class in my models.py.
data = model1.objects.all()
return TemplateResponse(request, 'index.html', {'data': data})
I am able to access data on the front end by using a for loop as shown below
{% for x in data %}
<h3>{{x.name}}</h3>
<h4>{{x.department}}</h4>
{% endfor %}
Since there are mutliple objects in this data, my question is if I want to access only the department of particular object with certain name, how can I do that?
For example here I am using a for loop, consider there are two objects in the data. Then the output would be
name1
department1
name2
department2
So now if I need to access only name2 without any loop, how can i do that?
Updating the question: I am updating this question with html, so that the question looks clear.
table id="example" class="table table-striped" cellspacing="1" width="100%">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Department</th>
<th>View/Edit</th>
</tr>
</thead>
<tbody>
{% for x in data %}
<tr>
<td>{{x.id}}</td>
<td>{{x.name}}</td>
<td>{{x.department}}</td>
<td>View</td>
<button type="button" class="btn-sm btn-primary btn-lg" data-toggle="modal" data-target="#myModal">
view</button></td>
</tr>
{% endfor %}
</tbody>
This is how my html looks, I am using data-table here. So all the data is captured in a table automatically. As you can see every row has a view button that I would implement. Once the user clicks the view button, I should pop up a modal dialog to show all the other details like {{x.dateJoined}} etc which I don't show in the table. But if I use a separate view to pop this dialog, I should send a request to the view from my template saying which row(with some ID) the user has clicked. How can i achieve that? How can I bind the view button with respective rows here?
You need to write custom template tag which will take the queryset and filtering parameters and returns you appropriate object, you can use simple_tag:
myapp/templatetags/myapp_tags.py
from django import template
register = template.Library()
#register.simple_tag
def get_model1_object(queryset, **filters):
if not filters:
raise template.TemplateSyntaxError('`get_model1_object` tag requires filters.')
retrun queryset.filter(**filters).first()
Then in template:
{% load get_model1_object from myapp_tags %}
{% get_model1_object data name='blah' as obj %}
Note: Your filtering criteria might yield multiple results but in get_model1_object i am only returning the first object assuming your criteria will be strict, change it according to your needs.
The first thing to understand is that template rendering happens on the server, before the user sees anything in their browser. The template is not sent to the user, only the HTML that the template generated. When the user is interacting with the page, the original template is not involved. So, you have two choices here:
You can render the data for all the objects in hidden div's on your page, then use javascript with something like a jquery dialog to display them on demand. This is only realistic if you have very few records.
You can create a second view with its own template, which renders just the HTML for the modal dialog contents. You could then, again using javascript/jquery, make an AJAX request to load the contents of the dialog that you need when you need it. In your first view template, the list of departments, include the url of the object you want to fetch, eg:
{% for x in data %}
<tr>
<td>{{x.name}}</td>
<td><a class="deptlink" href="{% url 'dept_detail' x.pk %}">
{{ x.department }}</a></td>
</tr>
{% endfor %}
Where dept_detail is the name of the urls.py entry for your view that supplies the contents of the dialog.
Then in your javascript, hook the a tag so it opens your dialog instead of leaving the page:
$('.deptlink').click(function (event) {
event.preventDefault();
# then the code after this is up to you, but something that'll
# load the url into your dialog and open it.
$('yourdialog').load($(event.target).attr('href'));
Since you say you are an intermediate in javascript I won't get into the details of implementation, but basically, the moral of the story is that the output of django is going to be an HTML page. Anything that you need to have on the client side either has to be in that page, or you will have to make another request to the server to get it... Either way, you'll need some javascript to do this, since you want a modal dialog with client side interaction.

save dictionary to database from html template in flask

I will try my best to be as concise as possible.
In my back end, I have a list of dictionaries saved to a variable. Each dictionary represents a post from reddit and includes the score, url, and title.
Respectively, the template will loop through this list and then return the values of each of these keys to the user like so:
<table>
<tr>
{% for x in data[0:5] %}
<td>
{{ x['score'] }}
{{ x['title'] }}
<br>
<a href='/add_to_favorites'> Add To Favorites </a>
</td>
{% endfor %}
</tr>
</table>
As you can see, there's an tag which is linked to a function on my utils.py that is attempting to save the respective dictionary to the database (I have a model that represents the url, title, and score).
I feel as though my template is not representing the dictionary in the correct way, for my link to include the html as when it is pressed I receive a 404 error (though I have this route already defined in views.py - '/add_to_favorites' which calls my 'save_post' function).
def save_post():
data = get_info()
for post in data:
fav= Favorite(title=post.get('title'), url=post.get('url'), score=post.get('score'), user_id=current_user.id)
db.session.add(fav)
db.session.commit()
return redirect(url_for('favorites'))
and:
#app.route('/add_to_favorites')
#login_required
def add_to_favorites():
return save_post()
Am i going about this the wrong way? How can i make sure that the link/button is associated with only the html of the that it is included in?
Just need some guidance into the right direction here, not necessarily the code to fix it. Thank you

How to redirect a Django template and use the 'Next' variable?

I am using Django's built in login view as can be seen in the following snippets:
urls.py
url(r'^login$',login,{'template_name': 'login.html'},name="login"),
template.html
<form method="post" action="{% url 'login' %}">
{% csrf_token %}
<table>
<tr>
<td>{{ form.username.label_tag }}</td>
<td>{{ form.username }}</td>
</tr>
<tr>
<td>{{ form.password.label_tag }}</td>
<td>{{ form.password }}</td>
</tr>
</table>
<input type="submit" value="login" />
<input type="hidden" name="next" value="{{ next }}" />
</form>
How can I use the next variable to redirect to a URL different than the default /accounts/profile/ that django redirects to? I know of people referring to the settings.py file but I am wondering how I can utilize the next variable to do this?
(I'm not really sure of how the next variable works even after referring to documentation, an explanation of this would be much appreciated)
if you are using django login view ie,
from django.contrib.auth.views import login
you just need to pass the next url to the template. so when the request is sent to the login view , the code is in place to redirect to that url. is no next url is found
settings.LOGIN_REDIRECT_URL is used
you can simple pass the next url just like,
<form method="post" action="{% url 'login' %}?next={{next_url}}">
Pass the "next_url" value via context.
The next case, if you need the next url redirection for any of you custom views, simple write a code inside the view to get next url and after doing the job inside the view you can redirect to the next url.
from django.utils.http import is_safe_url
def your_view(request):
# do your codes
redirect_to = request.GET.get(next, '') # use get or Post as per your requirement
if is_safe_url(url=redirect_to, host=request.get_host()):
HttpResponseRedirect(redirect_to)
else:
# your response
To clear your doubt how the next variable works: In the above view we get a get a http request and if we have passed the next url as query params. we will be getting it in the view. "request.GET.get(next, '')" will get you the next url you sent from view. from view level you can do the functionalities you need and then if the next url is present and valid you can use HttpResponseRedirect to redirect to the next url.
For login ref: Django: Redirect to previous page after login

Proper way to consume data from RESTFUL API in django

I'm trying to learn django so while I have a current solution I'm not sure if it follows best practices in django. I would like to display information from a web api on my website. Let's say the api url is as follows:
http://api.example.com/books?author=edwards&year=2009
Thsis would return a list of books by Edwards written in the year 2009. Returned in the following format:
{'results':
[
{
'title':'Book 1',
'Author':'Edwards Man',
'Year':2009
},
{
'title':'Book 2',
'Author':'Edwards Man',
'Year':2009}
]
}
Currently I am consuming the API in my views file as follows:
class BooksPage(generic.TemplateView):
def get(self,request):
r = requests.get('http://api.example.com/books?author=edwards&year=2009')
books = r.json()
books_list = {'books':books['results']}
return render(request,'books.html',books_list)
Normally, we grab data from the database in the models.py file, but I am unsure if I should be grabbing this API data in models.py or views.py. If it should be in models.py, can someone provide an example of how to do this? I wrote the above example sepecifically for stackoverflow, so any bugs are purely a result of writing it here.
I like the approach of putting that kind of logic in a separate service layer (services.py); the data you are rendering is quite not a "model" in the Django ORM sense, and it's more than simple "view" logic. A clean encapsulation ensures you can do things like control the interface to the backing service (i.e., make it look like a Python API vs. URL with parameters), add enhancements such as caching, as #sobolevn mentioned, test the API in isolation, etc.
So I'd suggest a simple services.py, that looks something like this:
def get_books(year, author):
url = 'http://api.example.com/books'
params = {'year': year, 'author': author}
r = requests.get(url, params=params)
books = r.json()
books_list = {'books':books['results']}
return books_list
Note how the parameters get passed (using a capability of the requests package).
Then in views.py:
import services
class BooksPage(generic.TemplateView):
def get(self,request):
books_list = services.get_books('2009', 'edwards')
return render(request,'books.html',books_list)
See also:
Separation of business logic and data access in django
Use the serializer instead of .json, as it gives flexibility to return in a number of formats.As while using rest-api , the provided serializer use is preferred.
Also keep the data handling and get data requests in view.py.The forms are used for templating not as the business logic.
Well, there are several things to keep in mind. First of all, in this case your data is not changing so often. So it is a good practice to cache this kind of responces. There are a lot of caching tools around, but redis is a popular option. Alternatevly, you can choose additional NoSQL database just for caching.
Secondly, what is the purpose of displaying this data? Are you expecting your users to interact with books or authors, etc? If it is just an information, there is no need in forms and models. If not, you must provide proper views, forms and models for both books and authors, etc.
And considering the place where you should call an API request, I would say it dependes heavily on the second question. Choices are:
views.py for just displaying data.
forms.py or still views.py for ineractivity.
<tbody>
{% if libros %}
{% for libro in libros %}
<tr>
<td>{{ libro.id }}</td>
<td>{{ libro.titulo }}</td>
<td>{{ libro.autor }}</td>
<td>{{ libro.eiditorial }}</td>
<td>{{ libro.descripcion }}</td>
<td>{{ libro.cantidad }}</td>
<td>{{ libro.Bodega.nombre }}</td>
<td>
{% if libro.imagen %}
<td><img src= "{{ libro.imagen.url }} "align="center" width="50px" ></td>
{% else %}
<h6>no hay imagen de libros</h6>
{% endif %}
</td>
<td><a class ="btn btn-primary "href="/">Editar</a></td>
<td><a class ="btn btn-danger red"href="/">Eliminar</a></td>
</tr>
{% endfor %}
{% else %}
<h1>no hay registros de libros</h1>
{% endif%}
</tbody>
as I can call it in an html when I already have a list of my local application greetings

Categories

Resources