Django FormView - 输入字段不保存到DB

时间:2016-06-16 02:21:11

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

所以,我正在尝试使用输入字段向其中添加信息然后保存它。截至目前,我在尝试提交表单时没有收到任何错误,但它也没有创建对象。谁能看到错误?希望得到一些帮助。

以下是我的client_setup.py表单:

from django import forms

from producer.models import Client

class ClientSetupForm(forms.Form):

    company_name = forms.CharField(required=False)
    first_name = forms.CharField()
    last_name = forms.CharField()

    def clean_company_name(self):
        company_name = self.cleaned_data.get('company_name')

        pass

    def clean_first_name(self):
        first_name = self.cleaned_data.get('first_name')

        pass

    def clean_last_name(self):
        last_name = self.cleaned_data.get('last_name')

        pass

pod_funnel.py次观看:

from django.shortcuts import render

from .forms.client_setup import ClientSetupForm
from .forms.podcast_setup import PodcastSetupForm
from .forms.episode_info import EpisodeInfoForm
from .forms.image_files import EpisodeImageFilesForm
from .forms.wordpress_info import WordpressInfoForm
from .forms.chapter_marks import ChapterMarksForm
from .forms.show_links import ShowLinksForm
from .forms.tweetables import TweetablesForm
from .forms.clicktotweet import ClickToTweetForm
from .forms.schedule import ScheduleForm

from producer.models import Client, Production, ChapterMark, ProductionLink, ProductionTweet, Podcast

from django.views.generic.edit import FormView

from django.core.urlresolvers import reverse

class ClientSetupView(FormView):
    template_name = 'pod_funnel/forms.html'
    form_class = ClientSetupForm
    success_url = '/podfunnel/ClientSetupView/'

    def form_valid(self, form):

        form.clean_first_name()
        form.clean_last_name()

        return super(ClientSetupView, self).form_valid(form)

models.py

from django.db import models
from django.conf import settings
from django.utils.encoding import smart_text
from producer import myFields
from randomslugfield import RandomSlugField
from django.contrib.auth.models import User
from django.core import urlresolvers

class Client(TimeStampedModel):
    company_name = models.CharField(max_length=64)
    first_name = models.CharField(max_length=20)
    last_name = models.CharField(max_length=20)
    email = models.EmailField()
    user = models.ForeignKey(User, on_delete=models.CASCADE)

    def full_name(self):
        return smart_text('%s %s' % (self.first_name, self.last_name))

    def __unicode__(self):
        return smart_text(self.company_name)

class Podcast(TimeStampedModel):
    PRODUCTION_NAMES_HELP = 'You can use the following placeholders in the name: EPISODE_GUEST_FULL_NAME, ' \
                            'EPISODE_NUMBER, EPISODE_TITLE'

    BASE_PROD_DEFAULT_TITLE_FORMAT = 'EPISODE_NUMBER EPISODE_GUEST_FULL_NAME - EPISODE_TITLE'
    SECONDARY_PROD_DEFAULT_TITLE_FORMAT = 'EPISODE_TITLE with EPISODE_GUEST_FULL_NAME'

    client = models.ForeignKey(Client)
    name = models.CharField(max_length=100)
    uuid = models.CharField(max_length=32, verbose_name='Auphonic Preset UUID')

    dropbox_service = models.ForeignKey(Service, null=True, blank=True, related_name='dropbox_service_id',
                                        limit_choices_to={'provider': Service.DROPBOX}, on_delete=models.SET_NULL)
    soundcloud_service = models.ForeignKey(Service, null=True, blank=True, related_name='soundcloud_service_id',
                                           limit_choices_to={'provider': Service.SOUNDCLOUD}, on_delete=models.SET_NULL)
    libsyn_service = models.ForeignKey(Service, null=True, blank=True, related_name='libsyn_service_id',
                                       limit_choices_to={'provider': Service.LIBSYN}, on_delete=models.SET_NULL)
    archiveorg_service = models.ForeignKey(Service, null=True, blank=True, related_name='archiveorg_service_id',
                                           limit_choices_to={'provider': Service.ARCHIVEORG}, on_delete=models.SET_NULL)
    blubrry_service = models.ForeignKey(Service, null=True, blank=True, related_name='blubrry_service_id',
                                        limit_choices_to={'provider': Service.BLUBRRY}, on_delete=models.SET_NULL)
    youtube_service = models.ForeignKey(Service, null=True, blank=True, related_name='youtube_service_id',
                                        limit_choices_to={'provider': Service.YOUTUBE}, on_delete=models.SET_NULL)
    wordpress_config = models.ForeignKey(WordpressConfig, on_delete=models.SET_NULL, null=True, blank=True)

    itunes_url = models.URLField(null=True, blank=True)

    soundcloud_account = models.ForeignKey(SoundcloudConfig, on_delete=models.SET_NULL, null=True, blank=True)
    twitter_account = models.ForeignKey(TwitterConfig, on_delete=models.SET_NULL, null=True, blank=True)
    podcast_twitter_name = models.CharField(max_length=64, null=True)
    podcast_guest_twitter_name = models.CharField(max_length=64, null=True)
    schedule_tweets_on_publish = models.BooleanField(default=True, verbose_name="Schedule 'First Week Tweets' when "
                                                                                "production is published")
    podcast_click_to_tweet_format = models.CharField(max_length=200, null=True, blank=True,
                                                     help_text='You can use the following placeholders in the text: '
                                                               'PODCAST_TWITTER_NAME, PODCAST_GUEST_TWITTER_NAME, '
                                                               'WORDPRESS_URL')

    production_auto_email_test_mode = models.BooleanField(default=True, help_text='While Test Mode is enabled, Auto'
                                                                                  'email is sent to FullCast admin team'
                                                                                  'only. If disabled it will also be'
                                                                                  'sent to client email.')
    production_auto_email_subject_format = models.CharField(max_length=200, null=True, blank=True)
    production_auto_email_format = models.TextField(null=True, blank=True,
                                                    help_text='You can use the following placeholders in the text: '
                                                              'CLIENT_FIRST_NAME, WORDPRESS_URL, TRANSCRIPTION_URL, '
                                                              'EPISODE_GUEST_FIRST_NAME, EPISODE_GUEST_LAST_NAME, '
                                                              'EPISODE_NUMBER, CLICK_TO_TWEET_LINK, ITUNES_URL')

    base_production_name_format = models.CharField(max_length=200, null=True, blank=True,
                                                   default=BASE_PROD_DEFAULT_TITLE_FORMAT)
    secondary_production_name_format = models.CharField(max_length=200, null=True, blank=True,
                                                        default=SECONDARY_PROD_DEFAULT_TITLE_FORMAT,
                                                        help_text=PRODUCTION_NAMES_HELP)

    def __unicode__(self):
        return smart_text(self.name)

