{% empty %} does not work in django template - django

if works correctly but empty does not work, here is my code:
{% for answer in ans|slice:":3" %}
{% for course in crs %}
{% if answer.course_id == course.id %}
<h4 class="w3-text-blue">{{answer.course}}</h4>
{% endif %}
{% empty %}
<h1>empty</h1>
{% endfor %}
{% endfor %}
and this is my views:
class CourseListView(ListView, LoginRequiredMixin):
model = Course
template_name = 'course_list.html'
def get_context_data(self, **kwargs):
context_data = super(CourseListView, self).get_context_data(**kwargs)
context_data['crs'] = Course.objects.raw('SELECT * FROM ertaapp_course where prof_id=%s',[self.request.user.id])
context_data['ans'] = Answer.objects.raw('SELECT * FROM ertaapp_answer')
return context_data

Why you want to do that, just use {% if %} and {% else %}:
views.py
def get_context_data(self, **kwargs):
context_data = super(CourseListView, self).get_context_data(**kwargs)
context_data['crs'] = Course.objects.raw('SELECT * FROM ertaapp_course where prof_id=%s',[self.request.user.id])
ans = Answer.objects.all()
context_data['ans'] = ans
context['ans_count']=ans.count()
return context_data
Now, in html template
{% if ans_count > 0 %}
{% for answer in ans|slice:":3" %}
{% for course in crs %}
{% if answer.course_id == course.id %}
<h4 class="w3-text-blue">{{answer.course}}</h4>
{% endif %}
{% endfor %}
{% endfor %}
{% else %}
<h1>empty</h1>
{% endif %}

Related

In which variable is the model instance stored in customized view?

How can I actually pick up values from my model in a customised template?
Let's assume for this example, the model for Request has an attribute "title".
Following views.py:
class RequestModelView(ModelView):
datamodel = SQLAInterface(Request)
extra_args = {'my_extra_arg':Request}
show_template = 'show_request.html'
list_columns = ['title','description','request_status']
and here the show_requests.html
{% extends "appbuilder/general/model/show.html" %}
{% block show_form %}
This Text is before the show widget
{{ super() }}
This Text is shown below..
<hr>
{{ (self.title) }}; {{pk}}; {{pk['title']}}
{% endblock %}
In which variable can I find my object?
The only parameter that works is {{pk}} (it shows the ID of the Request).
I was thinking of something like item['title']
Thanks.
A very similar question was asked on their Github. I think you would have to use something along these lines:
views.py
class RequestModelView(ModelView):
datamodel = SQLAInterface(Request)
list_columns = ['title','description','request_status']
add_template = 'show_request.html'
#expose('/show_request', methods=['GET', 'POST'])
#has_access
def show_request(self):
get_filter_args(self._filters)
self.extra_args = {'item': list_columns}
return super(RequestModelView, self).add()
show_requests.html:
{% extends "appbuilder/general/model/show.html" %}
{% block show_form %}
This Text is before the show widget
{{ super() }}
This Text is shown below..
<hr>
{{ item['title'] }}
{% endblock %}
Documentation is certainly not very clear in this aspect, but please check template-extra-arguments
I'm not sure if you would still need extra_args = {'my_extra_arg':Request}.
The following example should make things clear:
from .models import cars
beautiful_names = ["John", "Jane", "Bob"]
flowers = ["Aster", "Buttercup", "Roses"]
class IndexView(View):
template_name = "dashboard/dashboard_index.html"
def get(self, request, *args, **kwargs):
all_car_objects=cars.objects.all()
return render(request,
self.template_name,
context={"my_addresslist": beautiful_names,
"my_rose_list": roses},
"all_cars":all_car_objects)
In your template you can then do something like:
<h1>Beautiful Names</h1>
{% for name in my_addresslist %}
<p>{{ name }}</p>
{% endfor %}
<h1>Roses</>
{% if my_rose_list %}
{% for rose in my_rose_list %}
<p>{{ rose }}</p>
{% endfor %}
{% endif %}
<h1>Cars</>
{% if all_cars %}
{% for car in all_cars %}
<div>
<p>{{ car.name }}</p>
<p>{{ car.make }}</p>
<p>{{ car.model }}</p>
</div
{% endfor %}
{% endif %}
So for your example, it comes down to this:
class MyView(ModelView):
datamodel = SQLAInterface(MyTable)
extra_args = {'my_request_list':Request}
show_template = 'show_request.html'
<h1>Requests</>
{% if my_request_list %}
{% for request in my_request_list %}
<p>{{ request }}</p>
{% endfor %}
{% endif %}

