I have a custom filter in django admin interface
class ClipExcludeRightsFilter(ListFilter):
title = 'rights'
parameter_name = 'exclude_rights'
template = 'admin_mod/filters/exclude_rights.html'
def lookups(self, request, model_admin):
result = (
('avod', 'avod'),
('svod', 'svod'),
('est', 'est'),
('tvod', 'tvod')
)
return result
def queryset(self, request, queryset):
if self.value():
urls_owner = ClipRestriction.objects.exclude(vod_system=self.value()).values_list('clip_id', flat=True)
return queryset.filter(
pk__in=urls_owner
)
And in interface it returns list (select) and I can select just one attribute. But I need to implement multiple select. I found, that default template for this is template/admin/filter.html
{% load i18n %}
<h3>{% blocktrans with filter_title=title|capfirst %} By {{ filter_title }} {% endblocktrans %}</h3>
<select class="combobox">
{% for choice in choices %}
<option{% if choice.selected %} selected{% endif %} value="{{ choice.query_string|iriencode }}" >{{ choice.display }}</option>
{% endfor %}
</select>
Maybe I need to write my own template but no idea how to (I need to filter selected options instantly).
I just selected all option:selected using jquery and then pass it as a parameter in my url.
Related
I am struggling with something that should be routine for me by now but I have a mental block.
I have a model that stores Country names and a slug version of the name.
Eg. "United States", "united-states"
I want to display the country names in a template for selection, then return the selected country's slug value to the Class based View which will then obtain the data. The list of countries can be links or dropdown - whatever. But I need to obtain the selected value in the View. Here is a simplified version:
Template
{% extends 'base.html' %}
{% block content %}
<form method="POST">
{% for country in object_list %}
{{ country.pretty_name }}</br>
{% endfor %}
</form>
{% endblock content %}
View
class CountryView(TemplateView):
country_name = THE SLUG
country_obj = Country(country_name)
country_obj.build_country_dictionary()
country_obj.display()
So I think I need one of the get methods to access this but I cannot work it out. Thanks for any help.
The "structured way"
Have a look at FormView, where you define your form class (which you also need to create, depends on your situation can be a model form as well). The rest is pretty much handled by the view.
https://ccbv.co.uk/projects/Django/4.0/django.views.generic.edit/FormView/
PSEUDO code
class MyForm(ModelForm):
model = YourModel
class MyFormView(FormView):
form_class = MyForm
# depends on what you want to do, you can overwrite form_valid to do your logic
The quickest way
PSEUDO code
{% extends 'base.html' %}
{% block content %}
<form method="POST">
{% csrf_token %}
<select name="selection">
{% for country in object_list %}
<option value="{{ country.slug_name }}">{{ country.pretty_name }}</option>
{% endfor %}
</select>
<input type="submit">Submit</input>
</form>
{% endblock content %}
class CountryView(TemplateView):
def post(self, request, *args, **kwargs):
selection = request.POST.get('selection')
I am trying to set the initial choices in a dropdown, on profile edit for selecting Business type. But I want the dropdown to already have the current instance' selections already chosen. But I just cant figure out how to render this on the frontend. I heard of a select option that jinja template offers, to do this?
I will take a code snippet from my app,
def edit_profile(request):
request_user = request.user
# FOR SENDING USER TO SERVER
if request.method == 'POST':
template_name = 'business/profile_view.html'
first_name = request.POST['first_name']
business = request.POST.getlist('business_type', '')
if business == '':
pass
try:
user_obj = Account.objects.get(email=request.user)
""" Loop over business types and assign to user """
user_obj.business.clear()
for _business in business:
user_obj.business.add(_business)
return redirect('/auth/edit_profile/')
except Exception as e:
message = {"message": "Profile edit ERROR"}
return render(request, template_name, message)
# FOR SERVER TO USER
if request.method == 'GET':
template_name = 'business/profile_view.html'
context = dict()
user_obj = Account.objects.get(email=request.user)
context['business_type'] = user_obj.business
if request.path == '/auth/edit_profile/':
return render(request, template_name, context)
elif request.path == '/auth/edit_profile_edit/':
return render(request, 'business/profile_edit.html', context)
And my Template
<select class="selectpicker" name="business_type" multiple="multiple"title="Select a category">
{% for business in business_types %}
<option value="{{ business.id }}">{{ business.name }}</option>
{% endfor %}
</select>
You can add "selected" to your views context:
context['selected'] = business # or however you are identifying the selected
then in the html you can add the selected tag with an ifequal statement:
{% for business in business_types %}
<option {% if ifequal business.name selected.name %}selected{% endif %}
value="{{ business.id }}">{{ business.name }} </option>
{% endfor %}
or if the context is a list, then you can use {% if business in selected_businesses %}
{% for business in business_types %}
<option {% if business in selected_businesses %}selected{% endif %}
value="{{ business.id }}">{{ business.name }} </option>
{% endfor %}
I'd recommend looking into Django's forms system. It does a lot of the work of setting up forms, rendering widgets, and even validating your data for you. You can also send forms with the current instance already filled in
I created a model and one of the fields has choices. I created a select form in my template and the choices are not been displayed. I'm not using Forms or ModelForms for a few reasons. But my understanding is that I should be able to make this work using CHOICES in the model, building a form in the template and save the information using the object manager. How can I get the choices to populate the form?
Models.py
class NewRating(models.Model):
EXCELLENT = 'EX'
GOOD = 'GD'
FAIR = 'FR'
BAD = 'BD'
RATING_CHOICES = (
(EXCELLENT, 'Excellent'),
(GOOD, 'Good'),
(FAIR, 'Fair'),
(BAD, 'Bad')
)
function = models.ForeignKey(Function, related_name='frating')
timeline = models.ForeignKey(Timeline, related_name='trating')
rating = models.CharField(max_length=25,choices=RATING_CHOICES)
Views.py
def f_page(request, Function_id):
assignments = Function.objects.get(id=Function_id)
time = Timeline.objects.all()
ratings = NewRating.objects.all()
context = {
'assignments': assignments,
'time' : time,
'ratings' : ratings,
}
return render (request, 'project/pager.html', context)
HTML
<div id=for_rat>
{% for rated in time %}
<form action= "/project/rated" method='POST'>
{% csrf_token %}
{{rated.segment}}
<input type="hidden" name="year" value="{{rated.year}}">
<input type="hidden" name="month" value= "{{assignments.id}}">
<select name="ratings">
<option value="">Choose From List</option>
{% for rating in ratings %}
<option value="{{rating.choices}}">{{rating.choices}}</option>
{% endfor %}
</select>
{% endfor %}
<input type="submit" value="Save">
</form>
</div>
Using {% for rating in ratings %}
{{rating.choices}}
{% endfor %} is not working. Can I set the choices in the models if I'm building my own forms? If yes, what am I doing wrong that this is not rendering?
Easiest, simplest and the 100% working method is:
Get the objects [lets say 'my_Model_with_choices'] with my_Model_with_choices = yourModel.objects.first() and you can get the choices with my_Model_with_choices._meta.get_field('your_foreign_key_variable_name').choices
def f_page(request, Function_id):
assignments = Function.objects.get(id=Function_id)
ratings = NewRating.RATING_CHOICES
context = {
'ratings' : ratings,
}
return render (request, 'project/pager.html', context)
Inside HTML template:
<select class="custom-select col-md-5" name="ratings" id="ratings" required>
<option disabled selected value="">Ethnic Group</option>
{% for value, ratings_group in ratings %}
<option value='{{value}}'>{{ratings_group}}</option>
{% endfor %}
</select>
If you're strictly not willing to use Form or ModelForm, you need to have choices to be iterable which is possible via enum.
You can check my sample code about how to implement choices with enums here.
You'll have to make some tweaks to your context and template after doing this.
You might want to look how to get the list of choices with enum.
try this
{% for rating in ratings %}
<select name="ratings">
<option value="">Choose From List</option>
{% for x, y in rating._meta.get_field('rating').choices %}
<option value="{{ x }}">{% if rating.rating == x %} selected{% endif %}>
{{ y }}
</option>
{% endfor %}
</select>
{% endfor %}
Make sure that this code is outside the
{% for rated in time %}
...
{% endfor %}
block
I use Django Endless Paginator plugin.
I try to change the value of ENDLESS_PAGINATION_PER_PAGE from template side.
As default is 10.
I want to realize some dropbox where the user can change between (Example: 10,20,50,100 Objects).
Thanks for answer, but something not work property.
1. I have view.py
def adv_search(request):
objects = None
if request.GET.get('key'):
form = AdvancedSearchForm(request.GET)
if form.is_valid():
repo = Repository()
objects = list(repo.find_objects('*'+form.cleaned_data['key'] +'*', type=FileObject, chunksize=20))
return render(request, 'templates/adv_search.html', {'form': form, 'objects': objects })
return render(request, 'templates/adv_search.html', {'form': AdvancedSearchForm(), 'objects': objects})
2. Then forms.py
class AdvancedSearchForm(forms.Form):
key = forms.CharField(max_length=500, label="", widget= forms.TextInput(attrs={'class': 'label'}))
show_props = forms.MultipleChoiceField(choices = (("pid", "pid"),("title", "title"),("type","type"),("source","source"),("date","date"),("publisher","publisher"),("subject","subject"),("label","label"),("cDate","cDate"),("mDate","mDate")),required=False, widget=forms.CheckboxSelectMultiple(attrs={'class': 'my-class'}))
paginator = forms.ChoiceField(choices =(('10', '10'),('20','20'), ('50','50'), ('100','100')) ,required=False, )
3. adv_search.html
{% paginate paginator objects %}
{% for obj in objects %}
...
<div class="paginator">
{% get_pages %}
{{ pages.first_as_arrow }}
{% show_pages %}
{{ pages.last_as_arrow }}
<form method="get">
{{ form.paginator }}
<input type="submit" Value="Go">
</form>
{{ pages.total_count }} total objects
</div>
Everything works except select
Thanks Andrey
You can have a form which will set pagination per page and then use that submitted value in template. Here is an example:
View
from django.shortcuts import render
from .models import Entry
def endless_view(request):
pagination_per_page = request.GET.get('per_page', 10)
entries = Entry.objects.all()
return render(request, 'some_template.html', {'pagination_per_page':
pagination_per_page, 'entries': entries})
Template
{% extends 'base.html' %}
{% load endless %}
{% block content %}
{# #}
<form action="" method="get">
<select name="per_page">
<option value="10">10 per page</option>
<option value="20">20 per page</option>
<option value="50">50 per page</option>
<option value="100">100 per page</option>
</select>
<input type="submit" Value="Go">
</form>
{% paginate pagination_per_page entries %}
{% for entry in entries %}
{# your code to show the entry #}
{% endfor %}
{% show_pages %}
{% endblock content %}
Reference
http://django-endless-pagination.readthedocs.org/en/latest/templatetags_reference.html
I have a model called Subtopic. One of my templates runs a forloop on an object, returning a different field for each cell of a table row.
Two of the table cells look up a field which is a ManytoMany foreign key, both to the same foreign model, Resource. I want each to display different results, based on the value of a boolean field within the Resource model.
What you see below is currently working fine, but doesn't attempt to filter by the boolean field.
models.py:
class ICTResourceManager(models.Manager):
def get_query_set(self):
return super(ICTResourceManager, self).get_query_set().filter('is_ict': True)
class NonICTResourceManager(models.Manager):
def get_query_set(self):
return super(NonICTResourceManager, self).get_query_set().filter('is_ict': False)
class Resource(models.Model):
subtopics = models.ManyToManyField(Subtopic)
external_site = models.ForeignKey(ExternalSite)
link_address = models.URLField(max_length=200, unique=True, verify_exists=False)
requires_login = models.BooleanField()
is_ict = models.BooleanField()
flags = models.ManyToManyField(Flag, blank=True)
comment = models.TextField()
def __unicode__(self):
return u'%s %s' % (self.external_site, self.link_address)
objects = models.Manager()
ict_objects = ICTResourceManager()
nonict_objects = NonICTResourceManager()
class Meta:
ordering = ['external_site', 'link_address']
views.py:
def view_ks5topic(request, modulecode, topicshortname):
listofsubtopics = Subtopic.objects.filter(topic__module__code__iexact = modulecode, topic__shortname__iexact = topicshortname)
themodule = Module.objects.get(code__iexact = modulecode)
thetopic = Topic.objects.get(module__code__iexact = modulecode, shortname__iexact = topicshortname)
return render_to_response('topic_page.html', locals())
My template:
{% for whatever in listofsubtopics %}
<tr>
<td>
{{ whatever.objective_html|safe }}
<p>
{% if request.user.is_authenticated %}
{% with 'objective' as column %}
{% include "edit_text.html" %}
{% endwith %}
{% else %}
{% endif %}
</td>
<td>
{% regroup whatever.resource_set.all by external_site.name as resource_list %}
{% for external_site in resource_list %}
<h4>{{ external_site.grouper }}</h4>
<ul>
{% for item in external_site.list %}
<li>{{ item.comment }}</li>
{% endfor %}
</ul>
{% endfor %}
</td>
</tr>
{% endfor %}
As you can see, I've added extra managers to the model to do the filtering for me, but when I replace the appropriate lines in the template, I just get blanks. I have tried: for external_site.ict_objects in resource_list and for item.ict_objects in resource_list and <a href="{{ item.ict_objects.link_address }}">. If this were in the view I could probably do the filter just by .filter('is_ict': True), but with this being inside a forloop I don't know where to do the filtering.
I also tried writing regroup whatever.resource_set.filter('is_ict': True) in the template, but the syntax for regrouping seems to use resource_set.all rather than resource_set.all() (and I don't know why) so the filter text doesn't work here.
Turns out it was possible to do it using a custom template filter. The original efforts to filter within the template weren't working, given that as is well documented the template language is not a fully-fledged python environment. My original question remains open for anyone who knows an alternative method that more directly addresses the question I was originally asking, but here's how I did it:
myapp_extras.py:
from django import template
register = template.Library()
def ict(value, arg):
"filters on whether the is_ict Boolean is true"
return value.filter(is_ict=arg)
register.filter('ict', ict)
My template, note the use of the custom filter in line 2:
<td>
{% regroup whatever.resource_set.all|ict:1 by external_site.name as resource_list %}
{% for external_site in resource_list %}
<h4>{{ external_site.grouper }}</h4>
<ul>
{% for item in external_site.list %}
<li>{{ item.comment }}</li>
{% endfor %}
</ul>
{% endfor %}
</td>
After this I was able to remove the additional custom managers from the model.
One further question, when filtering for the boolean is_ict field, I found that I had to use filter(is_ict=1) and filter(is_ict=0). Is that the only way to refer to a True or False value?