django admin list_filter too long - django

I have a list_filter with loads of sectors. This list, on the right side of the page, is too long.
Can I use an input select field instead since I can't choose more than one sector?
I have seen this before, screenshots, but I can not find the way to do this.
edit:
I have a custom FilterSpec not a list_filter

You can write your own custom FilterSpec (custom admin list filter).
This feature is not part of the Django code yet; it is planned for version 1.2. You'll need to apply this patch to the Django code: http://code.djangoproject.com/ticket/5833.
There are many examples on stackoverflow on how to do that, e.g: https://stackoverflow.com/a/1294952/342473.

http://lincolnloop.com/blog/2011/jan/11/custom-filters-django-admin/

The long list that you said comes from the default template 'admin/filter.html', in django/contrib/admin/templates/admin/filter.html, of builtin ListFilters.
There are several ways to customize it:
Globally override 'admin/filter.html'. Render select tag instead of ul tag if the count of choices hit certain limit. This affects all list filters in admin. The select tag should have onchange event handler like
<select ... onchange="location.href=this.options[this.selectedIndex].value">
Set template attribute in your specific ListFilter instance, to the name of the customized filter template. The content of the template is like #1. Django 1.4+ is required for this.
Add javascript in the ModelAdmin instance to convert HTML content inside the ul tag to select tag as soon as DOM has been fully loaded.

This is how i resolved it (jQuery):
$('#changelist-filter ul').each(function(){
var maxlength = 10;
if ($(this).children().length > maxlength )
{
var list=$(this),
select=$(document.createElement('select')).insertBefore($(this).hide());
$('>li a', this).each(function(){
console.log($(this).parent().attr('class'));
var target=$(this).attr('target'),
option=$(document.createElement('option'))
.appendTo(select)
.val(this.href)
.attr('selected', $(this).parent().attr('class'))
.html($(this).html())
.click(function(){
if (target==='_blank'){
window.open($(this).val());
}
else{
window.location.href=$(this).val();
}
});
});
list.remove();
}
});

Related

Use template tag (in HTML ) in view as a variable

I'm creating a web page on Django,
I want to create next and previous post in the bottom of blog page.
is there any way to use a simple tag like {{post.title}} in HTML and refer it to view page to find the index of current post ?
This is where you should use pagination. If you are using DRF you might need this pagination.

EmberJS - How to display subset of a model in a view

I am very new (started today) to Ember and cannot figure how how to set this up in a correct manner.
Models:
Post, Comment
On the 'show' template for Post, I want to display only the comments that are not blocked (isBlocked is a attribute of Comment model). Should I use a View and pass in a param to filter out the comments?
I cannot find an useful example or tutorial that explains this. Is there a way similar to how this would be done in Rails with partials and locals or something?
You can use a computed property that uses filterProperty to filter your model inside your controller. Then use that computed property to display in your template.
Assuming your Comment model has an isBlocked attribute, you can set up a computed property like,
comments: function() {
return this.filterProperty('isBlocked', false);
}.property('#each.isBlocked')
Then in the template use comments as the collection to iterate over. The comments collection will have all comments except those where isBlocked is true.

Setting selected entry using helper.options?

