博客文章创建过程中表单的异常行为

时间:2019-07-07 18:00:34

标签: django bootstrap-4 django-forms django-templates django-2.2

我正在开发个人博客的后端,并使用this tutorial作为日期和时间,以创建用于创建博客文章的表单。

即使我选择一个或多个标签,也不会将其添加到帖子中。使用此表单发布后的帖子没有标签。但是,如果我通过django admin做同样的事情,我将无法创建没有标签的帖子。

create_post.html

  <form class="" method="POST" enctype="multipart/form-data" novalidate>{% csrf_token %}

    <div class="form-group">

      <div class="row">
        <div class="col-sm-9">

          <div class="form-group mb-4">
            <div>{{ form.title }}</div>
            <label for="id_title">
              <span class="text-info" data-toggle="tooltip" title="{{ form.title.help_text }}">
                <i class="far fa-question-circle"></i>
              </span>
              <small class="text-danger">{{ form.title.errors }}</small>
            </label>
          </div>

          <div class="form-group mb-4">
            <div>{{ form.description }}</div>
            <label for="id_description">
              <span class="text-info" data-toggle="tooltip" data-placement="bottom" title="{{ form.description.help_text }}">
                <i class="far fa-question-circle"></i>
              </span>
              <small class="text-danger">{{ form.description.errors }}</small>
            </label>
          </div>

          <div class="form-group mb-4">
            <div>{{ form.contents }}</div>
            <label for="id_contents">
              <span class="text-info" data-toggle="tooltip" data-placement="bottom" title="{{ form.contents.help_text }}">
                <i class="far fa-question-circle"></i>
              </span>
              <small class="text-danger">{{ form.contents.errors }}</small>
            </label>
          </div>

          <div class="form-group mb-4">
            <div>{{ form.header_image_link }}</div>
            <label for="id_header_image">
              <span class="text-info" data-toggle="tooltip" title="{{ form.header_image_link.help_text|safe }}">
                <i class="far fa-question-circle"></i>
              </span>
              <small class="text-danger">{{ form.header_image_link.errors }}</small>
            </label>
          </div>

        </div>
        <div class="col-sm-3">

          <div class="form-group mb-4">
            <div class=""><h4>{{ form.post_category.label }}</h4></div>
            <div>{{ form.post_category }}</div>
            <label for="id_category">
              <span class="text-info" data-toggle="tooltip" title="{{ form.post_category.help_text }}">
                <i class="far fa-question-circle"></i>
              </span>
              <small class="text-danger">{{ form.post_category.errors }}</small>
            </label>
          </div>

          <div class="form-group mb-4">
            <div class=""><h4>{{ form.post_tag.label }}</h4></div>
            <div>{{ form.post_tag }}</div>
            <label for="id_tag">
              <span class="text-info" data-toggle="tooltip" title="{{ form.post_tag.help_text }}">
                <i class="far fa-question-circle"></i>
              </span>
              <small class="text-danger">{{ form.post_tag.errors }}</small>
            </label>
          </div>

          <div class="form-inline mb-4 py-0">
            <div class="input-group mx-1">
              <label for="id_highlighted">{{ form.highlighted.label }}</label>
              <div class="ml-1">{{ form.highlighted }}</div>
            </div>

            <div class="input-group mx-1">
              <label for="id_draft">{{ form.draft.label }}</label>
              <div class="ml-1">{{ form.draft }}</div>
            </div>
          </div>

          <div class="form-group mb-4">
            <div class=""><h4>{{ form.publishing_date.label }}</h4></div>
            <div class="input-group date" data-target-input="nearest">
              {{ form.publishing_date }}
              <div class="input-group-append" data-target="#publishing_date_field" data-toggle="datetimepicker">
                <div class="input-group-text"><i class="fa fa-calendar"></i></div>
              </div>
            </div>
            <label for="publishing_date_field">
              <span class="text-info" data-toggle="tooltip" title="{{ form.publishing_date.help_text }}">
                <i class="far fa-question-circle"></i>
              </span>
              <small class="text-danger">{{ form.publishing_date.errors }}</small>
            </label>

            <script>
              $(function () {
                $("#publishing_date_field").datetimepicker({
                  format: 'DD/MM/YYYY HH:mm',
                });
              });
            </script>
          </div>

          <div class="form-group mb-4">
            <div class=""><h4>{{ form.author.label }}</h4></div>
            <div>{{ form.author }}</div>
            <label for="id_author">
              <span class="text-info" data-toggle="tooltip" title="{{ form.author.help_text }}">
                <i class="far fa-question-circle"></i>
              </span>
              <small class="text-danger">{{ form.author.errors }}</small>
            </label>
          </div>

        </div>

      </div>
    </div>

    <hr>

    <div class="row justify-content-md-center">
      <div class="col-md-auto">
        <input type="submit" class="btn btn-info shadow" value="Pubblica">
      </div>
    </div>

  </form>

forms.py

