zoukankan      html  css  js  c++  java
  • Django源码解读——ModelAdmin方法解读

    本期解读源码:
    django.contrib.adminModelAdmin类中方法changelist_view

        def changelist_view(self, request, extra_context=None):
            """
            The 'change list' admin view for this model.
            changelist_view管理视图函数主要用于django自带后台admin管理模型时,用户初始看到的模型信息显示列表
            视图函数一共有三个参数
                self:代表ModelAdmin类本身
                request:代表这次请求
                extra_context:代表额外的信息,这里extra_context默认为None,说明在访问这个方法时,即便是没带上extra_context也能正常访问
            """
    # 从django.contrib.admin.views.main导入错误报警ERROR_FLAG
            from django.contrib.admin.views.main import ERROR_FLAG
            # opts为当前管理模型的Meta属性,可理解为当前管理模型的别名
            opts = self.model._meta
            # 当前管理模型的app标签,这个在app.py和init.py中设置
            app_label = opts.app_label
            # 判断当前请求用户有没有查看或者修改权限,没有抛出异常PermissionDenied
            if not self.has_view_or_change_permission(request):
                raise PermissionDenied
    
            try:
                #尝试得到请求数据列表的实例
                cl = self.get_changelist_instance(request)
            # 如果不能正常得到,捕获异常IncorrectLookupParameters
            except IncorrectLookupParameters:
                # Wacky lookup parameters were given, so redirect to the main
                # changelist page, without parameters, and pass an 'invalid=1'
                # parameter via the query string. If wacky parameters were given
                # and the 'invalid=1' parameter was already in the query string,
                # something is screwed up with the database, so display an error
                # page.
                # 异常显示页面
                if ERROR_FLAG in request.GET:
                    return SimpleTemplateResponse('admin/invalid_setup.html', {
                        'title': _('Database error'),
                    })
                return HttpResponseRedirect(request.path + '?' + ERROR_FLAG + '=1')
    
            # If the request was POSTed, this might be a bulk action or a bulk
            # edit. Try to look up an action or confirmation first, but if this
            # isn't an action the POST will fall through to the bulk edit check,
            # below.
            # 默认action按钮是未被点击的
            action_failed = False
            # 得到被选择的项目的列表
            selected = request.POST.getlist(helpers.ACTION_CHECKBOX_NAME)
            
            # 得到请求的action
            actions = self.get_actions(request)
            # Actions with no confirmation
            if (actions and request.method == 'POST' and
                    'index' in request.POST and '_save' not in request.POST):
                if selected:
                    response = self.response_action(request, queryset=cl.get_queryset(request))
                    if response:
                        return response
                    else:
                        action_failed = True
                else:
                    msg = _("Items must be selected in order to perform "
                            "actions on them. No items have been changed.")
                    self.message_user(request, msg, messages.WARNING)
                    action_failed = True
    
            # Actions with confirmation
            if (actions and request.method == 'POST' and
                    helpers.ACTION_CHECKBOX_NAME in request.POST and
                    'index' not in request.POST and '_save' not in request.POST):
                if selected:
                    response = self.response_action(request, queryset=cl.get_queryset(request))
                    if response:
                        return response
                    else:
                        action_failed = True
    
            if action_failed:
                # Redirect back to the changelist page to avoid resubmitting the
                # form if the user refreshes the browser or uses the "No, take
                # me back" button on the action confirmation page.
                return HttpResponseRedirect(request.get_full_path())
    
            # If we're allowing changelist editing, we need to construct a formset
            # for the changelist given all the fields to be edited. Then we'll
            # use the formset to validate/process POSTed data.
            formset = cl.formset = None
    
            # Handle POSTed bulk-edit data.
            if request.method == 'POST' and cl.list_editable and '_save' in request.POST:
                if not self.has_change_permission(request):
                    raise PermissionDenied
                FormSet = self.get_changelist_formset(request)
                modified_objects = self._get_list_editable_queryset(request, FormSet.get_default_prefix())
                formset = cl.formset = FormSet(request.POST, request.FILES, queryset=modified_objects)
                if formset.is_valid():
                    changecount = 0
                    for form in formset.forms:
                        if form.has_changed():
                            obj = self.save_form(request, form, change=True)
                            self.save_model(request, obj, form, change=True)
                            self.save_related(request, form, formsets=[], change=True)
                            change_msg = self.construct_change_message(request, form, None)
                            self.log_change(request, obj, change_msg)
                            changecount += 1
    
                    if changecount:
                        msg = ngettext(
                            "%(count)s %(name)s was changed successfully.",
                            "%(count)s %(name)s were changed successfully.",
                            changecount
                        ) % {
                            'count': changecount,
                            'name': model_ngettext(opts, changecount),
                        }
                        self.message_user(request, msg, messages.SUCCESS)
    
                    return HttpResponseRedirect(request.get_full_path())
    
            # Handle GET -- construct a formset for display.
            elif cl.list_editable and self.has_change_permission(request):
                FormSet = self.get_changelist_formset(request)
                formset = cl.formset = FormSet(queryset=cl.result_list)
    
            # Build the list of media to be used by the formset.
            if formset:
                media = self.media + formset.media
            else:
                media = self.media
    
            # Build the action form and populate it with available actions.
            if actions:
                action_form = self.action_form(auto_id=None)
                action_form.fields['action'].choices = self.get_action_choices(request)
                media += action_form.media
            else:
                action_form = None
    
            selection_note_all = ngettext(
                '%(total_count)s selected',
                'All %(total_count)s selected',
                cl.result_count
            )
    
            context = {
                **self.admin_site.each_context(request),
                'module_name': str(opts.verbose_name_plural),
                'selection_note': _('0 of %(cnt)s selected') % {'cnt': len(cl.result_list)},
                'selection_note_all': selection_note_all % {'total_count': cl.result_count},
                'title': cl.title,
                'is_popup': cl.is_popup,
                'to_field': cl.to_field,
                'cl': cl,
                'media': media,
                'has_add_permission': self.has_add_permission(request),
                'opts': cl.opts,
                'action_form': action_form,
                'actions_on_top': self.actions_on_top,
                'actions_on_bottom': self.actions_on_bottom,
                'actions_selection_counter': self.actions_selection_counter,
                'preserved_filters': self.get_preserved_filters(request),
                **(extra_context or {}),
            }
    
            request.current_app = self.admin_site.name
    
            return TemplateResponse(request, self.change_list_template or [
                'admin/%s/%s/change_list.html' % (app_label, opts.model_name),
                'admin/%s/change_list.html' % app_label,
                'admin/change_list.html'
            ], context)
    
  • 相关阅读:
    ThinkPHP 3.2.2 实现持久登录 ( 记住我 )
    Java实现 LeetCode 20 有效的括号
    Java实现 LeetCode 20 有效的括号
    Java实现 LeetCode 19删除链表的倒数第N个节点
    Java实现 LeetCode 19删除链表的倒数第N个节点
    Java实现 LeetCode 19删除链表的倒数第N个节点
    Java实现 LeetCode 18 四数之和
    Java实现 LeetCode 18 四数之和
    Java实现 LeetCode 18 四数之和
    Java实现 LeetCode 17 电话号码的字母组合
  • 原文地址:https://www.cnblogs.com/donoho/p/11577076.html
Copyright © 2011-2022 走看看