Django model filtering(query) - django

I'm struggling with a model filtering, what I doing wrong? Here is my code:
models.py
class Images(models.Model):
TAK_NIE = (
('y', 'Tak'),
('n', 'Nie')
)
nazwa_polska = models.ForeignKey(Roslina, related_name='images', on_delete=models.CASCADE)
image = models.ImageField(max_length=255, upload_to=generate_filename)
zdjecie_glowne = models.CharField(max_length=1,choices=TAK_NIE,default='n')
def czyGlowne(self):
return self.filter(zdjecie_glowne='y')
def __str__(self):
return self.nazwa_polska.nazwa_polska
html not working:
{% for zdjecie in ros.images.czyGlowne %}
{{ zdjecie.image }}
<img src="{% static '' %}{{ zdjecie.image|cut:"static/"}}" alt="brak
zdjecia" class="img-thumbnail zdjecia">
{% endfor %}
on the same page working html code:
{% for zdjecie in ros.images.all %}
<div class="col-lg-4">
<img src="{% static '' %}{{ zdjecie.image|cut:"static/"}}" alt="brak
zdjecia" class="img-thumbnail zdjecia">
</div>
{% endfor %}

Your view should be filtering or creating the filtered queryset.
You can also filter like this:
{% for zdjecie in ros.images.all %}
(% if zdjecie.zdjecie_glowne == 'y' %}
{{ zdjecie.image }}
<img src="{% static '' %}{{ zdjecie.image|cut:"static/"}}" alt="brak
zdjecia" class="img-thumbnail zdjecia">
{% endif %}
{% endfor %}

Related

Django admin template - grid instead of list

