Getting post data from private page

setup_postdata takes a post object of type \WP_Post, but you’re passing it a WP_Query instead

e.g.

global $post;
setup_postdata( $post );

Thankfully the solution is trivial, when you call the_post, it sets up the current post data for you, so removing that line is all you need to do.

The second issue is that WP_Query will filter out private posts if you’re not logged in, so setting the post status to private is necessary.

An important thing you’re missing though is the clean up call. You need to call wp_reset_postdata() when you’re done so that code that runs after your loop has the current post and not the last post in your query.

Here’s what that query might look like:

$the_query = new WP_Query( array(
    'id' => '1457'
    'post_type' => 'page',
    'post_status' => 'private'
) );
if ( $the_query->have_posts() ) {
    while( $the_query->have_posts() ) {
        $the_query->the_post();
        // do something;
    }
    wp_reset_postdata();
}

There’s a faster way though, you already know the post ID, so we can do this:

$p = get_post( 1457 );
if ( null !== $p ) {
    setup_postdata( $p );
    // do things
    wp_reset_postdata();
}