Using images in 2 different django models - django

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!

Related

How to pass dynamic filtering options in django_filters form instead of all model objects?

I have the following structure of the project (models):
Company (based on Groups) <-- Products (foreignKey to Company) <-- Reviews (foreignKey to Products).
Inside template i want to give a user an opportunity to filter reviews by products, but when using django_filters it shows corrects queryset of reviews (related only to company's products) but in filter form dropdown options i can see all products of all companies (even those which are not presented on the page), for example for Company X i see on my page only Cactus and Dakimakura reviews, but in filter form i can select Sausage (but i shouldnt, because its product from another company).
For now it's all looks like this:
#View
def reviewsView(request):
context = {}
user = request.user
company = user.company
products_qset = ProductModel.objects.filter(company=company)
reviews_objects = ReviewModel.objects.filter(product__in=products_qset)
filter = ReviewFilter(request.GET, queryset=reviews_objects)
context['filter'] = filter
return render(request, 'companies/reviews.html', context)
#Filter
class ReviewFilter(django_filters.FilterSet):
class Meta:
model = ReviewModel
fields = [
'product',
'marketplace',
'operator',
'state'
]
#Template
<form action="" method="get">
{{ filter.form.as_p }}
<input type="submit" name="press me" id="">
</form>
<div class="review-list">
{% for i in filter %}
{{i.product}}, {{i.marketplace}} etc.
{% endfor %}
I've done quite a lot of research on django_filters docs and this question seems like duplicate, but i can't fully understand what and why is happening to init in this answer and how to correctly rewrike class ReviewFilter so filter instance would do something like this (in View):
filter = ReviewFilter(request.GET, queryset_to_dispplay=MyQueryset, queryset_to_display_filtering_options=MyQueryset). For now its surely happening because ReviewFilter Meta points to the all table (ReviewModel) objects, instead of filtered beforehands.
I also trying to apply pagination on this page (i cut this from question code for "shortness") and after i will be able to implement filtering i would like to merge those two somehow, but if what i want is not possible - please point me to the right direction (for example: 'you can do this by writing your very own filtering system using some js, no need to use django_filters' or 'with angular.js/view.js/somethingelse you can have it all from the box').

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

How to use sorl-thumbnail package together with django-tables2 package?

I do have a table defined in tables.py that renders a column with recipes images.
class ImageColumn(Column):
def render(self, value):
return format_html(
'<img src="static/media/{url}" height="150px", width="150px">',
url=value
)
class RecipeTable(tables.Table):
image = ImageColumn()
name = Column(linkify=True)
class Meta:
model = Recipe
template_name = "django_tables2/bootstrap4.html"
fields = (
"image",
"name",
"directions",
"ingredients",
)
Each image has different size and when I render it with fixed height="150px", width="150px", aspect ratio messes up the image. Therefore I thought I could use sorl-thumbnail package to help mi with generating thumbnails, rather then resizing the whole images. It looks like it is not possible to easily use both django-tables2 and sorl-thumbnail since thumbnails are rendered in html template. My template contains only this to render the table:
{% render_table table 'django_tables2/bootstrap4.html' %}
I need to access the cell so that I can use thumbnail template tag where image should be placed.
{% thumbnail item.image ‘200x100’ as im %}
<img src=’{{ im.url }}’>
{% endthumbnail %}
The only solution I see could be to edit the bootstrap4.html, but is there a better way? Am I missing something?

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?

How to select a specific related element in 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()