<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def build_query(spec):
 """ build the where clause based on a view specification spec -- The view specification. Contains the following possible values: future -- Boolean; whether to include entries from the future category -- Which category to limit to recurse -- Whether to include subcategories entry_type -- one or more entry types to include entry_type_not -- one or more entry types to exclude date -- a date spec last -- the last entry to end a view on first -- the first entry to start a view on before -- get entries from before this one after -- get entries from after this one """


    query = model.Entry.select()

    # primarily restrict by publication status
    if spec.get('_deleted', False):
        query = where_entry_deleted(query)
    elif spec.get('future', False):
        query = where_entry_visible_future(query)
    else:
        query = where_entry_visible(query)

    # restrict by category
    if spec.get('category') is not None:
        path = str(spec.get('category', ''))
        recurse = spec.get('recurse', False)
        query = where_entry_category(query, path, recurse)

    if spec.get('entry_type') is not None:
        query = where_entry_type(query, spec['entry_type'])

    if spec.get('entry_type_not') is not None:
        query = where_entry_type_not(query, spec['entry_type_not'])

    if spec.get('tag') is not None:
        query = where_entry_tag(query, spec['tag'])

    if spec.get('date') is not None:
        query = where_entry_date(query, spec['date'])

    if spec.get('last') is not None:
        query = where_entry_last(query, get_entry(spec['last']))

    if spec.get('first') is not None:
        query = where_entry_first(query, get_entry(spec['first']))

    if spec.get('before') is not None:
        query = where_before_entry(query, get_entry(spec['before']))

    if spec.get('after') is not None:
        query = where_after_entry(query, get_entry(spec['after']))

    return query.distinct()