Unified query builders for all browse views; could still be classes

svn: r19791
This commit is contained in:
Doug Blank 2012-06-08 13:16:05 +00:00
parent 49cf552b3f
commit 2baba1dbb3
2 changed files with 429 additions and 165 deletions

View File

@ -16,6 +16,7 @@
{% endif %} {% endif %}
<input type="submit" value="Search:"></input> <input type="submit" value="Search:"></input>
<input autocomplete="off" name="search" id="get_focus" type="text" size="50" value="{{search}}"></input> <input autocomplete="off" name="search" id="get_focus" type="text" size="50" value="{{search}}"></input>
<br/><i>Available search terms</i>: <b>{{search_terms}}</b>
</form> </form>
</div> </div>

View File

@ -258,69 +258,38 @@ def view_list(request, view):
search = "" search = ""
if view == "event": if view == "event":
context["tviews"] = _("Events") context["tviews"] = _("Events")
if request.user.is_authenticated(): search = request.GET.get("search") if request.GET.has_key("search") else ""
private = Q() query, order, terms = build_event_query(request, search)
else: object_list = Event.objects \
# NON-AUTHENTICATED users .filter(query) \
private = Q(private=False) .distinct() \
if request.GET.has_key("search"): .order_by(*order)
search = request.GET.get("search")
object_list = Event.objects \
.filter((Q(gramps_id__icontains=search) |
Q(event_type__name__icontains=search) |
Q(place__title__icontains=search)) &
private
) \
.distinct() \
.order_by("gramps_id")
else:
object_list = Event.objects.filter(private).order_by("gramps_id")
view_template = 'view_events.html' view_template = 'view_events.html'
total = Event.objects.all().count() total = Event.objects.all().count()
elif view == "media": elif view == "media":
context["tviews"] = _("Media") context["tviews"] = _("Media")
if request.user.is_authenticated(): search = request.GET.get("search") if request.GET.has_key("search") else ""
private = Q() query, order, terms = build_media_query(request, search)
else: object_list = Media.objects \
# NON-AUTHENTICATED users .filter(query) \
private = Q(private=False) .distinct() \
if request.GET.has_key("search"): .order_by(*order)
search = request.GET.get("search")
object_list = Media.objects \
.filter(Q(gramps_id__icontains=search) &
private
) \
.distinct() \
.order_by("gramps_id")
else:
object_list = Media.objects.filter(private).order_by("gramps_id")
view_template = 'view_media.html' view_template = 'view_media.html'
total = Media.objects.all().count() total = Media.objects.all().count()
elif view == "note": elif view == "note":
context["tviews"] = _("Notes") context["tviews"] = _("Notes")
if request.user.is_authenticated(): search = request.GET.get("search") if request.GET.has_key("search") else ""
private = Q() query, order, terms = build_note_query(request, search)
else: object_list = Note.objects \
# NON-AUTHENTICATED users .filter(query) \
private = Q(private=False) .distinct() \
if request.GET.has_key("search"): .order_by(*order)
search = request.GET.get("search")
object_list = Note.objects \
.filter((Q(gramps_id__icontains=search) |
Q(note_type__name__icontains=search) |
Q(text__icontains=search)) &
private
) \
.distinct() \
.order_by("gramps_id")
else:
object_list = Note.objects.filter(private).order_by("gramps_id")
view_template = 'view_notes.html' view_template = 'view_notes.html'
total = Note.objects.all().count() total = Note.objects.all().count()
elif view == "person": elif view == "person":
context["tviews"] = _("People") context["tviews"] = _("People")
search = request.GET.get("search") if request.GET.has_key("search") else "" search = request.GET.get("search") if request.GET.has_key("search") else ""
query, order = build_person_query(request, search) query, order, terms = build_person_query(request, search)
object_list = Name.objects \ object_list = Name.objects \
.filter(query) \ .filter(query) \
.distinct() \ .distinct() \
@ -330,7 +299,7 @@ def view_list(request, view):
elif view == "family": elif view == "family":
context["tviews"] = _("Families") context["tviews"] = _("Families")
search = request.GET.get("search") if request.GET.has_key("search") else "" search = request.GET.get("search") if request.GET.has_key("search") else ""
query, order = build_family_query(request, search) query, order, terms = build_family_query(request, search)
object_list = Family.objects \ object_list = Family.objects \
.filter(query) \ .filter(query) \
.distinct() \ .distinct() \
@ -339,118 +308,62 @@ def view_list(request, view):
total = Family.objects.all().count() total = Family.objects.all().count()
elif view == "place": elif view == "place":
context["tviews"] = _("Places") context["tviews"] = _("Places")
if request.user.is_authenticated(): search = request.GET.get("search") if request.GET.has_key("search") else ""
private = Q() query, order, terms = build_place_query(request, search)
else: object_list = Place.objects \
# NON-AUTHENTICATED users .filter(query) \
private = Q(private=False) .distinct() \
if request.GET.has_key("search"): .order_by(*order)
search = request.GET.get("search")
object_list = Place.objects \
.filter((Q(gramps_id__icontains=search) |
Q(title__icontains=search)
) &
private
) \
.distinct() \
.order_by("gramps_id")
else:
object_list = Place.objects.filter(private).order_by("gramps_id")
view_template = 'view_places.html' view_template = 'view_places.html'
total = Place.objects.all().count() total = Place.objects.all().count()
elif view == "repository": elif view == "repository":
context["tviews"] = _("Repositories") context["tviews"] = _("Repositories")
if request.user.is_authenticated(): search = request.GET.get("search") if request.GET.has_key("search") else ""
private = Q() query, order, terms = build_repository_query(request, search)
else: object_list = Repository.objects \
# NON-AUTHENTICATED users .filter(query) \
private = Q(private=False) .distinct() \
if request.GET.has_key("search"): .order_by(*order)
search = request.GET.get("search")
object_list = Repository.objects \
.filter((Q(gramps_id__icontains=search) |
Q(name__icontains=search) |
Q(repository_type__name__icontains=search)
) &
private
) \
.distinct() \
.order_by("gramps_id")
else:
object_list = Repository.objects.filter(private).order_by("gramps_id")
view_template = 'view_repositories.html' view_template = 'view_repositories.html'
total = Repository.objects.all().count() total = Repository.objects.all().count()
elif view == "citation": elif view == "citation":
context["tviews"] = _("Citations") context["tviews"] = _("Citations")
if request.user.is_authenticated(): search = request.GET.get("search") if request.GET.has_key("search") else ""
private = Q() query, order, terms = build_citation_query(request, search)
else: object_list = Citation.objects \
# NON-AUTHENTICATED users .filter(query) \
private = Q(private=False) .distinct() \
if request.GET.has_key("search"): .order_by(*order)
search = request.GET.get("search")
object_list = Citation.objects \
.filter(Q(gramps_id__icontains=search) &
private
) \
.distinct() \
.order_by("gramps_id")
else:
object_list = Citation.objects.filter(private).order_by("gramps_id")
view_template = 'view_citations.html' view_template = 'view_citations.html'
total = Citation.objects.all().count() total = Citation.objects.all().count()
elif view == "source": elif view == "source":
context["tviews"] = _("Sources") context["tviews"] = _("Sources")
if request.user.is_authenticated(): search = request.GET.get("search") if request.GET.has_key("search") else ""
private = Q() query, order, terms = build_source_query(request, search)
else: object_list = Source.objects \
# NON-AUTHENTICATED users .filter(query) \
private = Q(private=False) .distinct() \
if request.GET.has_key("search"): .order_by(*order)
search = request.GET.get("search")
object_list = Source.objects \
.filter(Q(gramps_id__icontains=search) &
private
) \
.distinct() \
.order_by("gramps_id")
else:
object_list = Source.objects.filter(private).order_by("gramps_id")
view_template = 'view_sources.html' view_template = 'view_sources.html'
total = Source.objects.all().count() total = Source.objects.all().count()
elif view == "tag": elif view == "tag":
context["tviews"] = _("Tags") context["tviews"] = _("Tags")
if request.GET.has_key("search"): search = request.GET.get("search") if request.GET.has_key("search") else ""
search = request.GET.get("search") query, order, terms = build_tag_query(request, search)
object_list = Tag.objects \ object_list = Tag.objects \
.filter(Q(name__icontains=search)) \ .filter(query) \
.distinct() \ .distinct() \
.order_by("name") .order_by(*order)
else:
object_list = Tag.objects.order_by("name")
view_template = 'view_tags.html' view_template = 'view_tags.html'
total = Tag.objects.all().count() total = Tag.objects.all().count()
elif view == "report": elif view == "report":
context["tviews"] = _("Reports") context["tviews"] = _("Reports")
if request.GET.has_key("search"): search = request.GET.get("search") if request.GET.has_key("search") else ""
search = request.GET.get("search") query, order, terms = build_report_query(request, search)
if request.user.is_superuser: object_list = Report.objects \
object_list = Report.objects \ .filter(query) \
.filter(Q(name__icontains=search)) \ .distinct() \
.distinct() \ .order_by(*order)
.order_by("name")
else:
object_list = Report.objects \
.filter(Q(name__icontains=search) & ~Q(report_type="import")) \
.distinct() \
.order_by("name")
else:
if request.user.is_superuser:
object_list = Report.objects.all().order_by("name")
else:
object_list = Report.objects \
.filter(~Q(report_type="import")) \
.order_by("name")
view_template = 'view_report.html' view_template = 'view_report.html'
total = Report.objects.all().count() total = Report.objects.all().count()
else: else:
@ -471,6 +384,7 @@ def view_list(request, view):
except (EmptyPage, InvalidPage): except (EmptyPage, InvalidPage):
page = paginator.page(paginator.num_pages) page = paginator.page(paginator.num_pages)
context["search_terms"] = ", ".join(terms)
context["page"] = page context["page"] = page
context["view"] = view context["view"] = view
context["tview"] = _(view.title()) context["tview"] = _(view.title())
@ -641,18 +555,18 @@ def build_person_query(request, search):
""" """
protect = not request.user.is_authenticated() protect = not request.user.is_authenticated()
### Build the order: ### Build the order:
terms = ["surname", "given"]
if protect: if protect:
# Do this to get the names sorted by private/alive # Do this to get the names sorted by private/alive
query = (Q(private=False) & Q(person__private=False)) query = Q(private=False) & Q(person__private=False)
order = ("surname__surname", "private", "person__probably_alive", order = ["surname__surname", "private", "person__probably_alive",
"first_name") "first_name"]
else: else:
query = Q() query = Q()
order = ("surname__surname", "first_name") order = ["surname__surname", "first_name"]
### Build the query: ### Build the query:
if search: if search:
if "," in search or "=" in search: if "," in search or "=" in search:
terms = ["surname", "given"]
for term in [term.strip() for term in search.split(",")]: for term in [term.strip() for term in search.split(",")]:
if "=" in term: if "=" in term:
field, value = [s.strip() for s in term.split("=")] field, value = [s.strip() for s in term.split("=")]
@ -693,46 +607,44 @@ def build_person_query(request, search):
else: # no search fields, just raw search else: # no search fields, just raw search
if protect: if protect:
query &= (Q(surname__surname__icontains=search) | query &= (Q(surname__surname__icontains=search) |
Q(surname__prefix__icontains=search) | Q(surname__prefix__icontains=search) |
Q(person__gramps_id__icontains=search)) Q(person__gramps_id__icontains=search))
else: else:
query &= (Q(surname__surname__icontains=search) | query &= (Q(surname__surname__icontains=search) |
Q(first_name__icontains=search) | Q(first_name__icontains=search) |
Q(suffix__icontains=search) | Q(suffix__icontains=search) |
Q(surname__prefix__icontains=search) | Q(surname__prefix__icontains=search) |
Q(title__icontains=search) | Q(title__icontains=search) |
Q(person__gramps_id__icontains=search)) Q(person__gramps_id__icontains=search))
else: # no search else: # no search
pass # nothing else to do pass # nothing else to do
return query, order #make_message(request, query)
return query, order, terms
def build_family_query(request, search): def build_family_query(request, search):
""" """
Build and return a Django QuerySet and sort order for the Family Build and return a Django QuerySet and sort order for the Family
table. table.
""" """
terms = ["father", "mother", "id", "type"]
protect = not request.user.is_authenticated() protect = not request.user.is_authenticated()
if protect: if protect:
query = (Q(private=False) & Q(father__private=False) & query = (Q(private=False) & Q(father__private=False) &
Q(mother__private=False)) Q(mother__private=False))
order = ("father__name__surname__surname", order = ["father__name__surname__surname",
"father__private", "father__probably_alive", "father__private", "father__probably_alive",
"father__name__first_name", "father__name__first_name",
"mother__name__surname__surname", "mother__name__surname__surname",
"mother__private", "mother__probably_alive", "mother__private", "mother__probably_alive",
"mother__name__first_name") "mother__name__first_name"]
else: else:
query = Q() query = Q()
order = ("father__name__surname__surname", order = ["father__name__surname__surname",
"father__name__first_name", "father__name__first_name",
"mother__name__surname__surname", "mother__name__surname__surname",
"mother__name__first_name") "mother__name__first_name"]
if search: if search:
if "," in search or "=" in search: if "," in search or "=" in search:
if "," not in search:
terms = ["surnames"]
else:
terms = ["father", "mother"]
for term in [term.strip() for term in search.split(",")]: for term in [term.strip() for term in search.split(",")]:
if "=" in term: if "=" in term:
field, value = [s.strip() for s in term.split("=")] field, value = [s.strip() for s in term.split("=")]
@ -752,6 +664,10 @@ def build_family_query(request, search):
query &= Q(father__name__surname__surname__istartswith=value) query &= Q(father__name__surname__surname__istartswith=value)
elif field == "mother": elif field == "mother":
query &= Q(mother__name__surname__surname__istartswith=value) query &= Q(mother__name__surname__surname__istartswith=value)
elif field == "type":
query &= Q(family_rel_type__name__icontains=value)
elif field == "id":
query &= Q(gramps_id__icontains=value)
else: else:
make_message(request, message="Invalid query field '%s'" % field) make_message(request, message="Invalid query field '%s'" % field)
else: # no search fields, just raw search else: # no search fields, just raw search
@ -768,7 +684,353 @@ def build_family_query(request, search):
else: # no search else: # no search
pass # nothing left to do pass # nothing left to do
#make_message(request, query) #make_message(request, query)
return query, order return query, order, terms
def build_media_query(request, search):
terms = ["id"]
protect = not request.user.is_authenticated()
if protect:
query = Q(private=False) # general privacy
order = ["gramps_id"]
else:
query = Q()
order = ["gramps_id"]
if search:
if "," in search or "=" in search:
for term in [term.strip() for term in search.split(",")]:
if "=" in term:
field, value = [s.strip() for s in term.split("=")]
else:
if terms:
field = terms.pop(0)
value = term
else:
continue
if "." in field and not protect:
query &= Q(**{field.replace(".", "__"): value})
elif field == "id":
query &= Q(gramps_id__icontains=value)
else:
request.user.message_set.create(message="Invalid query field '%s'" % field)
else: # no search fields, just raw search
if protect:
query &= Q(gramps_id__icontains=search)
else:
query &= Q(gramps_id__icontains=search)
else: # no search
pass # nothing left to do
return query, order, terms
def build_note_query(request, search):
terms = ["id", "type", "text"]
protect = not request.user.is_authenticated()
if protect:
query = Q(private=False) # general privacy
order = ["gramps_id"]
else:
query = Q()
order = ["gramps_id"]
if search:
if "," in search or "=" in search:
for term in [term.strip() for term in search.split(",")]:
if "=" in term:
field, value = [s.strip() for s in term.split("=")]
else:
if terms:
field = terms.pop(0)
value = term
else:
continue
if "." in field and not protect:
query &= Q(**{field.replace(".", "__"): value})
elif field == "id":
query &= Q(gramps_id__icontains=value)
elif field == "type":
query &= Q(note_type__name__icontains=value)
elif field == "text":
query &= Q(text__icontains=value)
else:
request.user.message_set.create(message="Invalid query field '%s'" % field)
else: # no search fields, just raw search
if protect:
query &= (Q(gramps_id__icontains=search) |
Q(note_type__name__icontains=search) |
Q(text__icontains=search))
else:
query &= (Q(gramps_id__icontains=search) |
Q(note_type__name__icontains=search) |
Q(text__icontains=search))
else: # no search
pass # nothing left to do
return query, order, terms
def build_place_query(request, search):
terms = ["id", "title"]
protect = not request.user.is_authenticated()
if protect:
query = Q(private=False) # general privacy
order = ["gramps_id"]
else:
query = Q()
order = ["gramps_id"]
if search:
if "," in search or "=" in search:
for term in [term.strip() for term in search.split(",")]:
if "=" in term:
field, value = [s.strip() for s in term.split("=")]
else:
if terms:
field = terms.pop(0)
value = term
else:
continue
if "." in field and not protect:
query &= Q(**{field.replace(".", "__"): value})
elif field == "id":
query &= Q(gramps_id__icontains=value)
elif field == "title":
query &= Q(title__icontains=value)
else:
request.user.message_set.create(message="Invalid query field '%s'" % field)
else: # no search fields, just raw search
if protect:
query &= (Q(gramps_id__icontains=search) |
Q(title__icontains=search))
else:
query &= (Q(gramps_id__icontains=search) |
Q(title__icontains=search))
else: # no search
pass # nothing left to do
return query, order, terms
def build_repository_query(request, search):
terms = ["id", "name", "type"]
protect = not request.user.is_authenticated()
if protect:
query = Q(private=False) # general privacy
order = ["gramps_id"]
else:
query = Q()
order = ["gramps_id"]
if search:
if "," in search or "=" in search:
for term in [term.strip() for term in search.split(",")]:
if "=" in term:
field, value = [s.strip() for s in term.split("=")]
else:
if terms:
field = terms.pop(0)
value = term
else:
continue
if "." in field and not protect:
query &= Q(**{field.replace(".", "__"): value})
elif field == "id":
query &= Q(gramps_id__icontains=value)
elif field == "name":
query &= Q(name__icontains=value)
elif field == "type":
query &= Q(repository_type__name__icontains=value)
else:
request.user.message_set.create(message="Invalid query field '%s'" % field)
else: # no search fields, just raw search
if protect:
query &= (Q(gramps_id__icontains=search) |
Q(name__icontains=search) |
Q(repository_type__name__icontains=search)
)
else:
query &= (Q(gramps_id__icontains=search) |
Q(name__icontains=search) |
Q(repository_type__name__icontains=search)
)
else: # no search
pass # nothing left to do
return query, order, terms
def build_citation_query(request, search):
terms = ["id"]
protect = not request.user.is_authenticated()
if protect:
query = Q(private=False) # general privacy
order = ["gramps_id"]
else:
query = Q()
order = ["gramps_id"]
if search:
if "," in search or "=" in search:
for term in [term.strip() for term in search.split(",")]:
if "=" in term:
field, value = [s.strip() for s in term.split("=")]
else:
if terms:
field = terms.pop(0)
value = term
else:
continue
if "." in field and not protect:
query &= Q(**{field.replace(".", "__"): value})
elif field == "id":
query &= Q(gramps_id__icontains=value)
else:
request.user.message_set.create(message="Invalid query field '%s'" % field)
else: # no search fields, just raw search
if protect:
query &= (Q(gramps_id__icontains=search))
else:
query &= (Q(gramps_id__icontains=search))
else: # no search
pass # nothing left to do
return query, order, terms
def build_source_query(request, search):
terms = ["id"]
protect = not request.user.is_authenticated()
if protect:
query = Q(private=False) # general privacy
order = ["gramps_id"]
else:
query = Q()
order = ["gramps_id"]
if search:
if "," in search or "=" in search:
for term in [term.strip() for term in search.split(",")]:
if "=" in term:
field, value = [s.strip() for s in term.split("=")]
else:
if terms:
field = terms.pop(0)
value = term
else:
continue
if "." in field and not protect:
query &= Q(**{field.replace(".", "__"): value})
elif field == "id":
query &= Q(gramps_id__icontains=value)
else:
request.user.message_set.create(message="Invalid query field '%s'" % field)
else: # no search fields, just raw search
if protect:
query &= Q(gramps_id__icontains=search)
else:
query &= Q(gramps_id__icontains=search)
else: # no search
pass # nothing left to do
return query, order, terms
def build_tag_query(request, search):
terms = ["name"]
protect = not request.user.is_authenticated()
if protect:
query = Q() # general privacy
order = ["name"]
else:
query = Q()
order = ["name"]
if search:
if "," in search or "=" in search:
for term in [term.strip() for term in search.split(",")]:
if "=" in term:
field, value = [s.strip() for s in term.split("=")]
else:
if terms:
field = terms.pop(0)
value = term
else:
continue
if "." in field and not protect:
query &= Q(**{field.replace(".", "__"): value})
elif field == "name":
query &= Q(name__icontains=value)
else:
request.user.message_set.create(message="Invalid query field '%s'" % field)
else: # no search fields, just raw search
if protect:
query &= Q(name__icontains=search)
else:
query &= Q(name__icontains=search)
else: # no search
pass # nothing left to do
return query, order, terms
def build_report_query(request, search):
terms = ["name"]
# NOTE: protection is based on super_user status
protect = not request.user.is_superuser
if protect:
query = ~Q(report_type="import") # general privacy
order = ["name"]
else:
query = Q()
order = ["name"]
if search:
if "," in search or "=" in search:
for term in [term.strip() for term in search.split(",")]:
if "=" in term:
field, value = [s.strip() for s in term.split("=")]
else:
if terms:
field = terms.pop(0)
value = term
else:
continue
if "." in field and not protect:
query &= Q(**{field.replace(".", "__"): value})
elif field == "name":
query &= Q(name__icontains=value)
else:
request.user.message_set.create(message="Invalid query field '%s'" % field)
else: # no search fields, just raw search
if protect:
query &= Q(name__icontains=search)
else:
query &= Q(name__icontains=search)
else: # no search
pass # nothing left to do
return query, order, terms
def build_event_query(request, search):
terms = ["id", "type", "place"]
protect = not request.user.is_authenticated()
if protect:
query = Q(private=False) # general privacy
order = ["gramps_id"]
else:
query = Q()
order = ["gramps_id"]
if search:
if "," in search or "=" in search:
for term in [term.strip() for term in search.split(",")]:
if "=" in term:
field, value = [s.strip() for s in term.split("=")]
else:
if terms:
field = terms.pop(0)
value = term
else:
continue
if "." in field and not protect:
query &= Q(**{field.replace(".", "__"): value})
elif field == "id":
query &= Q(gramps_id__icontains=value)
elif field == "type":
query &= Q(event_type__name__icontains=value)
elif field == "place":
query &= Q(place__title__icontains=value)
else:
request.user.message_set.create(message="Invalid query field '%s'" % field)
else: # no search fields, just raw search
if protect:
query &= (Q(gramps_id__icontains=search) |
Q(event_type__name__icontains=search) |
Q(place__title__icontains=search))
else:
query &= (Q(gramps_id__icontains=search) |
Q(event_type__name__icontains=search) |
Q(place__title__icontains=search))
else: # no search
pass # nothing left to do
return query, order, terms
def safe_int(num): def safe_int(num):
""" """
@ -811,3 +1073,4 @@ def process_reference(request, ref_by, handle, ref_to, order):
referenced_by.handle) referenced_by.handle)
context["action"] = "view" context["action"] = "view"
return render_to_response("reference.html", context) return render_to_response("reference.html", context)