Changes

Jump to: navigation, search

Gramps-Connect: Developer Introduction

2,228 bytes added, 01:54, 28 January 2013
m
gramps
Gramps developers are actively working on a version of Gramps thatruns on a web server, and displays one's family tree informationdynamically (as opposed to Gramps Narrated Web Report). This webapplication project is called Gramps-Connect. We have a workingdemonstration of this code available at http://gramps-connect.org. Itis written in Django, a Python web framework.
This page gives an introduction to Django for those that are already
familiar with Gramps data and Python. For more details on the specific Gramps Django interface, please see [[GEPS 013: Gramps Webapp]].
= Basic Django Structure =
The motivation and getting familiar with this project is provided in [[GEPS 013: Gramps Webapp]]. This dives into Django, from a getting started perspective. When you install and set up Django, all of the basic files are createdfor you with default settings. Django's[http://docs.djangoproject.com/en/1.1/ online documentation] and the[http://groups.google.com/group/django-users google group] areexcellent references. To follow is an outline of Django's filestructure, some important basics, and specific examples of ways towork with the Gramps dataset to create webpages.
In working with Gramps' Django files, there are four files that you may find yourself editing:
# [http://grampssvn.svncode.sourceforgesf.net/viewvcp/gramps/code/trunk/srcgramps/webwebapp/urls.py?view=log src/srcgramps/webwebapp/urls.py]# [http://grampssvn.svncode.sourceforgesf.net/viewvcp/gramps/code/trunk/srcgramps/webwebapp/grampsdb/views.py?view=log srcgramps/src/webwebapp/grampsdb/views.py]# [http://grampssvn.svncode.sourceforgesf.net/viewvcp/gramps/code/trunk/srcgramps/webwebapp/grampsdb/forms.py?view=log srcgramps/src/webwebapp/grampsdb/forms.py]# [http://grampssvn.svncode.sourceforgesf.net/viewvcp/gramps/code/trunk/src/data/templates src/data/templates/]
The template files have .html extensions and are found in thetemplates directory.
You will also find yourself referencing the
[http://grampssvn.svncode.sourceforgesf.net/viewvcp/gramps/code/trunk/srcgramps/webwebapp/grampsdb/models.py?view=log srcgramps/webwebapp/grampsdb/models.py] file, which defines the databasestructure. This file models the Gramps data as it exists in thedesktop Gramps application and will not require alteration unless thedatabase structure is changed. To access data from the database, youwill often reference the models.py file and refer to the tables andfields it defines.
We will now go through each of these files, exploring the use and format of each.
'''==urls.py'''==
urls.py is the file in which you define of all of the website's urls
mapped the url (e.g., ''person_detail'').
'''==views.py'''==
The functions that you map to your urls will exist in the views.py
<pre>
from webwebapp.grampsdb.models import *
def person_detail(request, ref):
fields like ''first'' and ''last name'' are displayed.
'''==Templates'''==
A template defines the html, but it is more than just an html file.
names in the dataset.
'''==forms.py'''==
Sometimes you want website users to be able to enter and edit data.
<pre>
from webwebapp.grampsdb.models import *
class PersonForm(forms.ModelForm):
<li>Last changed on {{PForm.last_changed.data}}</li>
</ul>
<input type="hidden" name="person-last_changed" id="id_person-last_changed" />
<input type="submit" value="Save" />
</form>
{% for field in form.visible_fields %}
<th>{{field.label_tag}}</th>
{% endfor %}
</tr>
{% endif %}
<tr><td> {# hidden fields for the form #}
{% for hidden in form.hidden_fields %}{{hidden }}{% endfor %}
</td></tr>
<tr> {# visible fields for the form #}
{% for field in form.visible_fields %}
<td>{{field}}</td>
{% endfor %}
</tr>
{% endif %}
<tr><td> {# hidden fields for the form #}
{% for hidden in form.hidden_fields %}{{hidden }}{% endfor %}
</td></tr>
<tr> {# visible fields for the form #}
{% for field in form.visible_fields %}
<td>{{field}}</td>
{% endfor %}
</tr>
{% endfor %}
</table>
<input type=”submit” value=”Save” />
= A Note on Error-Checking Forms =
When it came to working with the name formset, we wanted to be able tocheck to ensure that there was at least one name for the person andthat one and only one name was marked as preferred. Since we were usingthe view function uses an
an inline formset, which is not defined as a class, error-checking
became problematic. After much trial and error, my the solution was to
write an error-checking function outside the form classes (but it made
sense to store it in the forms.py file). We soon discovered thatSince
cleaned_data is only populated after running the clean functions and
only if the data is clean, so the data is accessed in a slightly
different manner. A string is returned with an error message (or an
empty string if all passed).
= A Little Javascript =
One of the javascript functions we added to the display screen handleschanging the display icon for the ''private'' fields. We decided toso that thedisplay the lock and unlock image files from the Gramps application can be used in
place of the default checkbox used by Django for Boolean fields.
First, though, the child template needs to handle loading the
</pre>
The ''onclick '' actions call the javascript function ''clickPrivate'', which
is written into the base.html file. So that this function can be used
for any number of ''private'' fields on the screen, this function is
written so that it will take the ''id '' of the page element calling it.
<pre>
}
</pre>
 
 
= Privacy =
''Currently, these are developer notes.''
 
One of the most important aspects of an on-line version of Gramps is the protection of sensitive data. There are two categories of sensitive data:
 
# data marked private
# people currently alive
 
Gramps core has developed a layered proxy wrapper system for protection of this sensitive data for reports. Gramps-Connect can use this, but only in limited fashion as we wish to talk directly to the databases in certain places:
 
# running a search query
# editing data using Django Forms
 
Gramps-Connect uses name-replacement to protect living people, and skips over private data. This strategy is generally how many genealogy sites work, but is also technically the easiest/fastest to use. Living people are determined by using the function Utils.probably_alive. This function is recursive and generally expensive in the number of queries which must be executed to determine if a person does not have a death event. Thus, it is advantageous to not run that query until you know you want to show some details of that person. On the other hand, private data can be determined easily as they have a property that directly reflects this value. Running a query to skip over private records can be initiated easily:
 
<pre>
object_list = Family.objects \
.filter((Q(gramps_id__icontains=search) |
Q(family_rel_type__name__icontains=search) |
Q(father__name__surname__istartswith=search) |
Q(mother__name__surname__istartswith=search)) &
Q(private=False) &
Q(father__private=False) &
Q(mother__private=False)
) \
.order_by("gramps_id")
</pre>
 
It would make much sense for probably_alive to be cached and stored on the person record, once it is determined. If that occurred, then living people could be excluded in top-level queries as are private data.
 
[[Category:Developers/General]]
[[Category:GEPS]]

Navigation menu