Django CMS plugin switch between different templates - python

For example i have very simple news plugin
Part of models.py:
class SimpleNews(CMSPlugin):
image = models.ImageField()
title = models.CharField(max_length=20)
excerpt = models.CharField(max_length=50)
text = models.CharField(max_length=1000)
And two different templates, one for short news and one for full news:
Short:
<h1>{{ instance.title }}</h1>
<p>
{{ instance.excerpt|safe }}
</p>
Full:
<img src={{instance.image}}/>
<h1>{{ instance.title }}</h1>
<p>
{{ instance.text|safe }}
</p>
I need to switch between this templates depending on adress. How can i do that?

So, i find answer by myself.
Vewy useful link here https://stackoverflow.com/a/34804271/6198007.
If switching is slow you'll need to add
cache=False
in your plugin in cms_plugins.py, after that all should be fine.
Sorry for my english.

Related

Django show same content (of a model) in sidebar of every page (also in different apps)

I have two apps: blog and mysite.
In the project folder, I have a template which includes a sidebar template. This sidebar is shown on every page of the project (index pages, mysite pages, blog pages).
One part of this sidebar should show a list of the latest x blog entries (independent of the page where the user is).
blog/models.py
class Post(models.Model):
author = models.ForeignKey('auth.User', on_delete=models.CASCADE)
title = models.CharField(max_length=264)
text = RichTextField(config_name='detail_text_field', default='')
created_date = models.DateTimeField(default=timezone.now)
blog/views.py
class LatestBlogEntriesListView(ListView):
model = Post
template_name = 'blog/_latest_blog_entries_list.html'
def get_queryset(self):
return Post.objects.all().order_by('created_date')[-3:]
sidebar.html
<div class="row">
{% include 'blog/_latest_blog_entries_list.html' %}
</div>
_latest_blog_entries_list.html
<h4>Latest Blog Entries</h4>
{% for post in objects %}
{{ post.title }}
{% endfor %}
Unfortunately, this does not work. My sidebar only shows the h4 "Latest Blog Entries", but not the posts. How can I do this?
Any help is highly appreciated!
I found to use a context processor, as described in this post: https://dev.to/harveyhalwin/using-context-processor-in-django-to-create-dynamic-footer-45k4
This allows to access a context variable within all pages.
When using ListView the default object is called object_list. Try changing your code to this:
{% for post in object_list %}
{{ post.title }}
{% endfor %}
You can also change this variable name in the view, so that when you catch it on the template, it's a custom name.
class LatestBlogEntriesListView(ListView):
model = Post
template_name = 'blog/_latest_blog_entries_list.html'
context_object_name = "your_new_object_name"

How do I html format my blog post in django?

So I want to make a blog post with HTML formatting from the admin page directly. For example from the models.py, you see the description is a TextField. When I go to the admin page to make a blog post, I want to be able to add HTML tags to my blog. So the text field will have HTML content. While I call the blog post onto the HTML template I want it to read the description as a HTML file and not just a text field.
models.py
from django.db import models
class Blog(models.Model):
title = models.CharField(max_length=100)
description = models.TextField()
date = models.DateField()
Blog.description at admin page
<HTML>
<body>
<p>Welcome to my first blog post!!</p>
</body>
</html>
blog.html
<h1>{{ blog.title }}</h1>
<hr>
<p>{{ blog.description }}</p>
Any help is appreciated. Thanks!
You can render it with the |safe template filter [Django-doc]. This will disable escaping HTML fragments, and it will thus no longer convert < to < for example:
<h1>{{ blog.title|safe }}</h1>
<hr>
<p>{{ blog.description|safe }}</p>
You however might want to take a look at the django-ckeditor package [GitHub] which offers a dedicated field, widget, etc. to enable editing the text with respect to rendering.

Text area not reading HTML

I have Django´s Blog APP installed, all working fine, but I need to add posts (via admin) with HTML in the post content field, now, the text area can only read plain text (it doesn´t render HTML).
This is the field:
(models.py)
content = models.TextField()
This is the HTML for this field:
<h6 class="card-text" ><small>{{post.content|slice:":500" |linebreaks |safe}}</small></h6>
Question is: are there special configs for Django/Python in order for the field to render HTML?
The safe tag should already do that... have you tried this:
{% autoescape off %}
{{ post.content }}
{% endautoescape %}
https://code.djangoproject.com/wiki/AutoEscaping
Hope this helps!

Django: best way to handle foreign key requests in template pages

