代码之家  ›  专栏  ›  技术社区  ›  Kérdezösködő Indián

如何对长列表分页

  •  1
  • Kérdezösködő Indián  · 技术社区  · 7 年前

    我(仍然)在学习Perl的Catalyst框架。我需要给一长串的书编页码。我不知道该用什么来分页以及如何使用它。第二,如果我想将“page=1”参数传递给list方法(现在是it形式),则传递的值不会出现。如果找不到第1页的Args,那就找不到第1页了。

    这些是我的档案:

    图书.pm

    use utf8;
    package Library::Schema::Result::Books;
    
    use strict;
    use warnings;
    
    use Moose;
    use MooseX::NonMoose;
    use MooseX::MarkAsMethods autoclean => 1;
    extends 'DBIx::Class::Core';
    
    __PACKAGE__->load_components("InflateColumn::DateTime");
    __PACKAGE__->table("books");
    __PACKAGE__->add_columns(
      "id",
      {
        data_type => "uuid",
        default_value => \"uuid_generate_v4()",
        is_nullable => 0,
        size => 16,
      },
      "title",
      { data_type => "varchar", is_nullable => 0, size => 128 },
    );
    
    __PACKAGE__->set_primary_key("id");
    __PACKAGE__->add_unique_constraint("uk_books", ["title"]);
    __PACKAGE__->meta->make_immutable;
    
    1;
    

    图书.pm (控制器)

    package Library::Controller::Book;
    use Moose;
    use namespace::autoclean;
    use utf8;
    use Data::Validate::UUID qw(is_uuid);
    
    BEGIN { extends 'Catalyst::Controller'; }
    
    sub base :Chained('/'): PathPart('book'): CaptureArgs(0) {
        my ($self, $c) = @_;
        $c->stash(books_rs => $c->model('DB::Books'));
        $c->stash(books => [$c->stash->{books_rs}->search(
            {},
            {order_by => 'title ASC'})]
        );
    }
    
    sub list :Chained('base'): PathPart('list'): Args(0) {
        my ($self, $c) = @_;
        $c->stash(template => 'book/list.tt2');
    }
    
    sub index :Path :Args(0) {
        my ( $self, $c ) = @_;
        return $c->res->redirect(
            $c->uri_for($c->controller('Book')->action_for('list'))
        );
    }
    
    sub book :Chained('base'): PathPart(''): CaptureArgs(1) {
        my ($self, $c, $bookid) = @_;
        if(!is_uuid(uc($bookid))) {
            die "Invalid book ID.";
        }
        my $book = $c->stash->{books_rs}->find(
            { id => $bookid },
            { key => 'primary' }
        );
        die "No such user" if(!$book);
        $c->stash(book => $book);
    }
    
    sub add :Chained('base'): PathPart('add'): Args(0) {
        my ($self, $c) = @_;
        if(lc $c->req->method eq 'post') {
            my $params = $c->req->params;
            my $books_rs = $c->stash->{books_rs};
            my $newbook = $books_rs->create({
                title => $params->{newBookTitle},
            });
            return $c->res->redirect(
                $c->uri_for($c->controller('Book')->action_for('list')
            ));
        }
    }
    
    sub edit :Chained('book') :PathPart('edit'): Args(0) {
        my ($self, $c) = @_;
        if(lc $c->req->method eq 'post') {
            my $params = $c->req->params;
            my $book = $c->stash->{book};
            $book->update({
                title => $params->{title},
            });
            return $c->res->redirect( $c->uri_for(
                $c->controller('Book')->action_for('list'),
                [ $book->id ]
            ));
        }
    }
    
    sub remove :Chained('book'): PathPart('remove'): Args() {
        my ($self, $c) = @_;
        my $book = $c->stash->{book};
        $book->delete();
        return $c->res->redirect(
            $c->uri_for($c->controller('Book')->action_for('list'))
        );
    }
    
    __PACKAGE__->meta->make_immutable;
    
    1;
    

    以及我的相关部分 书籍/列表.tt 文件:

    <table>
        <thead>
            <tr>
                <th></th>
                <th>Book title</th>
            </tr>
        </thead>
        <tbody>
            [% FOREACH book IN books -%]
            <tr>
                <td>
                    <a href="[%- c.uri_for(c.controller('Book').action_for('remove'), [book.id]) %]">
                        <img src="../../images/trash.png" width="22" height="22">
                    </a>
                </td>
                <td>[% book.title %]</td>
            </tr>
            [% END -%]
        </tbody>
    </table>
    
    2 回复  |  直到 7 年前
        1
  •  0
  •   simbabque    7 年前

    有两件事你需要做这件事。总的来说,这是相当直截了当的。它在 DBIC Cookbook

    控制器

    你的 list 方法只列出存储在 base 链式方法。现在需要添加代码来获取URL参数并减少列表。

    sub list :Chained('base'): PathPart('list'): Args(0) {
        my ($self, $c) = @_;
    
        if (my $page = $c->req->params->{page}) {
            # TODO: validate $page
    
            my $rs = $c->stash->{books};
            $c->stash->{books} = $rs->search(undef, {
                 page => $page,
                 rows => 10,    # or how many you want
            });
        }
    
        $c->stash(template => 'book/list.tt2');
    }
    

    这段代码将用一个新的替换你的隐藏的resultset LIMIT 依附于它。记住,结果集可以链接到堆栈,因此 ->search ->all .

    不需要对显示较小列表的模板进行任何更改。

    但是,您可能希望控制分页。你可以用 Data::Page COUNT 查询。打开 DBIC_TRACE=1 如果您对正在发生的事情感兴趣,可以查看在后台运行的查询。

    在你的 方法,其中我们刚刚添加了上述代码,也隐藏了寻呼机。

    my $rs = $c->stash->{books};
    $c->stash->{books} = $rs->search(undef, {
         page => $page,
         rows => 10,    # or how many you want
    });
    
    $c->stash->{pager} = $rs->pager;
    

    模板

    现在我们需要在模板中显示一些控件。我不会把它们都展示出来,只会给你一个想法。因为我们仍然支持完整的列表,所以我们只能在有寻呼机的情况下显示控件。

    <table>
        [%# ... %]
        <tbody>
            [% FOREACH book IN books -%]
            <tr>
                [%# ... %]
            </tr>
            [% END -%]
        </tbody>
    </table>
    
    [% IF pager %]
    <ul>
        <li><a href="?page=[% pager.first_page %]">First page</a></li>
    </ul>
    [% END %]
    

    没必要用 c.uri_for 这里,因为我们只需要添加一个URL参数。用户的浏览器足够聪明,可以让这个只有参数的相对URL指向它已经在的东西。所以如果用户正在查看 https://example.org/list?page=2 ,单击 链接 ?page=1 会把他们带到 https://example.org/list?page=1 .

        2
  •  0
  •   Kérdezösködő Indián    7 年前

    我设法消除了这个非页面错误:

    sub list :Chained('base'): PathPart('list'): Args(0) {
        my ($self, $c) = @_;
        if (my $page = $c->req->params->{page}) {
            my $rs = $c->stash->{books_rs}->search({}, {
                 page => $page,
                 rows => 5,
            });
            $c->stash->{books_rs} = $rs;
            $c->stash->{pager} = $rs->pager;
        }
        $c->stash(template => 'book/list.tt2');
    }
    

    但它仍然显示所有的书。使用 页码 参数对结果集没有影响。