Как в поле ManyToMany отобразить только те записи, у которых category = выбранной категории в Django
Вкратце: я хочу сделать так, чтобы внутри админ формы и пользовательской формы на сайте человек вначале выбирал категорию статьи, а в следующем поле ему отображались на выбор только те теги статьи, у которых поле category равно выбранному ранее. Как я могу сделать это (либо же стоит ли мне изменять структуру моих моделей)?
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=True, verbose_name='Обложка')
content = RichTextUploadingField(verbose_name='Текст')
create_time = models.DateTimeField(auto_now_add=True, verbose_name='Дата создания')
update_time = models.DateTimeField(auto_now=True, verbose_name='Дата изменения')
category = models.ForeignKey('Category', on_delete=models.PROTECT, verbose_name='Категория')
tags = models.ManyToManyField('Tag', verbose_name='Тэги')
views_count = models.IntegerField(null=True, blank=True, default=0, verbose_name='Количество просмотров')
comments_count = models.IntegerField(null=False, blank=True, default=0, verbose_name='Количество комментариев')
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_id': self.pk})
class Meta:
verbose_name = 'Статья'
verbose_name_plural = 'Статьи'
class Tag(models.Model):
name = models.CharField(max_length=100, unique=True, db_index=True, verbose_name='Название')
description = models.TextField(blank=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 = 'Тэги'
class Category(models.Model):
name = models.CharField(max_length=100, unique=True, db_index=True, verbose_name='Название')
description = models.TextField(blank=True, 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('category', kwargs={'category_slug': self.slug})
class Meta:
verbose_name = 'Категория'
verbose_name_plural = 'Категории'
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['category'].empty_label = "Категория не выбрана"
class Meta:
model = Article
category = forms.ModelChoiceField(queryset=Category.objects.all(), to_field_name='category')
fields = ['title', 'cover_image', 'content', 'category', 'tags']
widgets = {'title': forms.TextInput(attrs={'class': 'form-control form-input form__input',
'placeholder': 'Введите название статьи'}),
'content': CKEditorUploadingWidget(attrs={'class': 'form-control form-input form__input add-article-form__textarea',
'placeholder': 'Введите текст статьи'}),
'cover_image': forms.FileInput(attrs={'class': 'form-control form-input form__file-btn'}),
'tags': forms.CheckboxSelectMultiple(attrs={'class': 'form__checkbox'})}