How to select a specific related element in Django? - django

I have a model called 'Projects'.
Projects can be featured. If they are, they will be displayed on the home page
(Projects.filter(is_featured=True))
Each project contains several slides. These slides can be featured (Slide.is_featured=True), and contain an Image model which contains the actual image.
In my home page, I would like to display a slideshow in which each slide contains the project name, and the image contained in the featured slide.
I did that by adding a method called 'featured_slide()' in my Project Model, but now I realize that I've been hitting on the DB every time, and I would like to improve that by using the 'select_related' statement.
How can I do that?
Optimally, I would like to have a field like 'featured_slide' to represent the featured slide.
I was thinking of doing something along these lines:
Projects.filter(is_featured=True).annotate(featured_slide='slides__is_featured=True').select_related(slides__image)
I know it can't be that simple (slides__is_featured is not a database field), but you get the idea.

If you want a slideshow of only those Slides that themselves are featured as well as being related to a featured Projects:
class Project(...):
name = models.CharField()
is_featured = models.BooleanField()
class Slide(...):
project = models.ForeignKey(Project)
is_featured = models.BooleanField()
image = models.ImageField()
to query the slides (using select_related to avoid unnecessary queries):
slides = Slide.select_related("project").filter(is_featured=True, project__is_featured=True)
and template:
<ul>
{% for slide in slides %}
<li><img src="{{ slide.image.url }} /><span class="caption">{{ slide.project.name }}</caption></li>
{% endfor %}
</ul>
EDIT:
If you want to lookup the reverse relationship (i.e. get all the slides for a project), by default you can do the following:
project = Project.objects.get(...)
project_slides = project.slide_set.all()
You add _set to the model name. You can make this more intuitive by adding a related_name attribute to the relationship:
class Slide(...):
project = models.ForeignKey(Project, related_name="slideshow_slides")
and now use:
project = Project.objects.get(...)
project.slideshow_slides.all()

Related

how i can use django context inside context

Well I know that what I'm doing is not very feasible, but I wanted to know if there's any way to do this.I want to create a portfolio blog to post some 3d renders, for that I want to have more control over the structure of the page. for this I created two models (one for the post and another to receive the images, linking them to the post through a foreign key) so that I could have an indefinite number of images, the problem came when I decided that I wanted to be able to choose the one positioning of the images according to my need/desire, for that I did the following:
I used django summernote temporarily to be able to test the written posts, I knew that it would probably not be possible to do this because the content sent from the models is static.
I have the following models:
class Post(models.Model):
titulo_post=models.CharField(max_length=255, verbose_name='Titulo')
autor_post=models.ForeignKey(User, on_delete=models.DO_NOTHING, verbose_name='autor')
data_post=models.DateTimeField(default=timezone.now, verbose_name='Data publicação')
conteudo_post =models.TextField()
publicado_post=models.BooleanField(default=False, verbose_name='Status publicação')
def __str__(self) :
return self.titulo_post
and:
class Estudo(models.Model):
imagem=models.ImageField(upload_to='estd_img/%Y/%m/%d', blank=True, null=True)
post=models.ForeignKey(Post, on_delete=models.CASCADE)
I tried to put the following value in the field "conteudo_post" through the administrative area to see if it would work
<div class="container">
<div class="col-10 mx-auto">
<img class="img-fluid " src="{{imagem.0.url}}" alt="">
</div>
</div>
as I thought it didn't work, when I use {{post_conteudo}} the rendered html displays an escaped version of the content, when I use {{post_conteudo |safe}} it creates the image container, but is not able to find it. when checking the browser's developer mode I can see that the value of {{image.0.url}} was not processed and it remains in that format in the final html

How to use Django slugs creatively

In my frontpage.html. I have two buttons that link to the different categories of products I have I was using a for loop to get the slug needed for the URL link In the button, but this causes issues because it renders two buttons for each category i created in the models. My question: Is there a way for Django to only use one of these category slugs so I can specifically pick which URL it will render? I attached a picture of the frontpage.html file notice the for loop I am using to get the category slug that is being used to render the correct detail page. a for loop won't work since i have multiple categories
HTML
{% for category in menu_categories %}
Get Started
{% endfor %}
models.py for categories
class Category(models.Model):
title = models.CharField(max_length=255)
slug = models.SlugField(max_length=255)
ordering = models.IntegerField(default=0)
Here is the models.py as well. I was thinking there should be a way to explicitly call a specific slug and not render both buttons right next to each other

Using images in 2 different django models