What is the easiest / fastest way to override Django admin form to display grid of elements instead of list? My model includes a field for a 100x100px pic, and it would be easier to see them as a grid of pictures, not a list.
This is not terribly difficult, but it requires you to copy several large chunks of code from the Django library and incorporate them into your own application. Here's the overview:
You'll need to copy and then modify several template tags from django.contrib.admin.templatetags.admin_list:
django.contrib.admin.templatetags.admin_list.items_for_result
django.contrib.admin.templatetags.admin_list.result_list
django.contrib.admin.templatetags.admin_list.results
django.contrib.admin.templatetags.admin_list.result_list_tag
You'll need to copy and then modify a couple of templates:
django/contrib/admin/templates/admin/change_list.html
django/contrib/admin/templates/admin/change_list_results.html
For purposes of illustrating the solution, I have created an app called spam and a model called SpamPhoto, along with a model admin that is customized to display the image tag. I am using Bootstrap 4 for the grid. There are still some issues you might need to track down and figure out, like getting rid of the checkbox that shows up for each item. But this code should get about 90% of the way there.
Here's an overview of the files that I created/modified, and which you'll find below:
spam/models.py: contains the SpamPhoto model
spam/admin.py: contains the SpamPhotoAdmin
spam/templatetags/spamphoto_admin_list.py: contains the template tag / functions that will render the customized change list
spam/templates/admin/spam/spamphoto/change_list.html: this is the main changelist template, and only has a few small changes: it loads our custom template tags, it includes Bootstrap CSS, and it calls a customized template tag (defined below)
spam/templates/admin/spam/spamphoto/change_list_results.html: heavy modifications here, getting rid of the table elements and replacing with divs.
So again, this is a LOT of code, and most of it is lifted directly without very many changes. Here we go:
# spam/models.py
from django.db import models
class SpamPhoto(models.Model):
name = models.CharField(max_length=100)
image = models.ImageField()
# spam/admin.py
from django.contrib import admin
from django.utils.html import mark_safe
class SpamPhotoAdmin(admin.ModelAdmin):
list_display = ('name', 'image_tag')
list_display_links = ('name', 'image_tag')
def image_tag(self, obj):
return mark_safe(f'<img class="img-fluid" src="{obj.image.url}" />')
# spam/templatetags/spamphoto_admin_list.py
from django import template
# Note: you should import these from their "correct" locations! This is cheap/dirty:
from django.contrib.admin.templatetags.admin_list import (ResultList, result_headers, result_hidden_fields,
_coerce_field_name, lookup_field, ObjectDoesNotExist,
display_for_field, datetime, display_for_value, models,
mark_safe, NoReverseMatch, add_preserved_filters, format_html)
from django.contrib.admin.templatetags.base import InclusionAdminNode
register = template.Library()
def spamphoto_items_for_result(cl, result, form):
"""
Cloned from django.contrib.admin.templatetags.admin_list.items_for_result
The only modification is found at the very end of this function, where the HTML
tags are changed from `td` to `div`
"""
def link_in_col(is_first, field_name, cl):
if cl.list_display_links is None:
return False
if is_first and not cl.list_display_links:
return True
return field_name in cl.list_display_links
first = True
pk = cl.lookup_opts.pk.attname
for field_index, field_name in enumerate(cl.list_display):
empty_value_display = cl.model_admin.get_empty_value_display()
row_classes = ['field-%s' % _coerce_field_name(field_name, field_index)]
try:
f, attr, value = lookup_field(field_name, result, cl.model_admin)
except ObjectDoesNotExist:
result_repr = empty_value_display
else:
empty_value_display = getattr(attr, 'empty_value_display', empty_value_display)
if f is None or f.auto_created:
if field_name == 'action_checkbox':
row_classes = ['action-checkbox']
boolean = getattr(attr, 'boolean', False)
result_repr = display_for_value(value, empty_value_display, boolean)
if isinstance(value, (datetime.date, datetime.time)):
row_classes.append('nowrap')
else:
if isinstance(f.remote_field, models.ManyToOneRel):
field_val = getattr(result, f.name)
if field_val is None:
result_repr = empty_value_display
else:
result_repr = field_val
else:
result_repr = display_for_field(value, f, empty_value_display)
if isinstance(f, (models.DateField, models.TimeField, models.ForeignKey)):
row_classes.append('nowrap')
row_class = mark_safe(' class="%s"' % ' '.join(row_classes))
# If list_display_links not defined, add the link tag to the first field
if link_in_col(first, field_name, cl):
table_tag = 'th' if first else 'td'
first = False
# Display link to the result's change_view if the url exists, else
# display just the result's representation.
try:
url = cl.url_for_result(result)
except NoReverseMatch:
link_or_text = result_repr
else:
url = add_preserved_filters({'preserved_filters': cl.preserved_filters, 'opts': cl.opts}, url)
# Convert the pk to something that can be used in Javascript.
# Problem cases are non-ASCII strings.
if cl.to_field:
attr = str(cl.to_field)
else:
attr = pk
value = result.serializable_value(attr)
link_or_text = format_html(
'<a href="{}"{}>{}</a>',
url,
format_html(
' data-popup-opener="{}"', value
) if cl.is_popup else '',
result_repr)
yield format_html('<{}{}>{}</{}>', table_tag, row_class, link_or_text, table_tag)
else:
# By default the fields come from ModelAdmin.list_editable, but if we pull
# the fields out of the form instead of list_editable custom admins
# can provide fields on a per request basis
if (form and field_name in form.fields and not (
field_name == cl.model._meta.pk.name and
form[cl.model._meta.pk.name].is_hidden)):
bf = form[field_name]
result_repr = mark_safe(str(bf.errors) + str(bf))
# THIS LINE HAS BEEN CHANGED:
yield format_html('<div{}>{}</div>', row_class, result_repr)
if form and not form[cl.model._meta.pk.name].is_hidden:
# THIS LINE HAS BEEN CHANGED:
yield format_html('<div>{}</div>', form[cl.model._meta.pk.name])
def spamphoto_result_list(cl):
"""
Cloned from django.contrib.admin.templatetags.admin_list.result_list
The only change is to the `results` value in the returned dict, where we call `spamphoto_results`
"""
headers = list(result_headers(cl))
num_sorted_fields = 0
for h in headers:
if h['sortable'] and h['sorted']:
num_sorted_fields += 1
return {
'cl': cl,
'result_hidden_fields': list(result_hidden_fields(cl)),
'result_headers': headers,
'num_sorted_fields': num_sorted_fields,
# THIS LINE HAS BEEN CHANGED:
'results': list(spamphoto_results(cl)),
}
def spamphoto_results(cl):
"""
Cloned from django.contrib.admin.templatetags.admin_list.results
The only changes are where we call `spamphoto_items_for_result` instead of `items_for_result`
"""
if cl.formset:
for res, form in zip(cl.result_list, cl.formset.forms):
# THIS LINE HAS BEEN CHANGED:
yield ResultList(form, spamphoto_items_for_result(cl, res, form))
else:
for res in cl.result_list:
# THIS LINE HAS BEEN CHANGED:
yield ResultList(None, spamphoto_items_for_result(cl, res, None))
#register.tag(name='spamphoto_result_list')
def spamphoto_result_list_tag(parser, token):
"""
Cloned from django.contrib.admin.templatetags.admin_list.result_list_tag
The only change is to the `func` param, which now uses out custom `spamphoto_result_list` function
"""
return InclusionAdminNode(
parser, token,
# THIS LINE HAS BEEN CHANGED:
func=spamphoto_result_list,
template_name='change_list_results.html',
takes_context=False,
)
# spam/templates/admin/spam/spamphoto/change_list.html
{% extends "admin/base_site.html" %}
{% load i18n admin_urls static admin_list %}
<!-- ADDED THIS LINE / INCLUDING OUR CUSTOM TEMPLATE TAGS -->
{% load spamphoto_admin_list %}
{% block extrastyle %}
{{ block.super }}
<link rel="stylesheet" type="text/css" href="{% static "admin/css/changelists.css" %}">
{% if cl.formset %}
<link rel="stylesheet" type="text/css" href="{% static "admin/css/forms.css" %}">
{% endif %}
{% if cl.formset or action_form %}
<script src="{% url 'admin:jsi18n' %}"></script>
{% endif %}
{{ media.css }}
{% if not actions_on_top and not actions_on_bottom %}
<style>
#changelist table thead th:first-child {width: inherit}
</style>
{% endif %}
<!-- ADDED THIS LINE / INCLUDING BOOTSTRAP -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap#4.6.2/dist/css/bootstrap.min.css">
{% endblock %}
{% block extrahead %}
{{ block.super }}
{{ media.js }}
{% endblock %}
{% block bodyclass %}{{ block.super }} app-{{ opts.app_label }} model-{{ opts.model_name }} change-list{% endblock %}
{% if not is_popup %}
{% block breadcrumbs %}
<div class="breadcrumbs">
{% translate 'Home' %}
› {{ cl.opts.app_config.verbose_name }}
› {{ cl.opts.verbose_name_plural|capfirst }}
</div>
{% endblock %}
{% endif %}
{% block coltype %}{% endblock %}
{% block content %}
<div id="content-main">
{% block object-tools %}
<ul class="object-tools">
{% block object-tools-items %}
{% change_list_object_tools %}
{% endblock %}
</ul>
{% endblock %}
{% if cl.formset and cl.formset.errors %}
<p class="errornote">
{% if cl.formset.total_error_count == 1 %}{% translate "Please correct the error below." %}{% else %}{% translate "Please correct the errors below." %}{% endif %}
</p>
{{ cl.formset.non_form_errors }}
{% endif %}
<div class="module{% if cl.has_filters %} filtered{% endif %}" id="changelist">
<div class="changelist-form-container">
{% block search %}{% search_form cl %}{% endblock %}
{% block date_hierarchy %}{% if cl.date_hierarchy %}{% date_hierarchy cl %}{% endif %}{% endblock %}
<form id="changelist-form" method="post"{% if cl.formset and cl.formset.is_multipart %} enctype="multipart/form-data"{% endif %} novalidate>{% csrf_token %}
{% if cl.formset %}
<div>{{ cl.formset.management_form }}</div>
{% endif %}
{% block result_list %}
{% if action_form and actions_on_top and cl.show_admin_actions %}{% admin_actions %}{% endif %}
<!-- THIS LINE HAS BEEN CHANGED: -->
{% spamphoto_result_list cl %}
{% if action_form and actions_on_bottom and cl.show_admin_actions %}{% admin_actions %}{% endif %}
{% endblock %}
{% block pagination %}{% pagination cl %}{% endblock %}
</form>
</div>
{% block filters %}
{% if cl.has_filters %}
<div id="changelist-filter">
<h2>{% translate 'Filter' %}</h2>
{% if cl.has_active_filters %}<h3 id="changelist-filter-clear">
✖ {% translate "Clear all filters" %}
</h3>{% endif %}
{% for spec in cl.filter_specs %}{% admin_list_filter cl spec %}{% endfor %}
</div>
{% endif %}
{% endblock %}
</div>
</div>
{% endblock %}
# spam/templates/admin/spam/spamphoto/change_list_results.html
{% load i18n static %}
{% if result_hidden_fields %}
<div class="hiddenfields">{# DIV for HTML validation #}
{% for item in result_hidden_fields %}{{ item }}{% endfor %}
</div>
{% endif %}
{% if results %}
<div class="container">
<div class="row">
{% for result in results %}
{% if result.form and result.form.non_field_errors %}
<div>{{ result.form.non_field_errors }}</div>
{% endif %}
<div class="col-sm-2">{% for item in result %}{{ item }}{% endfor %}</div>
{% endfor %}
</div>
</div>
{% endif %}

filter in django 2.0

Hey I am writing app in django many blogs with many articles each but i dont know how to take artices which belongs to blog and write filter
My articles model
class Articles(models.Model):
title = models.CharField(max_length=150, verbose_name="Tytul")
content = models.TextField(verbose_name="Tekst")
published = models.DateTimeField(verbose_name="Data publikacji",auto_now=True)
image = models.FileField(upload_to="images",verbose_name="Obrazy",default=None)
blog = models.ForeignKey(Blogs,on_delete=models.CASCADE,null=True)
My blogs model
class Blogs(models.Model):
title = models.CharField(max_length=150, verbose_name="Tytul")
user = models.CharField(max_length=160, verbose_name="Uzytkownik")
blog.html
{% include 'base.html' %}
{% block blog %}
<h2>{{ blog.title }}</h2>
<div class="blog-info">
Tworca : {{ blog.user }}
</div>
{% block article %}
{% for a in article.blog_set.all %} <---- here
<div class="article">
Opublikowano : {{ a.published }}
</div>
<img src="{{ a.image.url }}" class="article-img">
<div class="article-intro">
<p>{{ a.content }}</p>
</div>
{% endfor %}
{% endblock %}
{% endblock %}
database

Django: the information is not processed for a given condition if

Template tag {% if %} {% endif %} does't work correctly. I need to make the search results on the page appear only after the search query. But for some reason, when the page loads, all existing content appears at once. But after get request filter works correctly.
views.py
def search(request):
place_list = Places.objects.all()
place_filter = PlaceFilter(request.GET, queryset=place_list)
return render(request, 'search/user_list.html', {'filter': place_filter})
html
{% if filter.qs %}
<div class="row">
{% for obj in filter.qs %}
<div class="col-md-3 admin__block">
<div class="cover__wrapper">
<img src="{{ obj.main_photo.url }}" alt="">
<span>#</span>{{ obj.name }}
<p>{{ obj.description }}</p>
</div>
</div>
{% endfor %}
</div>
{% endif %}
filters.py
class PlaceFilter(django_filters.FilterSet):
name = django_filters.CharFilter(lookup_expr='icontains', widget=forms.TextInput(attrs={
'placeholder': 'Search place', 'class': 'input__search'}))
class Meta:
model = Places
fields = ['name']
FilterSet's qs property returns filterset's queryset. So it's always True.
You can use request.GET in template to check if GET contains any request data and render only filtered data:
{% if request.GET %}
<div class="row">
{% for obj in filter.qs %}
<div class="col-md-3 admin__block">
<div class="cover__wrapper">
<img src="{{ obj.main_photo.url }}" alt="">
<span>#</span>{{ obj.name }}
<p>{{ obj.description }}</p>
</div>
</div>
{% endfor %}
</div>
{% endif %}

error in index.html of django-admin using django-admin-notifications

I am using django to make a new admin panel and I am also using django-admin-notifications to show notifications in my admin panel. I don't know why it is not working.
Here is my models.py
from __future__ import unicode_literals
from django.db import models
class MyAlbum(models.Model):
title = models.CharField(max_length=30)
photos = models.IntegerField()
def __unicode__(self):
return self.title
class Person(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
def __unicode__(self):
return self.first_name
class Musician(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
instrument = models.CharField(max_length=100)
def __unicode__(self):
return self.first_name
my admin.py
from django.contrib import admin
from django.contrib.admin import AdminSite
from .models import Person,MyAlbum,Musician
from django.contrib import admin
class MyAdminSite(AdminSite):
site_header = 'Wedding Administration'
site_admin = MyAdminSite(name='weddingadmin')
admin.site.register(Person)
admin.site.register(MyAlbum)
admin.site.register(Musician)
site_admin.register(Person)
site_admin.register(MyAlbum)
my notifications.py
import admin_notifications
from models import Person
def notification():
broken_links = Person.objects.filter(status=False).count()
if broken_links:
return "You have %s broken link%s.<br>You can view or fix them using the <a href='/admin/linkcheck/'>Link Manager</a>." % (broken_links, "s" if broken_links>1 else "")
else:
return ''
admin_notifications.register(notification)
I have also made changes in index.html of admin site
{% load notification_tag %}
{% extends "admin/base_site.html" %}
{% load i18n static %}
{% block extrastyle %}{{ block.super }}<link rel="stylesheet" type="text/css" href="{% static "admin/css/dashboard.css" %}" />{% endblock %}
{% block coltype %}colMS{% endblock %}
{% block bodyclass %}{{ block.super }} dashboard{% endblock %}
{% block breadcrumbs %}{% endblock %}
{% block content %}
{% error_notifications %}
<div id="content-main">
{% if app_list %}
{% for app in app_list %}
<div class="app-{{ app.app_label }} module">
<table>
<caption>
{{ app.name }}
</caption>
{% for model in app.models %}
<tr class="model-{{ model.object_name|lower }}">
{% if model.admin_url %}
<th scope="row">{{ model.name }}</th>
{% else %}
<th scope="row">{{ model.name }}</th>
{% endif %}
{% if model.add_url %}
<td>{% trans 'Add' %}</td>
{% else %}
<td> </td>
{% endif %}
{% if model.admin_url %}
<td>{% trans 'Change' %}</td>
{% else %}
<td> </td>
{% endif %}
</tr>
{% endfor %}
</table>
</div>
{% endfor %}
{% else %}
<p>{% trans "You don't have permission to edit anything." %}</p>
{% endif %}
</div>
{% endblock %}
{% block sidebar %}
<div id="content-related">
<div class="module" id="recent-actions-module">
<h2>{% trans 'Recent actions' %}</h2>
<h3>{% trans 'My actions' %}</h3>
{% load log %}
{% get_admin_log 10 as admin_log for_user user %}
{% if not admin_log %}
<p>{% trans 'None available' %}</p>
{% else %}
<ul class="actionlist">
{% for entry in admin_log %}
<li class="{% if entry.is_addition %}addlink{% endif %}{% if entry.is_change %}changelink{% endif %}{% if entry.is_deletion %}deletelink{% endif %}">
{% if entry.is_deletion or not entry.get_admin_url %}
{{ entry.object_repr }}
{% else %}
{{ entry.object_repr }}
{% endif %}
<br/>
{% if entry.content_type %}
<span class="mini quiet">{% filter capfirst %}{{ entry.content_type }}{% endfilter %}</span>
{% else %}
<span class="mini quiet">{% trans 'Unknown content' %}</span>
{% endif %}
</li>
{% endfor %}
</ul>
{% endif %}
</div>
</div>
{% endblock %}
please tell me what I am doing wrong.The index.html is the actual index.html of the admin template
EDIT 1:
TemplateSyntaxError at /admin/
'notification_tag' is not a registered tag library. Must be one of:
admin_list
admin_modify
admin_static
admin_urls
cache
i18n
l10n
log
static
staticfiles
tz
I was installing django-admin-notifications via pip but i found that only init.py file was installed in the site-packages so i cloned the repository so my advice is don't install django-admin-notifications via pip although there is a package available but only the init.py file was installed

Django Reverse Query in Template

I have models like this
class Blog(models.Model):
name = models.CharField(max_length=100)
tagline = models.TextField()
def __unicode__(self):
return self.name
class Entry(models.Model):
blog = models.ForeignKey(Blog)
headline = models.CharField(max_length=255)
I want to list all blogs in a page. I have written a view such that
def listAllBlogs(request):
blogs= Blog.objects.all()
return object_list(
request,
blogs,
template_object_name = "blog",
allow_empty = True,
)
And I can display tagline of blog such that in view
{% extends "base.html" %}
{% block title %}{% endblock %}
{% block extrahead %}
{% endblock %}
{% block content %}
{% for blog in blog_list %}
{{ blog.tagline }}
{% endfor %}
{% endblock %}
But I would like to show, such thing blog__entry__name but I don't know how can I achive this in template.
Also, there may be no entry in a blog. How can I detect in template ?
Thanks
To access blog entries (Related Manager): blog.entry_set.all
To do other actions if blog have no entries, you have the {% empty %} tag that is executed when the set is empty.
{% block content %}
{% for blog in blog_list %}
{{ blog.tagline }}
{% for entry in blog.entry_set.all %}
{{entry.name}}
{% empty %}
<!-- no entries -->
{% endfor %}
{% endfor %}
{% endblock %}
based on your code you could do the following.
{% block content %}
{% for blog in blog_list %}
{{ blog.tagline }}
{% for entry in blog.entry_set.all %}
{{entry.name}}
{% endfor %}
{% endfor %}
{% endblock %}