class BlogPostForm(forms.ModelForm):
    title = forms.CharField(
        max_length=70,
        help_text="<small>Write post title here. The title must be have max 70 characters.</small>",
        widget=forms.TextInput(
                            attrs={
                                "placeholder": "Titolo",
                                "type": "text",
                                "id": "id_title",
                                "class": "form-control form-control-lg",
                                }
                            ),
        )
    description = forms.CharField(
        max_length=200,
        help_text="<small>Write a post short description here. The description must be have max 200 characters.</small>",
        widget=forms.Textarea(
                            attrs={
                                "placeholder": "Descrizione",
                                "type": "text",
                                "id": "id_description",
                                "class": "form-control",
                                "rows": "2",
                                }
                        ),
        )
    contents = forms.CharField(
        help_text="<small>Write your contents here.</small>",
        widget=forms.Textarea(
                            attrs={
                            "placeholder": "Contenuti",
                            "type": "text",
                            "id": "id_contents",
                            "class": "form-control",
                            "rows": "20",
                            }
                        ),
        )
    publishing_date = forms.DateTimeField(
            input_formats=['%d/%m/%Y %H:%M'],
            label="Data di pubblicazione",
            help_text="<small>Write data and hour of publication. You can use also a past or a future date.</small>",
            widget=forms.DateTimeInput(
                                attrs={
                                    "id": "publishing_date_field",
                                    'class': 'form-control datetimepicker-input',
                                    'data-target': '#publishing_date_field',
                                }
                            ),
        )
    draft = forms.BooleanField(
        label="Bozza",
        widget=forms.CheckboxInput(
                            attrs={
                                "type": "checkbox",
                                "id": "id_draft",
                                "class": "form-check-input mx-2",
                                }
                        ),
        required=False,
        )    
    author = forms.ModelChoiceField(
        label="Autore",
        help_text="<small>Select the author.</small>",
        widget= forms.Select(
            attrs={
                "id": "id_author",
                "class": "custom-select",
                }
            ),
        empty_label="   ",
        queryset= User.objects.all(),
        )
    post_tag =forms.ModelMultipleChoiceField(
        label="Tag",
        help_text="<small>Select one or more tags. Press CTRL and click on a tag for multiple selection.</small>",
        widget= forms.SelectMultiple(
            attrs={
                "id": "id_category",
                "class": "custom-select",
                "size": "4",
                }
            ),
        queryset= BlogTag.objects.all(),
        )
    post_category = forms.ModelChoiceField(
        label="Categoria",
        help_text="<small>Select a category.</small>",
        widget= forms.Select(
            attrs={
                "id": "id_category",
                "class": "custom-select",
                }
            ),
        empty_label="   ",
        queryset= BlogCategory.objects.all(),
        )
    header_image_link = forms.CharField(
                        max_length=1000,
                        help_text="<small>Past here the image link.</small>",
                        widget=forms.TextInput(
                                attrs={
                                    "placeholder": "Url dell'immagine di testata",
                                    "type": "text",
                                    "id": "id_header_image",
                                    "class": "form-control",
                                }
                            )
                        )
    highlighted = forms.BooleanField(
                        label="In evidenza",
                        widget=forms.CheckboxInput(
                                            attrs={
                                                "type": "checkbox",
                                                "id": "id_highlighted",
                                                "class": "form-check-input mx-2",
                                                }
                                        ),
                        required=False,
                        )

    class Meta:
        model = BlogPost
        fields = [
                "author",
                "title",
                "description",
                "contents",
                "header_image_link",
                "post_tag",
                "post_category",
                "highlighted",
                "draft",
                "publishing_date",
                ]

models.py

class BlogPost(models.Model):
    publishing_date = models.DateTimeField(
        default=timezone.now,
        blank=True,
        )
    updating_date = models.DateTimeField(
        auto_now=True,
        )
    timestamp = models.DateTimeField(
        auto_now=False,
        auto_now_add=True,
        )
    title = models.CharField(
        max_length=70,
        unique=True,
        )
    slug_post = models.SlugField(
        max_length=70,
        unique=True,
        )
    description = models.TextField(
        max_length=200,
        blank=True,
        )
    contents = models.TextField(
        blank=True,
        )
    draft = models.BooleanField(
        default=False,
        )
    author = models.ForeignKey(
        User,
        related_name = "author_blogpost",
        on_delete=models.CASCADE,
        )
    highlighted = models.BooleanField(
        default=False,
        )
    header_image_link = models.CharField(
        max_length=1000,
        )
    post_category = models.ForeignKey(
        BlogCategory,
        related_name = "category_blogpost",
        on_delete=models.CASCADE,
        )
    post_tag = models.ManyToManyField(
        BlogTag,
        related_name = "tag_blogpost",
        )

    def __str__(self):
        return self.title

    class Meta:
        ordering = ['-publishing_date'] 

views.py

def createPost(request):
    if request.method == "POST":
        form = BlogPostForm(request.POST or None)
        if form.is_valid():
            new_post = form.save(commit=False)
            new_post.slug_post = slugify(new_post.title)
            new_post.save()
            return redirect('blogpost_list')
    else:
        form = BlogPostForm()
    context = {
        'form': form,
        }
    template = 'blog/editing/create_post.html'
    return render(request, template, context)

def updatePost(request, slug_post=None):
    update_post = get_object_or_404(BlogPost, slug_post=slug_post)
    form = BlogPostForm(request.POST or None, instance=update_post)
    if form.is_valid():
        update_post = form.save(commit=False)
        update_post.slug_post = slugify(update_post.title)
        update_post.save()
        return redirect('blogpost_list')

    context = {
        'form': form,
        }
    template = 'blog/editing/create_post.html'
    return render(request, template, context)

我怎么了?

1 个答案:

答案 0 :(得分:1)

许多关系必须手动设置。您可以覆盖ModelForm的save方法,这意味着您永远不能使用“ commit = False”

def save(self, commit=True):
    if not commit:
        raise Exception('Cannot save many to many fields if the blog post is not committed')
    instance = super().save()
    instance.post_tag.add(*self.cleaned_data['post_tag'])
    return instance

或者您可以在视图中添加标签

if form.is_valid():
    update_post = form.save(commit=False)
    update_post.slug_post = slugify(update_post.title)
    update_post.save()
    update_post.post_tag.add(*form.cleaned_data['post_tag'])
    return redirect('blogpost_list')