Множественный выбор Django продолжает выдавать недопустимое значение - PullRequest
0 голосов
/ 26 мая 2020

Я хочу иметь возможность выбирать несколько категорий при создании сообщения в блоге. Я могу сделать это без проблем на Django admin, но я не могу сделать это с помощью формы bootstrap.

У меня есть форма bootstrap, в которой пользователь сможет увидеть список категории, имеющиеся в базе. Я могу показать значения в раскрывающемся меню, и я могу выбрать несколько категорий, но когда я нажимаю на сообщение, он продолжает говорить {category} is not a valid value.

Я пробовал save_m2m(), но это тоже не сработало. Сообщение может иметь несколько категорий, а в категории может быть несколько сообщений. Я не могу понять, в моей модели или форме или в самом файле html.

models.py

class Category(models.Model):
    category_name = models.CharField(max_length=255)
    slug = models.SlugField(blank=True, unique=True)
    date_created = models.DateTimeField(auto_now_add=True, verbose_name='date created')
    date_updated = models.DateTimeField(auto_now=True, verbose_name='date updated')

    class Meta:
        verbose_name_plural = 'categories'

    def __str__(self):
        return self.category_name

class BlogPost(models.Model):
    STATUS = (
        ('draft', 'Draft'),
        ('published', 'Published'),
    )

    title = models.CharField(max_length=500, null=False, blank=False)
    body = models.TextField(max_length=5000, null=False, blank=False)
    image = models.ImageField(upload_to=upload_location, null=False, blank=False)
    date_published = models.DateTimeField(auto_now_add=True, verbose_name='date published')
    date_updated = models.DateTimeField(auto_now=True, verbose_name='date updated')
    author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    slug = models.SlugField(blank=True, unique=True)
    category = models.ManyToManyField(Category)
    status = models.CharField(max_length=10, choices=STATUS, default='draft')

    def __str__(self):
        return self.title

forms.py

class CreateBlogPostForm(forms.ModelForm):

    class Meta:
        model = BlogPost
        fields = ['title', 'body', 'image', 'category', 'status']

views.py

def create_blog_view(request):
    context = {}

    user = request.user
    categories = Category.objects.all
    statuses = BlogPost.STATUS

    if not user.is_authenticated:
        return redirect('login')

    form = CreateBlogPostForm(request.POST or None, request.FILES or None)

    if form.is_valid():
        obj = form.save(commit=False)
        author = Account.objects.filter(username=user.username).first()
        obj.author = author
        obj.save()
        form = CreateBlogPostForm()

    context['form'] = form
    context['categories'] = categories
    context['statuses'] = statuses

    return render(request, 'my_simple_blog/create-blog.html', context)

create-blog.html

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

                        <!-- title -->
                        <!-- body -->
                        <!-- image -->


                        <!-- category -->
                        <div class="form-group">
                            <label for="id_category">Category</label>
                            <select multiple class="form-control" id="id_category" name="category">
                                {% for category in categories %}
                                    <option value="{{ category.id }}">{{ category }}</option>
                                {% endfor %}
                            </select>
                        </div>

                        <!-- status -->
                        <div class="form-group">
                            <label for="id_status">Status</label>
                            <select class="form-control" id="id_status" name="status">
                                {% for val, name in statuses %}
                                    <option value="{{ val }}">{{ name }}</option>
                                {% endfor %}
                            </select>
                        </div>

                        {% for field in form %}
                            <p>{% for error in field.errors %}
                                <p style="color: red;">{{ error }}</p>
                            {% endfor %}
                            </p>
                        {% endfor %}

                        {% if form.non_field_errors %}
                            <div style="color:red;">
                                <p>{{ form.non_field_errors }}</p>
                            </div>
                        {% endif %}

                        <!-- Submit btn -->
                        <button class="submit-button btn btn-lg btn-primary btn-block" type="submit">POST</button>
                    </form>

ОБНОВЛЕНИЕ: я заставил его работать до такой степени, что я могу выбрать несколько и создать сообщение, отправив идентификатор категории в качестве значения опции множественного выбора. Но этот выбор не отражается в Django Admin.

1 Ответ

0 голосов
/ 27 мая 2020

Решение оказалось очень простым, django -crispy-forms.

После того, как я добавил необходимые настройки в settings.py

, я обновил свой create-blog.html :

{% load crispy_forms_filters %}

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

                        {{ form | crispy }}

                        {% for field in form %}
                            <p>{% for error in field.errors %}
                                <p style="color: red;">{{ error }}</p>
                            {% endfor %}
                            </p>
                        {% endfor %}

                        {% if form.non_field_errors %}
                            <div style="color:red;">
                                <p>{{ form.non_field_errors }}</p>
                            </div>
                        {% endif %}

                        <!-- Submit btn -->
                        <button class="submit-button btn btn-lg btn-primary btn-block" type="submit">POST</button>
                    </form>

Убедитесь, что вы загрузили crispy_forms_filters в верхней части файла.

В моем views.py я должен использовать save_m2m, так как я использовал obj.save(commit=False).

def create_blog_view(request):
    context = {}

    user = request.user
    categories = Category.objects.all
    statuses = BlogPost.STATUS

    if not user.is_authenticated:
        return redirect('login')

    form = CreateBlogPostForm(request.POST or None, request.FILES or None)

    if form.is_valid():
        obj = form.save(commit=False)
        author = Account.objects.filter(username=user.username).first()
        obj.author = author
        obj.save()
        form.save_m2m()
        form = CreateBlogPostForm()

    context['form'] = form
    context['categories'] = categories
    context['statuses'] = statuses

    return render(request, 'my_simple_blog/create-blog.html', context)

И вы должны иметь возможность выполнять множественный выбор, и выбор будет отражено в Django Админ.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...