Im am using Play 2.0.4 and
helper.options(myitems)
in my template (inside of a helper.select)
In this case, how can I define the default selected entry, which shall be one entry out of myitems? Thanks for any hint!
A little bit more about my case:
Imagine a news archive, showing all news titles. This news archive uses pagination, pagination uses GET to pass the next/previous page number.
The play framework however will only correctly select the currently selected "select" item (here: news category) when a POST request was used - while pagination uses GET!
Intended behaviour: While a filter is applied / a specific news category is selected, this shall always be visible to the user by preselecting the currently selected news category in the "select" form.
A "screenshot" for illustration:
So, anyone having a good idea on how to cope with this problem? Any way to tell Play manually which entry from the "select" form it shall select? '_default always adds a new entry instead of selecting one out of the given options ): Would be great, if one wouldn't have to build the complete "select" form manually.
Try passing '_default option to select helper:
#import views.html.helper._
#select(form("email"), options(List("first", "third")), '_default -> "second")
It seems, unfortunately, the only way to figure it out is to look up the source.
Update:
Specifying _default property doesn't set selected attribute on option tag. It looks like the only way to preselect entry is to pass prefilled form to the template. For example, suppose you have following form:
case class RegInfo(email: String, color: String)
private val registrationForm = Form(
mapping(
"email" → email,
"color" → nonEmptyText(minLength = 5, maxLength = 32)
)(RegInfo.apply)(RegInfo.unapply)
)
Then in the action prefill form before passing to the view:
def create = Action {
Ok(html.create(registrationForm.fill(RegInfo("user#qwe.com", "blue"))))
}
Then in template use helper:
#select(form("color"), options(List("red", "green", "blue")))
And value will be preselected.
Ended up with the pragmatic approach:
<select id="myfield" name="myfield" >
<option class="blank" value="">-- All items --</option>
#for((key, value) <- MyModel.options) {
#if(key == GETValuePassedToTemplate) {
<option value="#key" selected>#value</option>
} else {
<option value="#key">#value</option>
}
}
</select>
Still wondering if there is a better option / way to do it.
Actually, there is a nicer solution to it. If you call the template having the form partially bound you will achieve your goal. Here's the code for your controller:
Ok(views.html.myForm(myForm.bind(
Map("fieldName1" -> "value1",
"fieldName2" -> "value2"))))
Make sure you map fieldnames to the values of the options you want pre-selected.
Still wondering if there is a better option / way to do it.
Well, if your not hell-bent on using play to solve this particular problem, you could always solve it using JavaScript and jQuery:
$(function () {
$('#yourSelect_id').val(5);
}
Where your select options each has values and the one option you whish to pre select has value 5.

Alternative form for Django's `ChoiceField` that can handle thousands of entries

I have a form with a ChoiceField in it. It is rendered to the user as a dropdown box.
Problem is, I have thousands of entries in this field, which is causing the page to (a) load very slowly and (b) be sluggish.
I want an alternative widget, instead of Select, that could handle more than 10,000 choices.
Something like the admin's raw_id_fields would be good (if only it were usable in general forms...) but I'm open to ideas.
If autocomplete is an option for your UI you can take a look to django-simple-autocomplete:
App enabling the use of jQuery UI autocomplete widget for
ModelChoiceFields with minimal configuration required.
EDITED (reply OP comment)
I have not tested this solution, but digging documentation and source it seems that not all data is loaded at a time:
The ability to specify an URL for the widget enables you to hook up to
other more advanced autocomplete query engines if you wish.
Source code:
def get_json(request, token):
"""Return matching results as JSON"""
...
di = {'%s__istartswith' % fieldname: searchtext} # <- look here!
items = queryset.filter(**di).order_by(fieldname)[:10]
Widget source code
$("#id_%(name)s_helper").autocomplete({
source: function(request, response){
$.ajax({ # <-- look here
url: "%(url)s",
data: {q: request.term},
success: function(data) {
I don't know what is the raw_id_fields but why not use a model to store all your choices ?
class Choice(models.Model):
value = models.CharField()
class MyModel(models.Model):
choice = models.ForeignKey(Choice)
It would then be easy to select it if you want to display only 20 at a time for example.
Based on this comment (which really, you should have included in your question):
Let me clarify my task: I have 10,000 users. I have a form in which
you choose a user. You need to be able to choose any user you want.
You can't just load 20, because then you won't be able to choose the
other 9,980 users.
If you want something built-in, you can use the FilteredSelectMultiple widget from django.contrib.admin.widgets, which puts a filter on your select.
You should also cache the results of the 10,000 users so you don't hit your db everytime. This is what is causing your delay, not the number of users (which is tiny, for practical performance problems).

Django admin, hide +Plus sign to specific foreignkey field

i want to hide the plus + sign in some foreignkey fields of a specific model in django-admin interface. it's possible?
Thanks in advance!
The + is added when that foreign key's model can also be added in the admin, and is based on the permissions the user has on that model. If the user shouldn't be able to add those types of models, override has_add_permission on the foreign key's ModelAdmin (i.e. the one the plus sign would allow you to add), and return False for the appropriate conditions. The + will go away for any user not allowed.
If you just want to hide it for cosmetic purpose, I'd use a Javascript script that hides this '+' sign.
You can add custom Javascript sources to Admin Modelform's by using the Media inner class, as described in the docs. Something like this:
class MyModelAdmin(admin.ModelAdmin):
class Media:
js = ("js/hide_myfield_addlink.js",)
The Javascript source would look something like:
/* file: hide_myfield_addlink.js */
django.jQuery(document).ready(function() {
django.jQuery("#add_id_myfield").hide();
});
On the other hand, if those admin users should never be able to add such a model, don't give them the permission to add those. Then these add links will never be displayed.
Might as well do it in CSS:
.field-myfield .related-widget-wrapper-link {
display: none;
}
Or to disable it everywhere:
.related-widget-wrapper-link {
display: none;
}