This is my template file:
{% for tag, count in tags.items %}
{{ tag }} ({{count}}),
{% endfor %}
urls.py
url(r'^tag/(?P<slug>[\w-]+)/$', views.tags, name='tags'),
I am trying to take {{ tag }} as slug parameter. Is it possible? Next I would try to create page where I will list all pages that cointain tag in keywords field in Sites model.
I don't have tag model by the way. I am trying to take my tag variable and put it into my url (tag/tagvariable).
I get tags that way:
index.view
tags = Tags().all_tags()
context['tags'] = tags
calculations.py
class Tags():
def all_tags(self):
sites = Site.objects.values('keywords')
keywords = []
tags = []
for site in sites:
keywords.append(site['keywords'].split(','))
for keyword in keywords:
for tag in keyword:
tags.append(tag.strip())
return(dict(Counter(tags)))
models.py
class Site(models.Model):
category = models.ForeignKey('Category')
subcategory = ChainedForeignKey(
'Subcategory',
chained_field='category',
chained_model_field='category',
show_all=False,
auto_choose=True)
name = models.CharField(max_length=70)
description = models.TextField()
keywords = MyTextField()
date = models.DateTimeField(default=datetime.now, editable=False)
url = models.URLField()
is_active = models.BooleanField(default=False)
def get_absolute_url(self):
return "%s/%i" % (self.subcategory.slug, self.id)
class Meta:
verbose_name_plural = "Strony"
def __str__(self):
return self.name
A tag model is going to make your life easier
I'm assuming that you've make the correct view tag, use the slugify tag to convert your tag to a slug
{% for tag, count in tags.items %}
{{ tag }} ({{count}}),
{% endfor %}
and in the urls.py
url(r'^tag/(?P<slug>[-\w]+)/$', views.tags, name='tags'),
Related
I have this model.py file:
class Category(models.Model):
title = models.CharField(max_length=255, verbose_name="Title")
class Meta:
verbose_name_plural = "Categories"
def __str__(self):
return self.title
class Video(models.Model):
title = models.CharField(max_length=128)
description = models.TextField(default='')
thumbnail = models.ImageField(default='default_thumbnail.png', upload_to='thumbnails')
date_posted = models.DateTimeField(default=timezone.now)
category = models.ForeignKey(
Category,
on_delete=models.SET_DEFAULT,
#null=True,
default=1,
verbose_name="Category"
)
def __str__(self):
return self.title
Each video has its own category and I want to display on one page a given number of films in each category.
Currently, I'm only showing the last 5 videos on the page:
def home(request):
latest_videos = Video.objects.all().order_by('-date_posted')[:5]
categories = Category.objects.all()
context = {
'latest_videos': latest_videos,
#'categories': categories,
}
return render(request, 'videos/home.html', context)
I have no idea how to display a given number of movies in each category. I tried to send all the videos and query them on the template, but this is probably impossible.
Any ideas? I'm still learning Django, but this time I found a problem I can't solve all day.
Thanks
I don't know how many categories do you need to show in your template but one way to do this is like:
def home(request):
ready_data = []
all_categories = Category.objects.prefetch_related('video_set').all() # Note that video_set is your default related query name
for _c in all_categories:
related_videos = _c.video_set.all().order_by('-date_posted')[:5]
ready_data.append({"category_id": _c.id, "category_title": _c.title, "related_videos": related_videos})
context = {
'data': ready_data
}
return render(request, 'videos/home.html', context)
And you should also change this part of your template to something like:
{% for d in data %}
<p> category: {{ d.category_id }}, {{ d.category_title }} </p>
{% for v in d.related_videos %}
<h3> Videos </h3>
<p> {{ v.id }}- {{v.title}} </p>
{% endfor %}
{% endfor %}
This way you can show each category and 5 last of it's related videos.
I have a ListView where a I want to list products. The problem is that I can't get the related image of these products as they are in a different model.
The model for products is:
class Product(models.Model):
brand = models.ForeignKey(Brand, on_delete=models.CASCADE, verbose_name='marca')
name = models.CharField('nombre', max_length=40)
description = models.TextField('descripción', blank=True)
price = models.DecimalField(max_digits=8, decimal_places=2)
slug = models.SlugField(max_length=50)
active = models.BooleanField('activo',default=True)
in_stock = models.BooleanField('en stock', default=True)
tags = models.ManyToManyField(ProductTag, blank=True)
date_updated = models.DateTimeField('última actualización', auto_now=True)
The model of images is:
class ProductImage(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE, verbose_name='producto')
image = models.ImageField('imagen', upload_to="product-images")
thumbnail = models.ImageField('miniatura', upload_to="product-thumbnails", null=True)
To get both models in the template I used context.update in the view.
class ProductListView(ListView):
template_name = 'product_list.html'
context_object_name = 'products_list'
model = models.Product
paginate_by = 4
def get_context_data(self, **kwargs):
context = super(ProductListView, self).get_context_data(**kwargs)
context.update({'product_images_list': models.ProductImage.objects.all()})
return context
def get_queryset(self):
tag = self.kwargs['tag']
self.tag = None
if tag != 'all':
self.tag = get_object_or_404(models.ProductTag, slug=tag)
if self.tag:
products = models.Product.objects.active().filter(tags=self.tag)
else:
products = models.Product.objects.active()
return products.order_by('name')
Additionally, I created a filter to iterate both models in a forloop but I think is useless as I don't want to iterate both models, I just want to get the first image that matches the product's FK to show it in the template:
from django import template
register = template.Library()
#register.filter(name='zip')
def zip_lists(a, b):
return zip(a, b)
The template I'm using is:
{% extends 'base.html' %}
{% load humanize %}
{% load product_extras %}
{% block content %}
<div class="destacados">
{% for product, image in products_list|zip:product_images_list %}
<div class="collections coll-watches">
<img class="foto" src="{{ image.thumbnail.url }}">
<p class="prod-description">{{ product.name }}</p>
<p class="prod-description prices"><strong>$ {{ product.price|intcomma }}</strong></p>
<a class="boton-tr boton-tr-watches" href="#">Agregar al carrito</a>
</div>
{% endfor %}
</div>
{% endblock content %}
As you can see the problem is in <img class="foto" src="{{ image.thumbnail.url }}">. I know this is incorrect, but I don't know how to get the image related to the product through its FK.
I'm new i django (only two months) and I'm sure this should be easier, but I can figure it out...
Any help would be appreciated!!
Best regards
you can define a get image url method in your product model as below
def get_image_url(self):
img = self.productimage_set.first()
if img:
return img.thumbnail.url
return img #None
and call it in your templates get_image_url
Thank you very much #bmons. I had to modify the method a little bit, but your answer gave me the clue I needed.
This is the final code:
def get_image_url(self):
img = self.productimage_set.first().thumbnail.url
if img:
return img
return img #None
When Using img = self.productimage_set.thumbnail.first() I get a RelatedManager error.
Anyway, I really appreciate your help!! Cheers
I have a list of users and want to display their tasks only if the selected user belongs to the same department. My Models have a department field that I want to compare.
This is my template code.
{% extends 'view_users.html' %}
{% block view_user_tasks %}
Back
<p> todo lists for {{ user }}</p>
{% for todo in view_user_tasks %}
<a id="{{todo.id}}" class="todo_remove"></a>
{% endfor %}
{% endblock view_user_tasks %}
What i want to do is evaluate this condition:
if request.user.Department == user.Department:
show user tasks
This are my respective views.
class ViewUsers(ListView):
model = CustomUser
template_name = 'view_users.html'
class ViewUserTasks(ListView):
model = Todo
template_name = 'view_user_tasks.html'
context_object_name = 'view_user_tasks'
My models.py
class Todo(models.Model):
title = models.CharField(max_length=30)
body = models.CharField(max_length=255)
created_at = models.DateTimeField(auto_now_add=True, blank=True)
checked = models.BooleanField(default=False)
owner = models.ManyToManyField(CustomUser)
id = HashidAutoField(primary_key=True)
def __str__(self):
return "%s: %s" % (self.title, self.body)
class CustomUser(AbstractUser):
Department = models.CharField(max_length=30, blank=True)
How can I be able to accomplish this?
Do your filtering logic in the view. You can override the default get_queryset method and return only the Todos that you want.
class ViewUserTasks(ListView):
template_name = 'view_user_tasks.html'
context_object_name = 'view_user_tasks'
def get_queryset(self):
return Todo.objects.filter(user__Department=self.request.user.Department)
And then just loop through the returned data like you are already doing.
If I clearly understand your question, you can compare it like this:
{% if todo.user.id == user.id %}
I've got a model which I'm trying to filter according to an argument passed in the url, then display the filtered object via a template, but I don't know what I'm doing wrong.
Here's the urls.py:
url(r'^courses/(?P<course_code>\w+)/$', views.course, name="course"),
Here's the view:
from website.models import Course
def course(request, course_code):
current_course = Course.objects.filter(short_title='course_code')
template = loader.get_template('website/course.html')
context = Context({
'current_course': current_course,
})
return HttpResponse(template.render(context))
Here's the model:
class Course(models.Model):
title = models.CharField(max_length=200)
short_title = models.CharField(max_length=5)
course_type = models.CharField(max_length=100)
start_date = models.DateTimeField()
end_date = models.DateTimeField()
fee = models.IntegerField()
places = models.IntegerField()
venue = models.CharField(max_length=200)
description = models.TextField()
short_description = models.TextField()
age_low = models.IntegerField()
age_high = models.IntegerField()
And here's the template:
{% if current_course %}
{% for course in current_course %}
{{ current_course.title }}
{% endfor %}
{% else %}
<p>Sorry, that course doesn't exist.</p>
{% endif %}
And when I load the page /courses/CR1 (the course with short_title="CR1" definitely exists because it renders fine on another template where I'm not filtering but just displaying all the courses), it gives me "Sorry, that course doesn't exist."
Can anyone see what I'm doing wrong?
In this line:
current_course = Course.objects.filter(short_title='course_code')
You're checking for course titles with the exact text 'course_code'. You mean to use the value of the variable course_code:
current_course = Course.objects.filter(short_title=course_code)
Models:
class Technology(models.Model):
name = models.CharField(max_length=100, unique=True)
slug = models.SlugField(max_length=100, unique=True)
class Site(models.Model):
name = models.CharField(max_length=100, unique=True)
slug = models.SlugField(max_length=100, unique=True)
technology = models.ManyToManyField(Technology, blank=True, null=True)
Views:
def portfolio(request, page=1):
sites_list = Site.objects.select_related('technology').only('technology__name', 'name', 'slug',)
return render_to_response('portfolio.html', {'sites':sites_list,}, context_instance=RequestContext(request))
Template:
{% for site in sites %}
<div>
{{ site.name }},
{% for tech in site.technology.all %}
{{ tech.name }}
{% endfor %}
</div>
{% endfor %}
But in that example each site makes 1 additional query to get technology list. Is there any way to make it in 1 query somehow?
What you are looking for is an efficient way to do reverse foreign-key lookups. A generic approach is:
qs = MyRelatedObject.objects.all()
obj_dict = dict([(obj.id, obj) for obj in qs])
objects = MyObject.objects.filter(myrelatedobj__in=qs)
relation_dict = {}
for obj in objects:
relation_dict.setdefault(obj.myobject_id, []).append(obj)
for id, related_items in relation_dict.items():
obj_dict[id].related_items = related_items
I wrote a blogpost about this a while ago, you can find more info here: http://bit.ly/ge59D2
How about:
Using Django's session framework; load list request.session['lstTechnology'] = listOfTechnology on startup. And use session in rest of the app.