I have a retail site selling multiple brands. Each brand has its logo on its own page. The logo images are in their own model.
How do I use the same logo for a different model on the index page? I'd like to use the same logos while highlighting some store coupons in the sidebar.
Currently, I have a Foreign Key to the store in the IMG model.
current code:
models.py
class Logo(models.Model):
store = models.ForeignKey(Store, on_delete=models.CASCADE,
related_name="storelogo")
image = models.ImageField(upload_to=get_image_path)
views.py
def show_store(request, slug):
store = Store.objects.get(slug=slug)
uploads = store.storelogo.all()
return render(request, 'store.html', {
'store': store,
'products': products,
'coupons': coupons,
'uploads': uploads,
})
HTML
<div class="store-logo">
{% for logo in store.storelogo.all %}
<img src="{{ logo.image.url }}">
{% endfor %}
</div>
The logo shows fine on the store page but I can't get it to show in a For loop on the index page. Is it possible?
I could add another image model and add the exact same logo images for the coupons but it seems to be totally against DRY principles. Are there template tags I can use on an index page or is it best to create another model?
Let me know if I left anything out. Thanks!

Django form validation/saving for a template with varying quantity and order of text, images, and forms

I am trying to create a Django app where a user (say a researcher or a teacher) can create content for other users (participants or students) where any given page may include any number of content items (such as surveys questions, text, and/or images), and these items can be arranged by the teacher in any order on a page.
I'm taking an approach similar to the last chapters (10-12) of the book Django by Example. The app from those chapters comes very close to giving an example of my case using an e-Learning platform app, but they only allow teachers to create Content like Text and Images, they do not allow teachers to create survey questions for students. Here is the general approach that I am following.
The book models content for text and images for a given page like so:
class Content(models.Model):
page = models.ForeignKey(Page, related_name='contents')
content_type = models.ForeignKey(ContentType,
limit_choices_to={'model__in':('text',
'image')})
object_id = models.PositiveIntegerField()
item = GenericForeignKey('content_type', 'object_id')
order = OrderField(blank=True, for_fields=['page'])
class Meta:
ordering = ['order']
class ItemBase(models.Model):
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
class Meta:
abstract = True
def render(self):
return render_to_string('courses/content/{}.html'.format(
self._meta.model_name), {'item': self})
class Text(ItemBase):
content = models.TextField()
class Image(ItemBase):
file = models.FileField(upload_to='images')
There's an interface for teachers to fill out and order this content for a page.
Content is rendered within a template like so:
<div class="page">
{% for content in page.contents.all %}
{% with item=content.item %}
<h2>{{ item.title }}</h2>
{{ item.render }}
{% endwith %}
{% endfor %}
</div>
And the html used in the render method for a Text Content is simply:
{{item.content|linebreaks|safe }}
I don't find it difficult to extend this with QuestionTypes that extend ItemBase (similar to Text and Image models), as well as creating a StudentAnswer model for storing answers in the database.
I would probably override ItemBase render and put it into the QuestionType model so that I could pass a StudentAnswer model form into the context for the QuestionType html file.
I could then just have the html that is rendered contain {{ form }} for simplicity sake, and we now have a question that acts like any other content item and can be ordered with all of the others. This assumes that the HTML that contains the content has a form tag that encompass all of the rendered content items.
My problem is handling the POST request in the view. I have no idea how to validate and save answers from multiple forms on any given single page generated in this way. Examples I find assume a consistent number of forms that you know by name and are of different types.
I've also played around with the idea of creating a single dynamically generated form, but the examples I've seen for that assume you will loop through the fields in the template and display them in order rather than my requirement that a teacher determines the order which may include text or images in-between questions.
Is there a way to create what I'm looking for or can someone point me in the right direction?

Widget to display categories as tree in Django admin

is there any existing code to display the list of some Category object in the admin of a Django site?
Ideally I'd like some tree representation like
cat_1
----cat_1_1
----cat_1_2
cat_2
cat_3
----cat_3_1
----cat_3_2
----cat_3_3
with up/down button to change the order.
class Category(models.Model):
parent = models.ForeignKey('self', null=True, related_name='children')
name = models.CharField(max_length=100)
Firstly, you haven't actually defined an order on this model - just a parent. You need something like MPTT which keeps track of the level and the position within that level.
Given that, it's fairly easy to write a __unicode__ method for the model which displays the number of hyphens equal to the category's level:
def __unicode__(self):
return '%s%s' % ('-' * self.level, self.name)
As for the up/down button, you'll need to write that in Javascript, I expect.
Here is one widget, based on django-mptt :
http://anentropic.wordpress.com/2009/11/05/more-django-mptt-goodness-filteredselectmultiple-m2m-widget/
looks like what you're looking for
There is a django-categories package, which add a select box with all category to your admin site to manage categories.
It's very simple
All you have to do in your view is get all objects:
categories = Category.objects.all()
Then in your template :
{% for category in categories %}
<li>- {{category.name}} </li>
{% for child in category.children.all %}
<ul>* {{child.nom}} </ul>
{% endfor %}
</li>
{% endfor %}
Generating the desired tree like structure requires "Modified Preorder Tree Traversal" of the tabular data. A custom implementation will be fairly complex.
You can use existing package called Django MPTT to simplify the hierarchical tree generation based on your Category model.
With it you can achieve following:
get descendants of a node
get ancestors of a node
get all nodes at a given level
get leaf nodes