Job Search Engine


911 浏览 5 years, 8 months

2.2 列表视图

版权声明: 转载请注明出处 http://www.codingsoho.com/

CBV显示

接下来我们会通过django将列表在前端显示出来,首先会用django自带的render方法显示

先给一个最简单的实现

ListView

在views里添加列表视图,它从ListView继承而来

from django.views.generic.list import ListView
from .models import JobEntry

# Create your views here.
class JobEntryListView(ListView):
    model = JobEntry
路由

jse.urls里添加访问列表的路由

from job_entry.views import JobEntryListView

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^jobentry/$', JobEntryListView.as_view(), name='job_entry_list'),
]

如果现在访问http://127.0.0.1:8000/jobentry/,它会有下面报错

TemplateDoesNotExist at /jobentry/
job_entry/jobentry_list.html
Request Method: GET
Request URL:    [http://127.0.0.1](http://127.0.0.1):8000/jobentry/
Django Version: 1.11
Exception Type: TemplateDoesNotExist
Exception Value:    
job_entry/jobentry_list.html

Template-loader postmortem
Django tried loading these templates, in this order:

Using engine django:

django.template.loaders.app_directories.Loader: E:\Computer\virtualenv\ijob\env27\lib\site-packages\django\contrib\admin\templates\job_entry\jobentry_list.html (Source does not exist)
django.template.loaders.app_directories.Loader: E:\Computer\virtualenv\ijob\env27\lib\site-packages\django\contrib\auth\templates\job_entry\jobentry_list.html (Source does not exist)

因为我们现在缺少模板文件,它的默认路径在 [yourapp][yourapp_list.html],这个一个相对路径,绝对根目录需要在settings.py里指定。 上面的报错中,可以看到当前的templates搜索路径只在admin和auth模块

模板

修改settings文件

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates'),],                                # (1)
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

# (1) 增加的DIRS会新增搜索模板文件路径,这样最终添加的模板文件对应路径为[BASE_DIR]\templates\job_entry.jobentry_list.html

接下来实现jobentry_list.html文件

传递给template的变量为object_list,可以通过{{object_list}}语句直接显示

这会是一大串列表,我们用for语句寻呼访问

<H1>{{object_list}}</H1>

<table>
    <tr>
        <th>title</th>
        <th>salary</th>
        <th>region</th>
        <th>degree</th>
        <th>experience</th>
        <th>company</th>
        <th>industry</th>
        <th>description</th>
        <th>href</th>
        <th>created</th>
    </tr>
    {% for obj in object_list %}
    <tr>
        <td>{{obj.title}}</td>
        <td>{{obj.salary}}</td>
        <td>{{obj.region}}</td>
        <td>{{obj.degree}}</td>
        <td>{{obj.experience}}</td>
        <td>{{obj.company}}</td>
        <td>{{obj.industry}}</td>
        <td>{{obj.description}}</td>
        <td>{{obj.href}}</td>
        <td>{{obj.created}}</td>
    </tr>
    {% endfor %}
</table>

ListView参数配置和函数覆盖
get_context_data

上面例子中,可以看到模板文件里能够操作变量object_list这个变量,它是从哪儿传递过来的?可以修改吗?

它在MultipleObjectMixin::get_context_data中赋值

class MultipleObjectMixin(ContextMixin):
    def get_context_data(self, **kwargs):
        """
        Get the context for this view.
        """
        queryset = kwargs.pop('object_list', self.object_list)
        page_size = self.get_paginate_by(queryset)
        context_object_name = self.get_context_object_name(queryset)
        if page_size:
            paginator, page, queryset, is_paginated = self.paginate_queryset(queryset, page_size)
            context = {
                'paginator': paginator,
                'page_obj': page,
                'is_paginated': is_paginated,
                'object_list': queryset
            }
        else:
            context = {
                'paginator': None,
                'page_obj': None,
                'is_paginated': False,
                'object_list': queryset
            }
        if context_object_name is not None:
            context[context_object_name] = queryset
        context.update(kwargs)
        return super(MultipleObjectMixin, self).get_context_data(**context)

我们可以通过重载get_context_data这个函数来修改这个变量或者传递更多的变量

它也涉及了分页功能,这个我们在后面在详述

context_object_name

添加context_object_name

class JobEntryListView(ListView):
    model = JobEntry
    context_object_name  = 'jobentry_object_list'

这样在模板里也可以使用这个变量,它的值和object_list是一样的

{% for obj in jobentry_object_list %}
    <tr>
        <td>{{obj.title}}</td>
        <td>{{obj.salary}}</td>
        <td>{{obj.region}}</td>
        <td>{{obj.degree}}</td>
        <td>{{obj.experience}}</td>
        <td>{{obj.company}}</td>
        <td>{{obj.industry}}</td>
        <td>{{obj.description}}</td>
        <td>{{obj.href}}</td>
        <td>{{obj.created}}</td>
    </tr>
    {% endfor %}
ordering

可以通过修改ordering参数改变结果排序,例如我们想改成是创建时间倒叙,可以改成-created,那么结果会跟默认的相反,列表顺序颠倒了。

template_name

前面的模板我们是在指定文件存放的,也可以根据项目的需求放到自定义位置,该功能可以通过修改template_name实现

如果我随便改一个位置template_name = 'a.html',但是系统指定的位置仍正常放置了html文件,它不会报错,正常工作。但是如果指定位置并没有存放,那么就会继续报错找不到指定文件。从报错可以看到,它总是会找系统指定位置文件的

a.html, job_entry/jobentry_list.html
Request Method: GET
Request URL:    [http://127.0.0.1](http://127.0.0.1):8000/jobentry/
Django Version: 1.11
Exception Type: TemplateDoesNotExist
Exception Value:    
a.html, job_entry/jobentry_list.html

Template-loader postmortem
Django tried loading these templates, in this order:

Using engine django:
django.template.loaders.filesystem.Loader: E:\Computer\virtualenv\ijob\jse\templates\a.html (Source does not exist)
django.template.loaders.app_directories.Loader: E:\Computer\virtualenv\ijob\env27\lib\site-packages\django\contrib\admin\templates\a.html (Source does not exist)
django.template.loaders.app_directories.Loader: E:\Computer\virtualenv\ijob\env27\lib\site-packages\django\contrib\auth\templates\a.html (Source does not exist)

Using engine django:
django.template.loaders.filesystem.Loader: E:\Computer\virtualenv\ijob\jse\templates\job_entry\jobentry_list.html (Source does not exist)
django.template.loaders.app_directories.Loader: E:\Computer\virtualenv\ijob\env27\lib\site-packages\django\contrib\admin\templates\job_entry\jobentry_list.html (Source does not exist)
django.template.loaders.app_directories.Loader: E:\Computer\virtualenv\ijob\env27\lib\site-packages\django\contrib\auth\templates\job_entry\jobentry_list.html (Source does not exist)
其他

MultipleObjectMixin涉及的其它功能和配置从下面的代码段可以看出来

class MultipleObjectMixin(ContextMixin):
    """
    A mixin for views manipulating multiple objects.
    """
    allow_empty = True
    queryset = None
    model = None
    paginate_by = None
    paginate_orphans = 0
    context_object_name = None
    paginator_class = Paginator
    page_kwarg = 'page'
    ordering = None

很多配置是跟分页相关的,这个后面来学习