Skip to content

Commit

Permalink
Implemented foreign key cross-reference links. Refactored view metacl…
Browse files Browse the repository at this point in the history
…ass. Documented more existing features.
  • Loading branch information
kriskowal committed Jan 24, 2010
1 parent abc6783 commit c15c9c1
Show file tree
Hide file tree
Showing 9 changed files with 380 additions and 181 deletions.
1 change: 1 addition & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,5 @@ In future versions, Djata should support:
- A progressively enhanced, cross-referenced, HTML user interface.
- Custom views for viewing and editing charts, graphs, and trees.
- Throttling and Pacing
- Generalize for inter-application cross-references

14 changes: 12 additions & 2 deletions docs/quick-start.rst
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ documentation <views.rst>`_ for more information on customizing views.

Alternately, if you would just like to automatically generate a Djata view
for every model in your models file, you can use the ``views_from_models``
function
function.

``example/views.py``::

Expand All @@ -47,7 +47,17 @@ function

You can blend both approaches by customizing particular models after you
construct the views object. If you do not create a views object, it will be
created automatically by the first view class you declare.
created automatically by the first view class you declare. The
``views_from_models`` function accepts an optional ``exclude`` argument to
suprress generation of views for the named models::

from djata.views import *
import example.models as models
views = views_from_models(models, exclude = ('Bar',))

class Bar(View):
class Meta:
verbose_name_plural = 'barrii'

At the time of this writing, recent versions of Django expose the model's
``verbose_name`` and ``verbose_name_plural`` (that Django uses for URLs of
Expand Down
18 changes: 18 additions & 0 deletions docs/views.rst
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,24 @@ various properties to the ``Meta`` metadata class for your view.
on the views module. If neither the class or module specify a format,
requesting on a URL for the model without providing a format extension will
result in a "No format specified error".
- ``objects`` and ``fields``, compatible with the corresponding properties
of a model, may be provided as an alternative to using Django storage.
``objects.get(pk)``, ``fields.rel.to.objects.get(pk)``, ``fields.name``,
and ``fields.value_from_object(object)`` must be supported.
- ``include_fields`` white-lists certain fields by name. No others will
be available.
- ``exclude_fields`` black-lists certain fields by name. All others will
be available.
- ``exclude_methods`` black lists any set of ``GET``, ``PUT``,
``POST``, ``DELETE``
- ``exclude_actions`` black lists any set of ``read``, ``write``, ``add``,
``change``, ``delete``
- ``exclude_model_formats``
- ``exclude_object_formats``
- ``exclude_model_parsers``
- ``exclude_object_parsers``
- ``exclude_model_pages``
- ``exclude_object_pages``

The ``djata.views.ViewBase`` supports all the features of a ``View``
class but does not support any formats. This is a good base
Expand Down
62 changes: 53 additions & 9 deletions formats/format_html.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,41 @@ def process(self, request, view):
context = request.context
object = view.get_object()
fields = view.get_fields()
parent_fields = None # XXX
child_fields = view.get_child_fields()
related_fields = view.get_related_fields()
context['object'] = object
context['fields'] = fields
context['related_fields'] = related_fields
context['child_fields'] = related_fields
context['items'] = [
{
'name': field.name,
'value': field.value_from_object(object)
'value': cell(field, object, view)
}
for field in fields
]
context['child_items'] = [
{
'name': field.var_name,
'items': [
ChildCell(item, view)
for item in
field.model.objects.filter(**{
field.field.name: object,
})
]
}
for field in child_fields
]
context['related_items'] = [
{
'name': field.name,
'items': [
]
}
for field in related_fields
]

class HtmlObjectFormat(RawHtmlObjectFormat):
template = 'djata/object.html'
Expand All @@ -43,7 +69,7 @@ def process(self, request, view):
context['fields'] = fields
context['table'] = [
[
cell(field, object)
cell(field, object, view)
for field in fields
]
for object in objects
Expand Down Expand Up @@ -88,23 +114,41 @@ def process(self, request, view):
context['form'] = form_for_model(view.meta.model)(instance = object)
super(HtmlAddFormat, self).process(request, view)

def cell(field, object):
value = field.value_from_object(object)
def cell(field, object, view):
value = get_object_field_value(object, field)
if value is None:
return
else:
return Cell(field, object, value)
return Cell(field, object, view, value)

class Cell(object):
def __init__(self, field, object, value):
def __init__(self, field, object, view, value):
self.field = field
self.object = object
self.view = view
self.value = value
def __unicode__(self):
return unicode(self.value)
@property
def url(self):
if not isinstance(self.field, ForeignKey):
return
return '#'
if self.field.primary_key:
return self.view.get_url_of_object(self.object)
elif isinstance(self.field, ForeignKey):
return self.view.get_url_of_object(self.value)

class ChildCell(object):
def __init__(self, object, view):
self.object = object
self.view = view
def __unicode__(self):
return unicode(self.object)
@property
def url(self):
return self.view.get_url_of_object(self.object)

def get_object_field_value(object, field):
value = field.value_from_object(object)
if isinstance(field, ForeignKey) and value is not None:
value = field.rel.to.objects.get(pk = value)
return value

16 changes: 16 additions & 0 deletions media/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,22 @@ p, td, th {
text-align: justify;
}

a {
color: #0000aa;
}

a:active {
color: #aaaaaa;
}

a:visited {
color: #777777;
}

a:hover {
color: #0000ff;
}

.code {
font-size: 11px;
font-family: Monaco, monospace;
Expand Down
7 changes: 7 additions & 0 deletions templates/djata/cell.raw.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{% if cell.url %}
<a href="{{cell.url}}">
{{cell|default_if_none:""|escape|default:"&nbsp;"}}
</a>
{% else %}
{{cell|default_if_none:""|escape|default:"&nbsp;"}}
{% endif %}
10 changes: 1 addition & 9 deletions templates/djata/model.raw.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,7 @@
{% for row in table %}
<tr>
{% for cell in row %}
<td>
{% if cell.url %}
<a href="{{cell.url}}">
{{cell|default_if_none:""|escape|default:"&nbsp;"}}
</a>
{% else %}
{{cell|default_if_none:""|escape|default:"&nbsp;"}}
{% endif %}
</td>
<td>{% include "djata/cell.raw.html" %}</td>
{% endfor %}
</tr>
{% endfor %}
Expand Down
30 changes: 29 additions & 1 deletion templates/djata/object.raw.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,35 @@
{% for item in items %}
<tr>
<th>{{item.name|escape}}:</th>
<td>{{item.value|default_if_none:""|escape|default:"&nbsp;"}}</td>
<td>
{% with item.value as cell %}
{% include "djata/cell.raw.html" %}
{% endwith %}
</td>
</tr>
{% endfor %}
{% for item in child_items %}
<tr>
<th>{{item.name|escape}}:</th>
<td>
<ul>
{% for cell in item.items %}
<li>{% include "djata/cell.raw.html" %}</li>
{% endfor %}
</ul>
</td>
</tr>
{% endfor %}
{% for item in related_items %}
<tr>
<th>{{item.name|escape}}:</th>
<td>
<ul>
{% for cell in item.items %}
<li>{% include "djata/cell.raw.html" %}</li>
{% endfor %}
</ul>
</td>
</tr>
{% endfor %}
</table>
Loading

0 comments on commit c15c9c1

Please sign in to comment.