Как отобразить набор тегов в шаблоне django
Я пытаюсь вывести теги из отношения "многие ко многим", но мне чего-то не хватает
Вот мои модели:
class Post(models.Model):
date = models.DateTimeField(auto_now_add=True)
author = models.ForeignKey(Author, on_delete=models.CASCADE, related_name='posts', null=True, blank=True)
title = models.CharField(max_length=200)
content = models.TextField(null=True, blank=True)
image = models.ImageField(upload_to='post/images/', null=True, blank=True)
slug = models.SlugField(max_length=200, unique=True, null=True, blank=True)
tag = models.ManyToManyField('Tag', related_name='posts', blank=True)
def save(self, *args, **kwargs):
if self.image:
ext = os.path.splitext(self.image.name)[1]
filename = f"{datetime.now().strftime('%Y%m%d%H%M%S')}{ext}"
self.image.name = filename
if not self.slug:
self.slug = slugify(self.title)
return super().save(*args, **kwargs)
class Tag(models.Model):
name = models.CharField(max_length=200)
slug = models.SlugField(max_length=200, unique=True, blank=True)
post = models.ManyToManyField(Post, related_name='tags', blank=True)
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.name)
return super().save(*args, **kwargs)
def __str__(self):
return self.name
Это мой фрагмент шаблона
{% for post in posts %}
<div class="news-card">
<img src="{{post.image.url}}" class="news-img" alt="News" />
<div class="news-listing">
<ul class="tags">
{% for tag in post.tag.all %}
<li class="tag">{{tag.name}}</li>
{% endfor %}
</ul>
<h3 class="news-title">
<a href="{{post.slug}}"
>{{post.title}}</a
это мой вид и контекст, который я передаю
form = MessageForm()
context = {
'posts': posts,
'events': events,
'introductorys': introductory,
'products': products,
'form': form,
'authors': 'authors',
}
return render(request, 'app/index.html', context)
Я ожидаю, что будет сгенерирован список тегов, но шаблон не генерирует никаких тегов
Вы дублируете теги ManyToManyField
: вы делаете один в первой модели и один во второй. Это означает, что таким образом существуют два отношения, и добавление Post
к одному тегу не приведет к появлению второго.
You thus should merge the two ManyToManyField
s in one. It is not necessary to make a second one: with related_name=…
[Django-doc] you add a descriptor in the other to access the objects in the opposite way.
Например, мы можем использовать:
class Post(models.Model):
def post_image_filename(self, filename):
ext = os.path.splitext(self.image.name)[1]
filename = f"post/images/{datetime.now().strftime('%Y%m%d%H%M%S')}{ext}"
date = models.DateTimeField(auto_now_add=True)
author = models.ForeignKey(
Author,
on_delete=models.CASCADE,
related_name='posts',
null=True,
blank=True,
)
title = models.CharField(max_length=200)
content = models.TextField(null=True, blank=True)
image = models.ImageField(
upload_to=post_image_filename, null=True, blank=True
)
slug = models.SlugField(max_length=200, unique=True, null=True, blank=True)
tags = models.ManyToManyField('Tag', related_name='posts', blank=True)
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.title)
return super().save(*args, **kwargs)
class Tag(models.Model):
name = models.CharField(max_length=200)
slug = models.SlugField(max_length=200, unique=True, blank=True)
# no post
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.name)
return super().save(*args, **kwargs)
def __str__(self):
return self.name
Таким образом, мы работаем с:
<ul class="tags">
{% for tag in post.tags.all %}
<li class="tag">{{ tag.name }}</li>
{% endfor %}
</ul>
Note: You can make use of
django-autoslug
[GitHub] to automatically create a slug based on other field(s).