Suppose you are making a site to simply list your products.
You want to upload an unspecified number of pictures for your each of your products. So you, following Django's many-to-one documentation, make two models:
# files stored under my_app/static/my_app/product_images/product_<id>/<img_name>
def product_img_dir_path(instance, filename):
return 'my_app/static/my_app/product_images/product_{0}/{1}'.format(instance.product.id, filename)
class Product(models.Model):
name = models.CharField ...
... # other attributes of the product, e.g. price, etc
class ProductImage(models.Model):
product = models.ForeignKey("Product", on_delete=models.CASCADE)
image = models.ImageField(upload_to=product_img_dir_path)
Now if I want all of the images for say product 1, I can retrieve them using:
ProductImages.objects.filter(product__pk=1)
My question starts here.
Suppose you want an index page which just shows the listings for all of your products and for simplicity, the first image associated with each product.
You make a template page with
{% for product in product list %}
<div class="product-listing" style="display:inline">
<!-- image for product goes here -->
<!-- brief description goes here -->
</div>
{% endfor %}
where product_list was passed in your context:
# inside /my_app/views.py
def index(request):
...
context = {"product_list": Product.objects.all()}
...
Question: what is the best way to also have access to the images for displaying the images in the template page?
Currently I thought constructing a parallel image list would suffice:
# inside /my_app/views.py
def index(request):
...
product_list = Product.objects.all()
image_list = [product.productimage_set.all()[0] for product in product_list]
context = {"product_list": product_list, "image_list": image_list}
...
and then somehow using the forloop counter to get the corresponding image for the product.
e.g.
{% for product in product list %}
<div class="product-listing" style="display:inline">
<img src="{{ image_list[<forloop counter>].image.url }}" />
<!-- brief description goes here -->
</div>
{% endfor %}
Is there a better way to do this?
As long as you can access product.productimage_set, you can try to iterate it in your template and do not pass it as a view context.
In your Django template:
{% for product in product_list %}
<div class="product-listing" style="display:inline">
{% for product_image in product.productimage_set.all %}
<img src="{{ product_image.image.url }}" />
<!-- brief description goes here -->
{% endfor %}
</div>
{% endfor %}
I think that it will be easier for you to solve this if you simplify your design by moving the images to your Product model.
If you want to save the path to an image it will be easier to use CharField, but if you want to save many paths why not using JSONField?
My suggestion look like this:
class Product(models.Model):
name = models.CharField(null=True, blank=True)
main_image = models.CharField(null=True, blank=True) # Optional
images = JSONField(null=True, blank=True)

How can I get all users images in template,django

So , I'm trying to write blog in Django and now I have problem with comments.
Below each post I have users comments , with comment author name , image and comment.
Comments class:
class Comments(models.Model):
body = models.TextField()
author = models.ForeignKey(User, related_name= 'upser')
image = models.OneToOneField(UserProfile , related_name='im')
timestamp = models.DateTimeField(auto_now=True)
post = models.ForeignKey(Post, related_name='comments')
class Meta:
ordering = ('-timestamp',)
class UserProfile(models.Model):
user = models.OneToOneField(User, related_name='oser')
picture = models.ImageField(upload_to='profile_images', blank=True)
def __unicode__(self):
return self.user
So , I have comments class connected with UserProfile class in which I have user's image.
That's what I have in template to display all comments:
{% for comment in comments %}
<li>
<div class="media" style="margin-top: 10px">
<a class="pull-left" href="#">
<img class="media-object" src={{ MEDIA_ROOT }}/{{ PLACE FOR USER'S PICTURE }} alt="" width="80px" height="80px" >
</a>
<div class="media-body">
<h4 class="media-heading">{{ comment.author}}
<small>{{ comment.timestamp }}</small>
</h4>
{{ comment.body }}
</div>
</div>
</li>
{% endfor %}
And question ,how can I access user image from template if I have Comments object there?
I don't know why you need the image attribute that is a foreign key to the UserProfile model.
You can just do that in the template:
{{comment.author.oser.picture.url}}
This does the following:
Get the comment, get its author, go to its "oser" attribute which is the corresponding UserProfile and then get the picture attribute's image url.
Hope that helps.
Your model looks somewhat strange to me, or it doesn't fit so much your description:
you have a "Comments" class (shouldn't it be "Comment", as it contains a single comment?) which has a body, author, timestamp, the post it belongs to... fine. But the field you named "image" is actually the user_profile, right? Also, a OneToOneField would imply a 1 to 1 relationship between a Comment(s) object and a UserProfile... most probably not what you want!
Actually you have the author already, so that is enough to get the picture... so author is a user -> user_profile -> picture. Or do i understand your Model & question incorrectly?

Categories

Resources