Как в поле 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'})}
Вернуться на верх