Why this django formset has stopped saving the content all of a sudden?

I had this view that rendered a form and a formset in the same template:
class LearnerUpdateView(LearnerProfileMixin, UpdateView):
model = User
form_class = UserForm
formset_class = LearnerFormSet
template_name = "formset_edit_learner.html"
success_url = reverse_lazy('pages:home')
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
learner = User.objects.get(learner=self.request.user.learner)
formset = LearnerFormSet(instance=learner)
context["learner_formset"] = formset
return context
def get_object(self, queryset=None):
user = self.request.user
return user
def post(self, request, *args, **kwargs):
self.object = self.get_object()
form_class = self.get_form_class()
form = self.get_form(form_class)
user = User.objects.get(learner=self.get_object().learner)
formsets = LearnerFormSet(self.request.POST, request.FILES, instance=user)
if form.is_valid():
for fs in formsets:
if fs.is_valid():
# Messages test start
messages.success(request, "Profile updated successfully!")
# Messages test end
fs.save()
else:
messages.error(request, "It didn't save!")
return self.form_valid(form)
return self.form_invalid(form)
Then i wanted to make it prettier and i added the select2 multicheckbox widget and the django-bootstrap-datepicker-plus
Nothing has changed elsewhere, yet when i submit the post it only saves the data relative to User and not to Learner (which relies on the formset)
According to the messages, the formset data is not validated, I don't understand why since i didn't touch the substance at all but just the appearance.
Being a beginner im probably missing something big, I thank in advance whoever can help me find out the problem.
Here below the forms and the template:
(users.forms)
class LearnerForm(forms.ModelForm):
class Meta:
model = Learner
fields = ['locations', 'organization', 'supervisor', 'intro']
class UserForm(forms.ModelForm):
class Meta:
model = User
fields = ['username', 'first_name', 'last_name', 'birthday', 'email', 'profile_pic']
widgets = {
'birthday': DatePickerInput(format='%Y-%m-%d'), }
LearnerFormSet = inlineformset_factory(User, Learner, form=LearnerForm)
template
{% extends '_base.html' %}
{% load crispy_forms_tags %}
{% block content %}
<form action="" method="POST" enctype="multipart/form-data">
{% csrf_token %}
{{ form|crispy }}
{{ learner_formset.management_form}}
{% for form in learner_formset %}
{% if forloop.first %}
{% for field in form.visible_fields %}
{% if field.name != 'DELETE' %}
<label for="id_{{ field.name }}">{{ field.label|capfirst }}</label>
<div id='id_{{ field.name }}' class="form-group">
{{ field.errors.as_ul }}
{{ field }}
</div>
{% endif %}
{% endfor %}
{% endif %}
{% endfor %}
<input class="btn btn-success" type="submit" value="Update"/>
</form>
{% endblock content %}
I figured it out by combing the previous commits. The problem was in the template, the formset wasn't getting validated because i had ignored the hidden fields, which i hear are a common problem when dealing with formsets.
So the correct code is as such:
{% extends '_base.html' %}
{% load crispy_forms_tags %}
{% block content %}
<form action="" method="POST" enctype="multipart/form-data">
{% csrf_token %}
{{ form|crispy }}
{{ learner_formset.management_form}}
{% for form in learner_formset %}
{% if forloop.first %}
{% comment %} This makes it so that it doesnt show the annoying DELETE checkbox {% endcomment %}
{% for field in form.visible_fields %}
{% if field.name != 'DELETE' %}
<label for="{{ field.name }}">{{ field.label|capfirst }}</label>
<div id="{{ field.name }}" class="form-group">
{{ field }}
{{ field.errors.as_ul }}
</div>
{% endif %}
{% endfor %}
{% endif %}
{% for field in form.visible_fields %}
{% if field.name == 'DELETE' %}
{{ field.as_hidden }}
{% else %}
{# Include the hidden fields in the form #}
{% if forloop.first %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% endif %}
{% endif %}
{% endfor %}
{% endfor %}
<input class="btn btn-success" type="submit" value="Update"/>
</form>
{% endblock content %}

I want to display User videos and Other's videos separately. I am not getting output from the following code, Is my approach correct?

My view goes something like this
class Test(ListView):
model = VideoUpload
template_name = 'videoTube/videoTube.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["my_video_list"] = VideoUpload.objects.filter(user=self.request.user)
context["other_video_list"] = VideoUpload.objects.exclude(user=self.request.user)
print(context)
return context
Template code
{% for vid in my_video_list %}
{% if forloop.counter < 5 %}
{{ vid.video }}
{% endif %}
{% endfor %}
{% for vid in other_video_list %}
{% if forloop.counter < 5 %}
{{ vid.video }}
{% endif %}
{% endfor %}
I am not getting anything in the output. I am expecting my_video_list and other_video_list should be displayed separately

How can I display a Django admin inline model within a fieldset?

Consider the following ModelAdmin. In this instance, I'd like to have the inline "Book" UI display between the "None" fieldset and the Notes fieldset. Is that possible?
class AuthorAdmin(admin.ModelAdmin):
inlines = [BookInline]
fieldsets = (
(None, {
'fields': ('author_name', 'date_of_birth')
}),
('Notes', {
'fields': (['notes'])
}),
)
Bertrand Bortage posted another solution here: https://groups.google.com/forum/#!topic/django-users/yUq2Nvx_4eM
A late reply to say that I just pushed a fairly clean solution to this
problem in one of my projects:
https://github.com/dezede/dezede/commit/ed13ccaf34494e71fd913fd785c229052f6acdc8.
The idea is to define fieldsets_and_inlines_order in your
ModelAdmin(s), an iterable of 'f' and 'i' characters (for "fieldset"
and "inline") that specifies the order between the first fieldsets and
inlines. If len(fieldsets_and_inlines_order) < len(fieldsets) +
len(inlines), the remaining follows the original behaviour (fieldsets
first, then all inlines).
Example: you have 5 fieldsets and 3 inlines, defining
fieldsets_and_inlines_order = ('f', 'f', 'i', 'f', 'i') will give you:
fieldset fieldset inline fieldset inline fieldset fieldset inline Hope
it helps, Bertrand
I had another idea which is worth considering. Create a readonly placeholder field in your fieldsets for each inline then use jQuery to move the inlines into place for each placeholder. Something like this (jQuery omitted as I haven't written it yet):
fieldsets = (
(None, {
'fields': (
('inline_images',)
('thumbnail_image',),
('inline_authors',)
('title', 'is_active', 'order',)
),
}),
)
readonly_fields = ('inline_images', 'inline_authors')
inline_images = '<span class="replaceme inline_images"></span>'
inline_images.allow_tags = True
inline_authors = '<span class="replaceme inline_authors"></span>'
inline_authors.allow_tags = True
One more thing - there is an open Django issue asking for this positioning of inlines: https://code.djangoproject.com/ticket/4848
Unfortunately this is not possible with (the standard template from) django. If you look at the template for the change_form, you can see that inlines are always rendered separately after the fieldset:
https://github.com/django/django/blob/master/django/contrib/admin/templates/admin/change_form.html
The only work-around I see is to write a custom template with respect to the order you want.
I have constructed another quite generic solution...
In your admin.py add a new field to your Inline:
class YourModelInline(admin.TabularInline):
model = YourModel
after_field = "fieldname_of_field_before_inline"
Then customize render_change_form of AdminClass of the model that holds the Inline:
class EditModelAdmin(model.ModelAdmin):
inlines = [YourModelInline,]
def render_change_form(self, request, context, add=False, change=False, form_url='', obj=None):
sorted_inline_formsets = {}
inline_admin_formsets = context['inline_admin_formsets']
formsets_to_remove = []
for inline_formset in inline_admin_formsets:
if hasattr(inline_formset.opts, 'after_field'):
fieldname = inline_formset.opts.after_field
if fieldname in sorted_inline_formsets:
sorted_inline_formsets[fieldname].append(inline_formset)
else:
sorted_inline_formsets.update({
fieldname: [inline_formset,]
})
formsets_to_remove.append(inline_formset)
for inline_formset in formsets_to_remove:
inline_admin_formsets.remove(inline_formset)
context.update({
'sorted_inline_formsets': sorted_inline_formsets,
'inline_admin_formsets': inline_admin_formsets
})
return super(EditModelAdmin, self).render_change_form(request, context, add=add,
change=change, obj=obj, form_url=form_url)
We are moving all Inlines with extra field into own dictionary with fieldname as key...
For it to be rendered correctly create file /templates/admin/includes/fieldset.html that overrides standard django fieldset.html with following content:
{% load custom_filter %}
<fieldset class="module aligned {{ fieldset.classes }}">
{% if fieldset.name %}<h2>{{ fieldset.name }}</h2>{% endif %}
{% if fieldset.description %}
<div class="description">{{ fieldset.description|safe }}</div>
{% endif %}
{% for line in fieldset %}
<div class="form-row{% if line.fields|length_is:'1' and line.errors %} errors{% endif %}{% if not line.has_visible_field %} hidden{% endif %}{% for field in line %}{% if field.field.name %} field-{{ field.field.name }}{% endif %}{% endfor %}">
{% if line.fields|length_is:'1' %}{{ line.errors }}{% endif %}
{% for field in line %}
<div{% if not line.fields|length_is:'1' %} class="field-box{% if field.field.name %} field-{{ field.field.name }}{% endif %}{% if not field.is_readonly and field.errors %} errors{% endif %}{% if field.field.is_hidden %} hidden{% endif %}"{% elif field.is_checkbox %} class="checkbox-row"{% endif %}>
{% if not line.fields|length_is:'1' and not field.is_readonly %}{{ field.errors }}{% endif %}
{% if field.is_checkbox %}
{{ field.field }}{{ field.label_tag }}
{% else %}
{{ field.label_tag }}
{% if field.is_readonly %}
<div class="readonly">{{ field.contents }}</div>
{% else %}
{{ field.field }}
{% endif %}
{% endif %}
{% if field.field.help_text %}
<div class="help">{{ field.field.help_text|safe }}</div>
{% endif %}
</div>
{% if field.field.name %}
{% with field.field.name as fieldname %}
{% if sorted_inline_formsets|get_dict_value:fieldname != False %}
{% for inline_admin_formset in sorted_inline_formsets|get_dict_value:fieldname %}
{% include inline_admin_formset.opts.template %}
{% endfor %}
{% endif %}
{% endwith %}
{% endif %}
{% endfor %}
</div>
{% endfor %}
</fieldset>
This will add sorted inlines after the corresponding field... Now you only need the custom_filter for working with the dictionary in django template, create templatetags/custom_filter.py and add:
#register.filter
def get_dict_value(dict, key):
if key in dict:
return dict[key]
else:
return False
And voila: You can enter any fieldname into any Inline to add it after that field... It is a bit work to setup but if you have several inlines to sort it might be a cleaner way...

How I can get User.username and Group.name

I need to get the username and the name of group for all user.
The model that I use are User(default) and Group(default)
index.html:
{% for dato in usuarios %}
{{dato.first_name|title}}
{% for item in jefes %}
{{dato.groups}}
{% if dato.groups == item.id %} #I don't know to do this if
{{item.name}}
{% endif %}
{% endfor %}
{% endfor %}
view:
def inicio(request):
usuarios = User.Group.all()
grupos = Group.objects.all()
ctx = {'usuarios':usuarios,'grupos':grupos}
return render_to_response('index.html', ctx, context_instance=RequestContext(request))
You do not need the groups queryset from the view.
{% for dato in usuarios %}
{{dato.first_name|title}}
{% for group in dato.groups.all %}
{{group.name}}
{% endfor %}
{% endfor %}