Django: измените выбор выбора из FK в форме, связанной с представлением обновлений

#django #django-forms

#django #django-forms

Вопрос:

Тема потока модели -> Раздел -> Статья.

Я создаю представление обновления для своего проекта часто задаваемых вопросов, чтобы обновить уже созданные статьи. Я хочу, чтобы форма предоставляла выбор разделов на основе темы, под которой была создана статья. Поскольку у меня уже есть статьи, переданные PK по URL, я надеялся использовать его, чтобы вернуться к теме при создании моего фильтра. Я получаю object has no attribute ‘section’ ошибку, когда шаблон пытается отобразить форму в строке self.fields['section'].queryset = Section.objects.filter(topic_id=self.section.topic.id) в UpdateAriticleForm. Мне нужна помощь, чтобы разобраться с моим фильтром запросов.

URL-адрес:

 url(r'^ironfaq/article/update/(?P<pk>d )/$', ArticleUpdateView.as_view()),
  

Форма:

 from django import forms
from .models import Topic, Section, Article

class CreateArticleForm(forms.ModelForm):

    section = forms.ModelChoiceField(queryset=Section.objects.none())

    def __init__(self, *args, **kwargs):
        topic_pk = kwargs.pop('topic_pk')
        super(CreateArticleForm, self).__init__(*args, **kwargs)
        self.fields['section'].queryset = Section.objects.filter(topic_id=topic_pk)

    class Meta:
        model = Article
        widgets = {
            'answer': forms.Textarea(attrs={'data-provide': 'markdown', 'data-iconlibrary': 'fa'}),
        }
        fields = ('title','section','answer')

class UpdateArticleForm(forms.ModelForm):

    section = forms.ModelChoiceField(queryset=Section.objects.none())

def __init__(self, *args, **kwargs):
    super(UpdateArticleForm, self).__init__(*args, **kwargs)
    self.fields['section'].queryset = Section.objects.filter(topic_id=self.section.topic.id)

    class Meta:
        model = Article
        widgets = {
            'answer': forms.Textarea(attrs={'data-provide': 'markdown', 'data-iconlibrary': 'fa'}),
        }
        fields = ('title','section','answer')
  

Представление:

 class ArticleUpdateView(UpdateView):
    model = Article
    form_class = UpdateArticleForm
    template_name = "faq/form_create.html"

    def form_valid(self, form):
        article = form.save(commit=False)
        article.activity_user = self.request.user.username
        article.activity_date = datetime.datetime.now()
        article.save()
        self.success_url = "/ironfaq/%s/%s/%d" % (article.section.topic.slug,article.section.slug,article.id)
        return super(ArticleUpdateView,self).form_valid(form)
  

Модели:

 class Topic(Audit):
    name = models.CharField(max_length=255)
    icon = models.CharField(max_length=25,blank=True,null=True)
    sort = models.SmallIntegerField()
    slug = models.SlugField()

    class Meta:
        verbose_name_plural = "topics"

    def __str__(self):
        return self.name

class Section(Audit):
    name = models.CharField(max_length=255)
    sort = models.SmallIntegerField()
    slug = models.SlugField()
    topic = models.ForeignKey(Topic,on_delete=models.CASCADE)

    class Meta:
        verbose_name_plural = "sections"

    def __str__(self):
        return self.name

class Article(Audit):
    title = models.CharField(max_length=255)
    sort = models.SmallIntegerField()
    slug = models.SlugField()
    section = models.ForeignKey(Section,on_delete=models.CASCADE)
    answer = models.TextField()
    vote_up = models.IntegerField(default=0)
    vote_down = models.IntegerField(default=0)
    view_count = models.IntegerField(default=0)

    class Meta:
        verbose_name_plural = "articles"

    def __str__(self):
        return self.title
  

Ответ №1:

Ответом на эту проблему была не передача 'pk' в качестве аргумента форме и добавление get_form_kwargs в представление, чтобы форма могла видеть 'pk' переданные в URL.

Форма:

 class UpdateArticleForm(forms.ModelForm):

    section = forms.ModelChoiceField(queryset=Article.objects.none())

    def __init__(self, pk, *args, **kwargs):
        super(UpdateArticleForm, self).__init__(*args, **kwargs)
        self.fields['section'].queryset = Section.objects.filter(topic_id__exact=Article.objects.filter(id=pk).first().section.topic.id)
  

Вид:

 class ArticleUpdateView(UpdateView):
    model = Article
    form_class = UpdateArticleForm
    template_name = "faq/form_create.html"

    def get_form_kwargs(self):
        kwargs = super(ArticleUpdateView,self).get_form_kwargs()
        kwargs.update(self.kwargs)
        return kwargs

    def form_valid(self, form):
        article = form.save(commit=False)
        article.activity_user = self.request.user.username
        article.activity_date = datetime.datetime.now()
        article.save()
        self.success_url = "/ironfaq/%s/%s/%d" % (article.section.topic.slug,article.section.slug,article.id)
        return super(ArticleUpdateView,self).form_valid(form)