I researched how I could pass in a datetime object to my templates, but none of them seems to work. Here is the code for my view:
class LeadListView(LoginRequiredMixin, generic.ListView):
# some other code
today_date = datetime.date.today()
def get_context_data(self, **kwargs):
context = super(LeadListView, self).get_context_data(**kwargs)
context['today_date'] = self.today_date
return context
However, when I try to use the today_date in the template, it doesn't work. I am trying to use the today_date so that I might use it in an if statement to see if today's date is between two other datetime variables. Thanks a lot!
Some additional information on how the django template looks like:
{% if lead.class_start_date <= today_date and lead.class_end_date >= today_date %}
{% endif %}
Here, class_start_date and class_end_date are just part of the Lead model.
This is the full list view:
class LeadListView(LoginRequiredMixin, generic.ListView):
tempalte_name = "leads/lead_list.html"
context_object_name = "leads"
def get_queryset(self):
user = self.request.user
# initial queryset of leads for the entire organisation
if user.is_organisor:
queryset = Lead.objects.filter(
organisation=user.userprofile,
agent__isnull=False
)
else:
queryset = Lead.objects.filter(
organisation=user.agent.organisation,
agent__isnull=False
)
#filter for the agent that is logged in
queryset = queryset.filter(agent__user=user)
return queryset
You do not need to pass this to the context. Django already has a {% now … %} template tag [Django-doc].
You thus can render this with:
{% now 'DATE_FORMAT' %}
If you plan to filter however on the current day, you should filter in the view, since that will filter at the database level, which is more efficient:
from django.utils.timezone import now
class LeadListView(LoginRequiredMixin, generic.ListView):
model = Lead
def get_queryset(self, *args, **kwargs):
today = now().date()
return super().get_queryset(*args, **kwargs).filter(
class_start_date__lte=today,
class_end_date__gte=today
)
Related
I want to get sum of items i get by using generic date view.
Example views.py
class OrderDayArchiveView(LoginRequiredMixin, generic.dates.DayArchiveView):
queryset = Order.objects.all()
date_field = 'date_ordered'
template_name = 'ordersys/manager/archive_page.html'
Example template:
{% for order in object_list %}
<li class="bg-light">
{{ order.id }}: {{order.print_ordered_items_products_amounts}} (${{order.create_cost}})
</li>
{% endfor %}
Example path in urls.py:
path('<int:year>/<int:month>/<int:day>/', views.OrderDayArchiveView.as_view(month_format='%m'), name="archive_day"),
I want to get sum of all 'order.create_cost' sent to template, is it possible to get filtered queryset in this view? If not, how can i sum it in the template.
You can simply override get_context_data and add your aggregation there:
from django.db.models import Sum
class OrderDayArchiveView(LoginRequiredMixin, generic.dates.DayArchiveView):
queryset = Order.objects.all()
date_field = 'date_ordered'
template_name = 'ordersys/manager/archive_page.html'
def get_context_data(self, *, object_list=None, **kwargs):
context = super().get_context_data(object_list=object_list, **kwargs)
queryset = context['object_list']
sum_create_cost = queryset.aggregate(Sum('create_cost'))['create_cost__sum']
context['sum_create_cost'] = sum_create_cost
return context
I have a problem when I want to paginate the filter that I create with django_filter, in my template it shows me the query set and filter but paginate does not work, I would like to know why this happens and if you could help me.
I'll insert snippets of my code so you can see.
This is my views.py
PD: i have all the necesary imports.
#method_decorator(staff_member_required, name='dispatch')
class EmployeeListView(ListView):
model = Employee
paginate_by = 4
def dispatch(self, request, *args, **kwargs):
if not request.user.has_perm('employee.view_employee'):
return redirect(reverse_lazy('home'))
return super(EmployeeListView, self).dispatch(request, *args, **kwargs)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['filter'] = EmployeeFilter(self.request.GET, queryset = self.get_queryset())
return context
filters.py
import django_filters
from .models import Employee, Accident
class EmployeeFilter(django_filters.FilterSet):
class Meta:
model = Employee
fields = {
'rutEmployee' : ['startswith']
}
You should override get_queryset.This means you have to put your filter in get_queryset like this:
#method_decorator(staff_member_required, name='dispatch')
class EmployeeListView(ListView):
model = Employee
paginate_by = 4
def dispatch(self, request, *args, **kwargs):
if not request.user.has_perm('employee.view_employee'):
return redirect(reverse_lazy('home'))
return super(EmployeeListView, self).dispatch(request, *args, **kwargs)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['filter'] = EmployeeFilter(self.request.GET, queryset = self.get_queryset())
return context
def get_queryset(self):
queryset = super().get_queryset()
return EmployeeFilter(self.request.GET, queryset=queryset).qs
and use object_list instead of filter in employee_list.html like this:
{% for employee in object_list|dictsort:"id" reversed %}
You could also try this:
(A snippet from my source code)
class ModelListView(ListView):
model = YourModel
paginate_by = 4 # Change this if you don't intend to paginate by 4
ordering = model_field_to_order_by
# variable used to know if a match was found for the search made using django_filters
no_search_result = False
def get_queryset(self, **kwargs):
search_results = YourDjangoFiltersForm(self.request.GET, self.queryset)
self.no_search_result = True if not search_results.qs else False
# Returns the default queryset if an empty queryset is returned by the django_filters
# You could as well return just the search result's queryset if you want to
return search_results.qs.distinct() or self.model.objects.all()
def get_query_string(self):
query_string = self.request.META.get("QUERY_STRING", "")
# Get all queries excluding pages from the request's meta
validated_query_string = "&".join([x for x in re.findall(
r"(\w*=\w{1,})", query_string) if not "page=" in x])
# Avoid passing the query path to template if no search result is found using the previous query
return "&" + validated_query_string.lower() if (validated_query_string and not self.no_search_result) else ""
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
# Pass to template if you want to do something whenever an empty queryset is return by django_filters
context["no_search_result"] = self.no_search_result
# This is the query string which should be appended to the current page in your template for pagination, very critical
context["query_string"] = self.get_query_string()
context['filter'] = YourDjangoFiltersForm()
return context
In your html template you need to append the querystring passed to your template from the view, a sample is shown below
{% for i in page_obj.paginator.page_range %}
{% if page_obj.number == i %}
<li class="page-item active" aria-current="page">
<span class="page-link">{{ i }}<span class="sr-only">(current)</span></span>
</li>
{% elif i > page_obj.number|add:'-5' and i < page_obj.number|add:'5' %} <li class="page-item"><a
class="page-link" href="?page={{ i }}{{ query_string }}">{{ i }}</a></li>
{% endif %}
{% endfor %}
I am trying to print the content fields from my database,
Here's my models.py file:
class Post(models.Model):
title = models.CharField(max_length=100)
content = models.TextField()
read_time = models.TimeField(null=True, blank=True)
view_count = models.IntegerField(default=0)
Here's my views.py file:-
class PostDetailView(DetailView):
model = Post
def get_object(self):
obj = super().get_object()
obj.view_count += 1
obj.save()
return obj
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
all_texts = {
'texts': context.content
}
print(all_texts[texts])
return context
I am trying to access all the data's from the content field from my database,
But the above way is not working, Is there any way I can access all the data's from the content field, because I have to perform some action on these fields, like calculate the read_time of any content, based on the length of it.
You do not have to override the .get_queryset(…) method [Django-doc] for that, since the object is already passed to the context. You can simply render it in the template with:
{{ object.content }}
In case you really need this in the context, you can implement this as:
class PostDetailView(DetailView):
model = Post
# …
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context.update(
texts=self.object.content
)
return context
In case you need all post objects, you can add these to the context:
class PostDetailView(DetailView):
model = Post
# …
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context.update(
texts=self.object.content,
posts=Post.objects.all()
)
return context
and render these as:
{% for post in posts %}
{{ post.content }}
{% endfor %}
It might be better to work with an F expression [Django-doc] when incrementing the view counter to avoid race conditions:
class PostDetailView(DetailView):
model = Post
def get_object(self):
obj = super().get_object()
views = obj.view_count
obj.view_count = F('view_count') + 1
obj.save()
obj.view_count = views+1
return obj
Just query all objects and loop the queryset to manipulate them according to your needs like so:
def your_view(self, **kwargs):
# Get all table entries of Model Post
queryset = Post.objects.all()
# Loop each object in the queryset
for object in queryset:
# Do some logic
print(object.content)
[...]
return (..., ...)
first import models
from . models import Post
then in your function
data=Post.objects.values('content').all()
Now data have all the values in content field
data=[{'content':first_value},{'content':second_value},..like this...]
I have a hard time understanding class based views in Django. At this time I try to implement a request.session in a ListView. I try to implement the following function based code from the MdM Django Tutorial in to a ListView.
def index(request):
...
# Number of visits to this view, as counted in the session variable.
num_visits = request.session.get('num_visits', 0)
request.session['num_visits'] = num_visits + 1
context = {
'num_visits': num_visits,
}
return render(request, 'index.html', context=context)
I tried the following (and a lot of other things) but to no avail:
class ListPageView(FormMixin, ListView):
template_name = 'property_list.html'
model = Property
form_class = PropertyForm
def get(self, request, *args, **kwargs):
num_visits = request.session.get('num_visits', 0)
request.session['num_visits'] = num_visits + 1
return super().get(request, *args, **kwargs)
# ... some more code here
In my template I have:
<p>You have visited this page {{ num_visits }}{% if num_visits == 1 %} time{% else %} times{% endif %}.</p>
But the template variable renders always empty.
You still need to pass it to the context, by overriding the get_context_data method [Django-doc]:
class ListPageView(FormMixin, ListView):
template_name = 'property_list.html'
model = Property
form_class = PropertyForm
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['num_visits'] = self.request.session['num_visits']
return context
def get(self, request, *args, **kwargs):
num_visits = request.session.get('num_visits', 0)
request.session['num_visits'] = num_visits + 1
return super().get(request, *args, **kwargs)
I understand that this is a late answer, but I ran into the same problem, and I will try to put my two cents in and maybe my answer will help newbies like me.
Your template always has access to the {{ request }} variable, so you can simply use {{request.session.key}} without defining additional context.
I can also see that you used the {% if %} conditional for the plural, but Django has a nice filter {{ value|pluralize }}, it might be more useful for that.
I want to create a listview with various optional filters. My url should be look like this:
shop/category_6/?manufacturer_id=3
And it works well when I put this url just in to the browser form. But when i try to add this option to a template it gives me NoReverseMatch. My template:
{% for manufacturer in manufacturer_list %}
<p>{{manufacturer.1}}</p>
{% endfor %}
It is my view:
class ItemListView(ListView):
model = Item
context_object_name = 'item_list'
template_name = 'shop/item_list.html'
def get_queryset(self, **kwargs):
full_item_list=Item.objects.all()
queryset=full_item_list.filter(category__id=int(self.kwargs['category_id']))
manufacturer_id = self.request.GET.get('manufacturer_id')
if manufacturer_id:
queryset=queryset.filter(manufacturer__id=int(manufacturer_id))
return queryset
def get_context_data(self, **kwargs):
context = super(ItemListView, self).get_context_data(**kwargs)
context['category']=get_object_or_404(Category, pk=self.kwargs['category_id'])
context['manufacturer_list'] = self.get_queryset(**kwargs).values_list('manufacturer__id', 'manufacturer__name').distinct().order_by('manufacturer__name')
return context
What is my mistake?
You didn't configure GET params... May be shop/category_6/?manufacturer_id=3
{{manufacturer.1 }}