如何从表格中的ManaToManyField获取数据到Django视图?

时间:2018-08-01 10:19:23

标签: python django django-models django-forms django-views

models.py

class Posts(models.Model):
   """model for CreatePost"""
   author = models.CharField(max_length=100, null=False, blank=False)

   blog_title = models.CharField(max_length=100, null=False, blank=False)

   sub_catagory = models.ManyToManyField('SubCatagory')

   post_cover_image = models.ImageField(upload_to='post_cover_images', null=False, blank=False)

   post_discription = HTMLField(max_length=5000, null=False, blank=False, help_text='Enter the detailed post in max. 5000 characters')

   date_published = models.DateField(null=False, blank=False)

class Catagory(models.Model):
   """model for Catagory"""
   name = models.CharField(max_length=150, help_text='Enter a ctagory for blogpost')

class SubCatagory(models.Model):
   """model for subcatagories"""
   catagory = models.ForeignKey('Catagory', on_delete=models.CASCADE)
   sub_catagory_name = models.CharField(max_length=150, help_text='Enter subcatagory')

forms.py

class PostCreationForm(forms.ModelForm):
    class Meta:
        model = Posts
        fields = ('blog_title', 'sub_catagory', 'post_cover_image', 'post_discription')

views.py

@login_required
def createpost(request):
    if request.method=="POST":
        PostForm = PostCreationForm(request.POST, request.FILES)

        if PostForm.is_valid():

            postcont = Posts()

            if request.user.is_authenticated:
                postcont.blog_title = PostForm.cleaned_data['blog_title']
                postcont.post_cover_image = PostForm.cleaned_data['post_cover_image']
                postcont.post_discription = PostForm.cleaned_data['post_discription']
                postcont.author = request.user.username
                postcont.sub_catagory = PostForm.cleaned_data['sub_catagory']
                postcont.date_published = datetime.date.today()
                postcont.save()

                return HttpResponseRedirect(reverse('postcreationsuccessful'))
            else:
                return HttpResponseRedirect(reverse('createpost'))

    else:
        PostForm = PostCreationForm()

    return render(request, 'createpost.html', {'PostForm':PostForm})

模板

{% extends "base_generic.html" %}

{% block title %}<title>Create Post</title>{% endblock %}

{% block content %}
    <div class="container-fluid">
        <div class="row w-100">
            <div class="col-md-3">

            </div>
            <div class="col-md-6 shadow-sm p-3 mb-5 bg-white rounded">
                <form method="POST" enctype="multipart/form-data" action="{% url 'createpost' %}">{% csrf_token %}
                    <div class="row">
                        {% load bootstrap %}
                        <div class="col-md-12">
                            {{ PostForm.blog_title|bootstrap }}
                        </div>
                        <div class="col-md-12">
                            {{ PostForm.post_cover_image|bootstrap }}
                        </div>
                        <div class="col-md-12">
                            {{ PostForm.sub_catagory|bootstrap }}
                        </div>
                        <div class="col-md-12">
                            {{ PostForm.post_discription }}
                        </div>
                        <div class="col-md-12">
                            <input type="submit" value="Post">
                        </div>
                    </div>
                </form>
            </div>

            <div class="col-md-3">

            </div>
        </div>
    </div>
 {% endblock %}

我的问题是我在Posts和SubCatagory中有很多关系。作为子类别可以有很多职位。我想获取用户选择的类别,并希望使用views.py函数将其保存在模型中。

我想问一下我该怎么做。当我尝试这样做时:

postcont.sub_catagory = PostForm.cleaned_data ['sub_catagory']

我收到以下错误:

在/ posts / createpost /中的

TypeError   禁止直接分配给多对多集的前端。请改用sub_catagory.set()。

任何人都请帮忙!

1 个答案:

答案 0 :(得分:1)

就像错误所言,问题出在这一行:

postcont.sub_catagory = PostForm.cleaned_data['sub_catagory']

sub_categoryManyToManyField,因此不能直接将其设置为对象。您可以使用postcont.sub_category.set(PostForm.cleaned_data['sub_category']),但这仍然不是很优雅。

您的视图实际上不必将所有字段都修补到对象。我们可以让表单完成工作:

@login_required
def createpost(request):
    if request.method=="POST":
        post_form = PostCreationForm(request.POST, request.FILES)

        if post_form.is_valid():
            post_form.instance.auther = request.user.username
            postcont.instance.date_published = datetime.date.today()
            post_form.save()
            return redirect('postcreationsuccessful')
    else:
        post_form = PostCreationForm()

    return render(request, 'createpost.html', {'PostForm': post_form})

一些补充说明:

  1. if request.user.is_authenticated没用,因为@login_required装饰器已经检查了这一点;
  2. 如果authorUser,则最好在此处使用ForeignKey(User, ...)
  3. 您可以在date_published = models.DateField(auto_add_now=True, null=False)字段中使用date_published,以确保将“ date_published”自动设置为构造对象的日期;
  4. 通过在表单无效的情况下不进行重定向,可以实际呈现带有错误的表单,以便用户可以修复表单,然后再次提交;和
  5. 您可以使用return redirect(..),它是包裹在reverse(..)对象中的HttpResponseRedirect(..)的快捷方式。