Selecting all checkboxes in Django - python

I'm trying to find an elegant solution without recourse to using JQuery or JS. Is there anyway that one can perform a select all on fields that are options in a model?
I'm not so keen to use: django checkbox select all
I've seen it hinted at: https://groups.google.com/forum/#!topic/django-users/dzdiZ9TLR5g
But never been able to find anything that would easily allow me to provide a select all directly from Django. Does anyone know if this is possible to switch on? Or is JS the only way to perform this?
I note this answer earlier: select all rows in django_tables2
But is there a way to avoid this approach because I may not know what why fields are - hence, if I have more than one field on each page - i.e. multiple names.

Here is my easy solution with multiple Forms and multiple Fields :
{% for form in formset %}
<div>
{% for field in form %}
{{ field }}
{% for check in field|slice:":1" %}
<input type="checkbox" onClick="toggle(this,'{{ check.name }}')"/>
Select All
{% endfor %}
{% endfor %}
</div>
{% endfor %}
Each checkbox of one Field has the same name - so js can work with it.
Note that all the fields of this example form are checkboxes.
JS Code :
<script type="text/javascript" >
function toggle(source,name) {
checkboxes = document.getElementsByName(name);
for (var i = 0,
n = checkboxes.length; i < n; i++) {
checkboxes[i].checked = source.checked;
}
}
</script>
I extended this solution for django :
How to implement "select all" check box in HTML?

Any solution you write within Django would involve overriding widget renders to output html that included javascript/jquery anyway. I don't think there is any getting round it.
Edit: to answer your comment, the way I would personally do it is create a SlaveCheckboxWidget that could do something as simple inherit from the standard checkbox widget but change the css class name to "slave-checkbox" or similar, then have a MasterCheckboxWidget that includes a bit of jquery to select all (".slave-checkbox") and toggle them.
More on customising django widgets here

Related

How to append specific html to a Django code block using only Python/Django?

I have a form I'm working with in Django.
I have a built in error message I'm trying to get to render on the form.
My first step is to get the error message to render on the form and then I will go into the function and tweak when it shows up.
My problem emerges when it comes to doing it in python.
Normally, my preferred way would be to JQuery for the footer and use JavaScript to append/prepend the HTML. Then set it to show/hide based on conditionals.
However, for this I am wanting to do it in Python to make it easier for the people working w/ me.
Here's an example of the error message HTML I would like to use for appending to something else in JS.
error_field.append('<em for="name" class="form-error-message text-danger">');
Here is an example of the Django Code Block I would like to add it within
{% block form-footer %}
{{ block.super }}
{% endblock %}
What is the easiest way to accomplish this within Python/Django? To be clear, I can figure out the conditional stuff myself. Just the rendering of the specific HTML/CSS error class I have already created. I should be able to do the conditional/function part of this myself.
I can just show you an example, this is a part of my project
views.py
try:
user=User.objects.get(username=username)
except:
messages.info(request,'username does not exist')
return redirect('login')
return render(request,'users/login-register.html')
html
{% if messages %}
{% for i in messages %}
<div class="alert alert--{{i.tags}}">
<p class="alert__message">{{i}}</p>
<button class="alert__close">x</button>
</div>
{% endfor %}
{% endif %}
You can use this anywhere in your html page. This is a common page, and everything in here is extended. And of course this is an example similar to your problem. Check it out if you want

How do I display a different HTML attribute value in a Django template based on whether a mobile device is used?

I'm using Django and Python 3.7. I want to change the href in a template depending on whether a certain condition is satisfied (the user is viewing the page on a mobile device). If the user is using a regular device, the URL would be
{{ articlestat.article.path }}
Otherwise the path would be the above, except wiht the "www." replaced by "mobile.". What's the right way to do this? I have the below
{% if request.user_agent.is_mobile %}
<td align="center">Read Article</td>
{% else %}
<td align="center">Read Article</td>
{% endif %}
but it seems a little lengthy and I'm thinking there's a more concise way in Django to write all of the above.
I do not have a Django way of going about this at first glance but I do have a quick Javascript solution that you can have much more control over.
function redirect(btn, url) {
btn.on('click', function () {
window.location.href = url; // A string
})
}
var btn = <your btn>; // Use JQuery to get element as an ID
var url = <redirect url>;
redirect(btn, url);

Compare url in django

I am trying to hide a content when a user is visiting his own profile. I tried the code below but it didn't work. What could be wrong.
{% if request.path == "/account/users/{{ request.user.username }}/" %}
{% else %}
<img src="https://tyllplus.com/static/arrow-orange-down-vector-1.png" width="30" height="30">
{% endif %}
(Advanced) string processing should not be done in the template. Especially not with URLs, since you might later want to change the view. Even if you manage to get it work, if you later have a prefixed path, it can start failing. This method would also heavily depend on the format of the URL: if you later specify a URL where you use the id instead of the username, then you will need to look for all all URL processing that depends on this format. This is not elegant design.
Of course simple processing is no problem. For example adding comma separators to a number, etc. is typically handled by template tags. But URLs - in my opinion - do not really fit in that category.
You better encode this logic in the view (or make sure that you easily can detect it with elements from the view).
For example for a DetailView:
from django.views.generic.detail import DetailView
from django.contrib.auth.models import User
class UserDetailView(DetailView):
model = User
context_object_name = 'my_user'
template = 'user_detail.html'
We know that the my_user variable will carry the User object ot display, so then we can verify with:
{% if my_user != request.user %}
<!-- show something -->
{% else %}
<!-- show something else -->
{% endif %}

