模型表格在django中的外键上崩溃

时间:2010-01-10 21:07:42

标签: python django django-models django-forms

所以我正在尝试在管理页面及其中创建新的Feed 崩溃时出现错误IntegrityError:lifestream_feed.lifestream_id 可能不是NULL,表单['lifestream']已设置但是 form.instance.lifestream不是。

form.fields甚至表明lifestream是一个django.forms.models.ModelChoiceField

以下是代码:

class FeedCreationForm(forms.ModelForm):
    class Meta:
        model = Feed
        exclude = ['name', 'domain', 'fetchable']

    def parse_feed(self, feed_url):
        feed = feedparser.parse(feed_url)

        # Does the feed have errors
        if feed['bozo']:
            if feed['feed'].has_key("links"):
                for link in feed['feed']['links']:
                    if link["type"] == "application/rss+xml":
                        feed = self.parse_feed(link['href'])
                        if not feed['bozo']:
                            return feed
        else:
            return feed

        return None

    def clean(self):
        """
        Checks to make sure a feed url is valid and gets the feed
title
        and domain.
        """
        feed_url = self.cleaned_data.get('url')
        if not feed_url:
            # Feed url was not validated by the field validator
            return
        feed = self.parse_feed(feed_url)
        if feed:
            feed_url = feed['url']
            self.cleaned_data['url'] = feed_url
        else:
            # the feed was not parsed correctly.
            import logging

            self._errors['url'] = ErrorList(["This is not a valid
feed: %s" % feed['bozo_exception']])
            logging.error(feed['bozo_exception'])
            # This field is no longer valid. Remove from cleaned_data
            del self.cleaned_data['url']
            return

        # Check if the feed has a title field
        feed_info = feed.get('feed')
        if not feed_info.get('title'):
            self._errors['url'] = ErrorList(["This is not a valid
feed: The feed is empty"])
            # This field is no longer valid. Remove from cleaned_data
            del self.cleaned_data['url']
            return
        self.cleaned_data['name'] = feed_info['title']
        self.instance.name = self.cleaned_data['name']
        self.cleaned_data['domain'] = get_url_domain(feed_url)
        self.instance.domain = self.cleaned_data['domain']

        return self.cleaned_data

class FeedAdmin(admin.ModelAdmin):
    list_display    = ('name', 'lifestream', 'domain', 'fetchable')
    list_filter     = ('domain', 'lifestream')
    actions         = ['make_fetchable', 'make_unfetchable']

    add_form = FeedCreationForm
    model = Feed

    def make_unfetchable(self, request, queryset):
        queryset.update(fetchable=False)
    make_unfetchable.short_description = _(u"Mark as unfetchable")

    def make_fetchable(self, request, queryset):
        queryset.update(fetchable=True)
    make_fetchable.short_description = _(u"Mark as fetchable")

    def add_view(self, request):
        if not self.has_change_permission(request):
            raise PermissionDenied
        if request.method == 'POST':
            form = self.add_form(request.POST)
            if form.is_valid():
                new_feed = form.save()
                msg = _('The %(name)s "%(obj)s" was added
successfully.') % {'name': 'user', 'obj': new_feed}
                self.log_addition(request, new_feed)
                if "_addanother" in request.POST:
                    request.user.message_set.create(message=msg)
                    return HttpResponseRedirect(request.path)
                elif '_popup' in request.REQUEST:
                    return self.response_add(request, new_feed)
                else:
                    request.user.message_set.create(message=msg + ' '
+ ugettext("You may edit it again below."))
                    # TODO: use reversed url
                    return HttpResponseRedirect('../%s/' %
new_feed.id)
        else:
            form = self.add_form()

        return render_to_response('admin/lifestream/feed/
add_form.html', {
            'title': _('Add feed'),
            'form': form,
            'is_popup': '_popup' in request.REQUEST,
            'add': True,
            'change': False,
            'has_add_permission': True,
            'has_delete_permission': False,
            'has_change_permission': True,
            'has_file_field': False,
            'has_absolute_url': False,
            'auto_populated_fields': (),
            'opts': self.model._meta,
            'save_as': False,
            #'username_help_text': self.model._meta.get_field
('username').help_text,
            'root_path': self.admin_site.root_path,
            'app_label': self.model._meta.app_label,
        }, context_instance=template.RequestContext(request))

    def queryset(self, request):
        return self.model.objects.feeds()

admin.site.register(Feed, FeedAdmin)

class Lifestream(models.Model):
    """
    A lifestream. Lifestreams can be created per user.
    """
    site = models.ForeignKey(Site, verbose_name=_(u"site"))
    user = models.ForeignKey(User, verbose_name=_(u"user"))
    slug = models.SlugField(_("slug"), help_text=_('Slug for use in
urls (Autopopulated from the title).'), blank=True)
    title = models.CharField(_("title"), max_length=255)

    def __unicode__(self):
        return self.title

class FeedManager(models.Manager):
    ''' Query only normal feeds. '''

    def feeds(self):
        return super(FeedManager, self).get_query_set()

    def fetchable(self):
        return self.feeds().filter(fetchable=True)

class Feed(models.Model):
    '''A feed for gathering data.'''
    lifestream = models.ForeignKey(Lifestream, verbose_name=_
('lifestream'))
    name = models.CharField(_("feed name"), max_length=255)
    url = models.URLField(_("feed url"), help_text=_("Must be a valid
url."), verify_exists=True, max_length=1000)
    domain = models.CharField(_("feed domain"), max_length=255)
    fetchable = models.BooleanField(_("fetchable"), default=True)

    # The feed plugin name used to process the incoming feed data.
    plugin_class_name = models.CharField(_("plugin name"),
max_length=255, null=True, blank=True, choices=getattr(settings,
"PLUGINS", PLUGINS))

    objects = FeedManager()

    def __unicode__(self):
        return self.name 

它没有返回空的返回,它到达返回self.cleaned_data:

-> return self.cleaned_data
(Pdb) list
 85             self.cleaned_data['name'] = feed_info['title']
 86             self.instance.name = self.cleaned_data['name']
 87             self.cleaned_data['domain'] = get_url_domain(feed_url)
 88             self.instance.domain = self.cleaned_data['domain']
 89     
 90  ->         return self.cleaned_data
 91     
 92     class FeedAdmin(admin.ModelAdmin):
 93         list_display    = ('name', 'lifestream', 'domain', 'fetchable')
 94         list_filter     = ('domain', 'lifestream')
 95         actions         = ['make_fetchable', 'make_unfetchable']
(Pdb) self.cleaned_data
{'url': u'http://twitter.com/statuses/user_timeline/6166742.rss', 'domain': u'twitter.com', 'lifestream': <Lifestream: Social>, 'name': u'Twitter / sontek', 'plugin_class_name': u'lifestream.plugins.twitter.TwitterPlugin'}

2 个答案:

答案 0 :(得分:0)

我认为问题出在您的clean()方法中。

一般clean()方法(与clean_domain()等字段特定的清理方法相对)必须返回cleaned_data字典(减去任何不验证的字段),并且至少有3在clean方法中返回,不返回任何内容。

请参阅here

答案 1 :(得分:0)

原来这是django HEAD中的一个错误