Home Forums Feature Requests Add ability to exclude drafts from Relationship field


Add ability to exclude drafts from Relationship field

  • I was recently building a site that relied on user-submitted content where a Relationship field was in use, and the client requested that users should only be able to select published posts. I was a bit surprised that ACF doesn’t have an option for this already. In just about every instance where I’m using a Relationship field it seems to make sense to limit selection to published content only.

    I see three potential solutions, each with varying level of benefit/complexity:

    1) Simply exclude drafts by removing ‘draft’ from the post_status array under core/fields/relationship.php, line 134.

    2) Add a field option to “Exclude Drafts”, or “Show Published Only”

    3) Add a field option to allow an admin to select the exact set of post statuses to display in the relationship field (Publish, Draft, Private, etc.).

    I’m happy to write up this patch, just looking to get some feedback on a preferred approach.

  • ACF actually does have this feature (though I didn’t realize it until your question raised my curiosity).

    You can filter relationship query results using the filters ‘acf/fields/relationship/query’, ‘acf/fields/relationship/query/name={{field_name}}’, and ‘acf/fields/relationship/query/key={{field_key}}’ in increasing specificity. So to get only published posts, you would have something like:

    add_filter('acf/fields/relationship/query/name=your_relationship_name', 'relationship_options_filter', 10, 3);
    function relationship_options_filter($options, $field, $the_post) {
    	$options['post_status'] = array('publish');
    	return $options;
  • Nice find! This does appear to work. So my next question is: Would it still be nice to have this as an option in the UI? I suspect that in many (if not most) cases drafts are unwanted. For me the filters are sufficient, just trying to think of the less technically-inclined.

  • thanks wells5609!
    hi bootsz, yes that would be nice to select this in the options, every time we use this field, i always wonder who needs to select drafts 😉

  • Hey all – i need to do this too but not sure how to implement the above.

    I’ve placed it in my functions.php and changed name=your_relationship_name to name=related_projects (the name of the field?).

    Is there something else i should do?

  • I have just tried the above to no avail.

    Was there anything that else that needs doing?

  • @nml @v3nt you don’t need an acf function to get this working, although it might be nice to integrate something into the admin its not needed and is fairly easy to do this in your theme with or without using the filter mentioned above.

    Here’s how to do without using the filter:
    If you wrap the guts of your relationship loop with a conditional using get_post_status() you can exclude or specify at that point. e.g.

    $posts = get_field('relationship_field_name');
    if( $posts ): ?>
        <?php foreach( $posts as $post): // variable must be called $post (IMPORTANT) ?>
            <?php setup_postdata($post); ?>
            <?php if ( get_post_status() == 'publish' ) :?>
                    <a href="<?php the_permalink(); ?>"><?php the_title(); ?></a>
                    <span>Custom field from $post: <?php the_field('author'); ?></span>
            <?php endif;?>
        <?php endforeach; ?>
        <?php wp_reset_postdata(); // IMPORTANT - reset the $post object so the rest of the page works correctly ?>
    <?php endif; ?>

    If you don’t setup post data in your loop just use this instead:

        if ( get_post_status($p->ID) == 'publish' ){
            // loop code 


  • @lucidlips while I agree your solution is simple, I think data entered and set a non-published documents / post entry is not made public, it should not be pulled through as such.

    I think the default should be published only. If a developer wants to change this a php template change should be made available for an override.

    Just my 2 pennies..

    Great code example btw!

  • @nml you’re statement is mostly true for posts marked as ‘draft’ or ‘trash’ but the remainder of post status’s private/future/pending etc still have functional usage in a relationship. Im guessing the author avoided having an opinion and instead let developers make the decision.

    On that note, I think the relationship field could be extended to include a whole range of features that I would find useful, this being one of them.

  • @lucidlips I might be confused, but I think this question is about filtering the ACF relationship field UI to exclude draft posts (admin), not how to not show draft posts on the front-end.

    Your solution it explains how to exclude posts of a certain status from a loop, which I’m sure is helpful to many. But, it hasn’t nothing to do with ACF, but rather post loops.

    BTW. post_status is a column in the wp_posts table and is returned with the WP_Post object, so you could also use this condition:

        if ( 'publish' === $post->post_status ){
            // loop code 


  • Why does this field show drafts by default? Is there a reason? This should definitely be an option in the UI and not require any hooks.

  • @wells5609 – this solution was working wonderfully until recently. Anyone know how to address this issue currently (V 5.6.1)?

    Has this stopped working for anyone else?

    – I couldn’t agree more!

  • Adding vote for adding post status filter to relationship admin interface as described by @gavin310

  • I just found this topic after a client called me saying posts set as Private are showing up on their website. So is the relationship field really just showing all posts, regardless what status they have? This should never happen! A private post means it’s only meant for logged in users and not for anyone else!

  • Just wanted to chime-in on the side of this being bonkers.

    It’s fine for draft items to appear as choices in a Relationship… but they certainly should not be returned by front-end functions.

    The filter solution prevents them from being displayed as choices, but does not address items already set. I know I could use a conditional in the front-end loop, but the situation where I noticed this also relies on a count of the returned items, which would get messed up. I would need to essentially pre-process the results to have it be correct.

    I am really curious on the rationale here…

  • If you have multiple relationship fields and want to target them all just add this to your functions.php.

    add_filter( 'acf/fields/relationship/query','relationship_options_filter', 10, 3);
    function relationship_options_filter($options, $field, $the_post) {
    	$options['post_status'] = array('publish');
    	return $options;


Viewing 16 posts - 1 through 16 (of 16 total)

The topic ‘Add ability to exclude drafts from Relationship field’ is closed to new replies.