Как сделать добавление тэгов к статье в форме как на stackoverflow в Django
Сейчас я пытаюсь сделать добавление тегов в форме создания статьи на Django сайте. Вот что у меня есть сейчас:
Для модели тегов я использую в модели Article ManyToManyField.
views.py:
class AddArticle(LoginRequiredMixin, DataMixin, CreateView):
form_class = AddArticleForm
template_name = 'articles/add_article.html'
success_url = reverse_lazy('articles')
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
c_def = self.get_user_context(title='Создание статьи')
return dict(list(context.items()) + list(c_def.items()))
def form_valid(self, form):
obj = form.save(commit=False)
obj.username = self.request.user
obj.save()
return super().form_valid(form)
forms.py:
class AddArticleForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['tags'].empty_label = "Тэг не выбран"
class Meta:
model = Article
tags = forms.ModelMultipleChoiceField(queryset=Category.objects.all(), to_field_name='tags')
fields = ['title', 'cover_image', 'content', 'tags']
widgets = {'title': forms.TextInput(attrs={'class': 'form-control form-input form__input',
'placeholder': 'Введите название статьи'}),
'content': forms.Textarea(attrs={'class': 'form-control form-input form__input',
'placeholder': 'Введите текст статьи'}),
'cover_image': forms.FileInput(attrs={'class': 'form-control form-input form__file-btn'})}
models.py:
class Article(models.Model):
username = models.ForeignKey(AUTH_USER_MODEL, on_delete=models.PROTECT, verbose_name='Автор')
title = models.CharField(max_length=350, verbose_name='Заголовок')
cover_image = models.ImageField(upload_to='images/%Y/%m/%d/', blank=False, verbose_name='Обложка')
content = models.TextField(verbose_name='Текст')
create_time = models.DateTimeField(auto_now_add=True, verbose_name='Дата создания')
update_time = models.DateTimeField(auto_now=True, verbose_name='Дата изменения')
tags = models.ManyToManyField('Tag', verbose_name='Тэги')
views_count = models.IntegerField(null=False, default=0, verbose_name='Количество просмотров')
comments_count = models.IntegerField(null=False, default=0, verbose_name='Количество комментариев')
slug = models.SlugField(max_length=250, unique=True, db_index=True, verbose_name='URL')
is_published = models.BooleanField(default=False, auto_created=True, verbose_name='Опубликовано')
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('article', kwargs={'article_slug': self.slug})
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.title)
return super().save(*args, **kwargs)
class Meta:
verbose_name = 'Статья'
verbose_name_plural = 'Статьи'
class Tag(models.Model):
name = models.CharField(max_length=100, unique=True, db_index=True, verbose_name='Название')
category = models.ForeignKey('Category', on_delete=models.PROTECT, verbose_name='Категория')
slug = models.SlugField(max_length=200, unique=True, db_index=True, verbose_name='URL')
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('tag', kwargs={'tag_slug': self.slug})
class Meta:
verbose_name = 'Тэг'
verbose_name_plural = 'Тэги'
add_article.html:
{% block content %}
<section class="add-article">
<div class="container">
<div class="row d-flex justify-content-center">
<div class="col-lg-10 form-container">
<form class="form" method="post" enctype="multipart/form-data">
{% csrf_token %}
<div class="text-center form__errors">{{form.non_field_errors}}</div>
<div class="row">
{% for item in form %}
<div class="col-sm-4">
<label class="form__label" for="{{item.id_for_label}}">{{item.label}}: </label>
</div>
<div class="col-sm-8">
{{item}}
</div>
<div class="form__errors">{{item.errors}}</div>
{% endfor %}
</div>
<button class="form__btn btn" type="submit">Опубликовать статью</button>
</form>
</div>
</div>
</div>
</section>
{% endblock %}
Так вот в чём вопрос: как я могу сделать аналогичную систему добавления тегов как на stackoverflow? То есть мне нужна форма, в которой при нажатии на кнопку можно будет выбрать из списка нужный тег, а потом нажать второй раз и добавить второй и т. д.