Creating a "Recent Posts" list in a sidebar.

I'm working on a simple blog app in Django, and i'm having trouble figuring out how to dynamically generate the five most recent posts in a side bar. Each of my views are class based and they extend a generic template, each view maps to one template which I believe is the correct way to do it. I've looked for a way to do this using template tags, but it seems Django doesn't like you to put any logic inside of your templates.
The problem I believe is that I want this to exist within my base.html because I want the recent posts to be displayed site-wide, is a view even supposed to map to your base.html or does that cause problems, i'm pretty new with this. I don't know how to approach this, whether i'm supposed to create a new view for base.html or if I should use my template tags, or if I should extend an existing view(but if I do that it won't be site wide?).
I essentially want the following(they're ordered in reverse chronological order)
{% for post in post_list[:4] %}
{{ post.title }}
{% endfor %}
You can use a template tag. More specifically, an inclusion tag is what you need. This allows you to insert a rendered snippet anywhere inside your template via a small view-like piece of code.
For example, create a templatetags/blog_tags.py file (it's important that you create the templatetags folder within your app; Django searches for them here by default) in your blog app and add the following:
from django import template
register = template.Library()
#register.inclusion_tag('blog/snippets/recent_posts.html')
def render_recent_blogposts():
return {
# This is just an example query, your actual models may vary
'post_list': BlogPost.objects.all().order_by("published_on")[:4]
}
now create a blog/snippets/recent_posts.html template (it can be anywhere as long as it mathecs the #register.inclusion_tag(...) above.):
<ul>
{% for post in post_list %}
<li> {{ post.title }}</li>
...
{% endfor %}
</ul>
finally, in your original template, you can now render your template tags:
<aside>
{% load blog_tags %}
{% render_recent_blogposts %}
</aside>

Does Django cache templates automatically?

I'm new to Django and trying to implement a voting system between two images. However, it looks like the page is being cached or something because when I refresh it, some values are wrong. I have no cache setup in my Settings.
Here is the View:
def rate(request, type):
photos = Photo.objects.order_by('?')[:2]
c = Context({"photos": photos, "type": type})
return render_to_response("base_rate.html", c)
and the template:
{% extends "base.html" %}
{% block body %}
<div class="photo">
<img src="{{photos.0.photo.url}}" alt="Photo" />
Vote
Flag
</div>
<div class="photo">
<img src="{{photos.1.photo.url}}" alt="Photo" />
Vote
Flag
</div>
{% endblock %}
Some pages will contain wrong info for the objects. Here is an example source that I am getting:
<div class="photo">
<img src="/img/rate/16photo1.jpg" alt="Photo" />
Vote
Flag
</div>
<div class="photo">
<img src="/img/rate/17photo2.jpg" alt="Photo" />
Vote
Flag
</div>
The second Vote href should be "/rate/vote/17/16" and the flag href should be "/rate/flag/17" but something is going wrong and I am getting inconsistent data.
Any ideas?
Taking a look at this in some of my code, I have this in my template:
{{ mytable.0.pk }}
{{ mytable.1.pk }}
{{ mytable.0.pk }}
{{ mytable.3.pk }}
And I get this output:
91596
54774
156800
23593
Odd, until you consider that django executes database queries very lazily. This is what shows up in my mysql log for one page load:
SELECT `mytable`.`id` FROM `mytable` ORDER BY RAND() LIMIT 1
SELECT `mytable`.`id` FROM `mytable` ORDER BY RAND() LIMIT 1 OFFSET 1
SELECT `mytable`.`id` FROM `mytable` ORDER BY RAND() LIMIT 1
SELECT `mytable`.`id` FROM `mytable` ORDER BY RAND() LIMIT 1 OFFSET 3
Each time you use the dot notation, it is executing an entire new query. I'd suggest modifying your code like so:
def rate(request, type):
photos = list(Photo.objects.order_by('?')[:2])
c = Context({"photos": photos, "type": type})
return render_to_response("base_rate.html", c)
Because the list() is forcing an evaluation, it will execute the query right then and there. In addition, the data for both of those items is already cached, so there is no reason to hit the database again. You should be good to go.
order_by('?') means that the list is ordered in random order, so {{ photos.0 }} will be different each time you load the page.
Also:
Vote
^^^ ^^^
Looks like that's probably not correct.
Django doesn't cache these sorts of things by default. Make sure that your browser/isp/etc. isn't caching it.
It looks like your database query isn't returning what you're expecting. Check that directly via your debugger or with print statement debugging if you have to.
That said, you really need to think long and hard about your app design. Using a GET request to make stateful changes to your app is an incredibly bad idea. Especially the way you are doing it. You need to change those links to POST requests to a single form. Otherwise, you'll find that random web spiders destroy your application.

Categories