-------------------------------------------- --------

更新

Environment:


Request Method: POST
Request URL: http://192.168.33.10:8000/podfunnel/podcastsetup/

Django Version: 1.9
Python Version: 2.7.6
Installed Applications:
('producer',
 'django.contrib.admin',
 'django.contrib.sites',
 'registration',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'django_extensions',
 'randomslugfield',
 'adminsortable2',
 'crispy_forms')
Installed Middleware:
('django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware',
 'django.middleware.security.SecurityMiddleware')



Traceback:

File "/usr/local/lib/python2.7/dist-packages/django/core/handlers/base.py" in get_response
  149.                     response = self.process_exception_by_middleware(e, request)

File "/usr/local/lib/python2.7/dist-packages/django/core/handlers/base.py" in get_response
  147.                     response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "/home/vagrant/fullcast_project/producer/views/pod_funnel.py" in podcastsetup
  132.      instance.save()

File "/usr/local/lib/python2.7/dist-packages/django/db/models/base.py" in save
  700.                        force_update=force_update, update_fields=update_fields)

File "/usr/local/lib/python2.7/dist-packages/django/db/models/base.py" in save_base
  728.             updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields)

File "/usr/local/lib/python2.7/dist-packages/django/db/models/base.py" in _save_table
  812.             result = self._do_insert(cls._base_manager, using, fields, update_pk, raw)

File "/usr/local/lib/python2.7/dist-packages/django/db/models/base.py" in _do_insert
  851.                                using=using, raw=raw)

File "/usr/local/lib/python2.7/dist-packages/django/db/models/manager.py" in manager_method
  122.                 return getattr(self.get_queryset(), name)(*args, **kwargs)

File "/usr/local/lib/python2.7/dist-packages/django/db/models/query.py" in _insert
  1039.         return query.get_compiler(using=using).execute_sql(return_id)

File "/usr/local/lib/python2.7/dist-packages/django/db/models/sql/compiler.py" in execute_sql
  1064.                 cursor.execute(sql, params)

File "/usr/local/lib/python2.7/dist-packages/django/db/backends/utils.py" in execute
  79.             return super(CursorDebugWrapper, self).execute(sql, params)

File "/usr/local/lib/python2.7/dist-packages/django/db/backends/utils.py" in execute
  64.                 return self.cursor.execute(sql, params)

File "/usr/local/lib/python2.7/dist-packages/django/db/utils.py" in __exit__
  95.                 six.reraise(dj_exc_type, dj_exc_value, traceback)

File "/usr/local/lib/python2.7/dist-packages/django/db/backends/utils.py" in execute
  64.                 return self.cursor.execute(sql, params)

Exception Type: IntegrityError at /podfunnel/podcastsetup/
Exception Value: null value in column "client_id" violates not-null constraint
DETAIL:  Failing row contains (5, 2016-06-16 05:55:43.067263+00, 2016-06-16 05:55:43.06732+00, Awesome Show!, , null, null, null, null, null, null, null, null, null, null, null, null, null, http://html-color-codes.info/, null, t, t, EPISODE_NUMBER EPISODE_GUEST_FULL_NAME - EPISODE_TITLE, EPISODE_TITLE with EPISODE_GUEST_FULL_NAME, null).

-------------------------------------------- --------

client_setup.py表格:

from django import forms

from producer.models import Client
# from producer.models import Podcast

class ClientSetupForm(forms.ModelForm):

    class Meta:

        model = Client
        fields = ['company_name', 'first_name', 'last_name']

    def clean_company_name(self):
        company_name = self.cleaned_data.get('company_name')

        return company_name

    def clean_first_name(self):
        first_name = self.cleaned_data.get('first_name')

        return first_name

    def clean_last_name(self):
        last_name = self.cleaned_data.get('last_name')

        return last_name

podcast_setup.py表格:

from django import forms

from producer.models import Podcast

class PodcastSetupForm(forms.ModelForm):

class Meta:

    model = Podcast
    fields = ['name', 'itunes_url']

def clean_name(self):
    name = self.cleaned_data.get('name')

    return name

def clean_itunes_url(self):
    itunes_url = self.cleaned_data.get('itunes_url')

    return itunes_url

pod_funnel.py次观看:

from django.shortcuts import render

from .forms.client_setup import ClientSetupForm
from .forms.podcast_setup import PodcastSetupForm
from .forms.episode_info import EpisodeInfoForm
from .forms.image_files import EpisodeImageFilesForm
from .forms.wordpress_info import WordpressInfoForm
from .forms.chapter_marks import ChapterMarksForm
from .forms.show_links import ShowLinksForm
from .forms.tweetables import TweetablesForm
from .forms.clicktotweet import ClickToTweetForm
from .forms.schedule import ScheduleForm

from producer.models import Client, Production, ChapterMark, ProductionLink, ProductionTweet, Podcast

from django.views.generic.edit import FormView

from django.core.urlresolvers import reverse

def clientsetup(request):

title = 'Client Setup'
title_align_center = True
form = ClientSetupForm(request.POST or None)
context = {
    "title": title,
    "form": form
}

if form.is_valid():

    instance = form.save(commit=False)

    company_name = form.cleaned_data.get("company_name")
    first_name = form.cleaned_data.get("first_name")
    last_name = form.cleaned_data.get("last_name")

    instance.company_name = company_name
    instance.first_name = first_name
    instance.last_name = last_name

    instance.user = request.user

    instance.save()

    return render(request, "pod_funnel/forms.html", context)

else:

        return render(request, "pod_funnel/forms.html", context)

def podcastsetup(request):

title = 'Podcast Setup'
title_align_center = True
form = PodcastSetupForm(request.POST or None)
context = {
    "title": title,
    "form": form
}

if form.is_valid():

    instance = form.save(commit=False)

    name = form.cleaned_data.get("name")
    itunes_url = form.cleaned_data.get("itunes_url")

    instance.name = name
    instance.itunes_url = itunes_url

    instance.save()

    return render(request, "pod_funnel/forms_podcast_setup.html", context)

else:

        return render(request, "pod_funnel/forms_podcast_setup.html", context)

1 个答案:

答案 0 :(得分:3)

您的代码存在一些问题:

  • clean_<fieldname>方法必须返回一个值 - 您只需pass

  • 您不应该在视图中手动调用这些方法。这些被称为as part of the built-in form validation。在你的情况下,你实际上并没有在这些函数中执行任何逻辑,并且可以完全取消它们。

  • 您永远不应该直接修改form['cleaned_data']

  • 您的数据未在任何地方保存,因为您在验证表单后无法对其进行任何操作。您可能希望使用model form而不是常规表单,因为它具有用于在验证后将表单数据保存到模型的内置方法。

我建议您花一些时间研究模型表单(以及一般表单)的文档,因为您当前的实现似乎暗示了一些关于Django的Form API如何工作的误解。

修改 - 对使用ModelForm的更新代码发表评论:

  • 如上所述,您使用clean_<fieldname>方法是错误的,也是不必要的。完全删除这些并且不要直接编辑form['cleaned_data]`。

  • 您收到的错误是因为您的Podcast模型具有Client必需外键,但此值永远不会设置。您的ModelForm仅设置nameitunes_url。您需要将此字段添加到表单中,或者在保存表单实例之前手动设置此值。