I'm trying to write a UsersTable
class with django-tables2
to be sub-classed by StudentsTable
. This code works fine:
tables.py
import django_tables2 as tables
from django_tables2.utils import A # alias for accessor
from .models.environment import Student
def getEditColumn(accessor, kwargs):
return tables.LinkColumn(
viewname='wakemeup:edit_object',
kwargs=kwargs,
verbose_name='',
text='Editar',
accessor=accessor
)
class UsersTable(tables.Table):
# Define constructor
def __init__(self, *args, **kwargs):
# Call base table class constructor
super(UsersTable, self).__init__(data = kwargs['data'])
objectid = kwargs['objectid']
objecttype = kwargs['objecttype']
# Create base attributes
self.objectid = objectid
self.objecttype = objecttype
self.mykwargs={
'objecttype': objecttype,
'objectid': A(objectid)
}
self.edit_link = getEditColumn(objectid, self.mykwargs)
class Meta:
model = Student
class StudentsTable(UsersTable):
# Call UsersTable constructor
def __init__(self, *args, **kwargs):
super(StudentsTable, self).__init__(*args, **kwargs)
print(self.edit_link) # Verify edit_link has been generated
class Meta:
sequence = ('firstname','lastname','emailaddress','phonenumber','defaultsignaturescanfile','classid')
However, when I try to reference the edit_link
column inherited from UsersTable
, I get an error:
Modified StudentsTable
class StudentsTable(UsersTable):
# Call UsersTable constructor
def __init__(self, *args, **kwargs):
super(StudentsTable, self).__init__(*args, **kwargs)
print(self.edit_link) # Verify edit_link has been generated
class Meta:
exclude = ('studentuserid','reputationvalue','schoolid')
sequence = ('firstname','lastname','emailaddress','phonenumber','defaultsignaturescanfile','classid','edit_link')
Error
Exception Type: KeyError
Exception Value: 'edit_link'
It seems like the Meta
class info is being read before the inherited edit_link
column is generated. The print(edit_link)
line returns the expected object, so the field is available.
I tried all kinds of futzing around with the Meta class...but no luck. Can someone please help me out?
Here's the trace:
Environment:
Request Method: GET
Request URL: http://127.0.0.1:8000/wakemeup/admin/student
Django Version: 2.0.1
Python Version: 3.6.4
Installed Applications:
['django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'users.apps.UsersConfig',
'wakemeup.apps.WakemeupConfig',
'crispy_forms',
'django_tables2']
Installed Middleware:
('whitenoise.middleware.WhiteNoiseMiddleware',
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware')
Template error:
In template C:\Program Files (x86)\Python36-32\lib\site-packages\django_tables2\templates\django_tables2\bootstrap.html, error at line 11
edit_link
1 : {% load django_tables2 %}
2 : {% load i18n %}
3 : {% block table-wrapper %}
4 : <div class="table-container">
5 : {% block table %}
6 : <table {% if table.attrs %} {{ table.attrs.as_html }}{% else %}class="table"{% endif %}>
7 : {% block table.thead %}
8 : {% if table.show_header %}
9 : <thead>
10 : <tr>
11 : {% for column in table.columns %}
12 : {% if column.orderable %}
13 : <th {{ column.attrs.th.as_html }}><a href="{% querystring table.prefixed_order_by_field=column.order_by_alias.next %}">{{ column.header }}</a></th>
14 : {% else %}
15 : <th {{ column.attrs.th.as_html }}>{{ column.header }}</th>
16 : {% endif %}
17 : {% endfor %}
18 : </tr>
19 : </thead>
20 : {% endif %}
21 : {% endblock table.thead %}
Traceback:
File "C:\Program Files (x86)\Python36-32\lib\site-packages\django\core\handlers\exception.py" in inner
35. response = get_response(request)
File "C:\Program Files (x86)\Python36-32\lib\site-packages\django\core\handlers\base.py" in _get_response
128. response = self.process_exception_by_middleware(e, request)
File "C:\Program Files (x86)\Python36-32\lib\site-packages\django\core\handlers\base.py" in _get_response
126. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "c:\Users\ravioli\eclipse-workspace\dcp\wakemeup\views.py" in admin_list
100. return render(request, 'wakemeup/admin/index.html', {'objects' : objectSet, 'objecttype': objecttype})
File "C:\Program Files (x86)\Python36-32\lib\site-packages\django\shortcuts.py" in render
36. content = loader.render_to_string(template_name, context, request, using=using)
File "C:\Program Files (x86)\Python36-32\lib\site-packages\django\template\loader.py" in render_to_string
62. return template.render(context, request)
File "C:\Program Files (x86)\Python36-32\lib\site-packages\django\template\backends\django.py" in render
61. return self.template.render(context)
File "C:\Program Files (x86)\Python36-32\lib\site-packages\django\template\base.py" in render
175. return self._render(context)
File "C:\Program Files (x86)\Python36-32\lib\site-packages\django\template\base.py" in _render
167. return self.nodelist.render(context)
File "C:\Program Files (x86)\Python36-32\lib\site-packages\django\template\base.py" in render
943. bit = node.render_annotated(context)
File "C:\Program Files (x86)\Python36-32\lib\site-packages\django\template\base.py" in render_annotated
910. return self.render(context)
File "C:\Program Files (x86)\Python36-32\lib\site-packages\django\template\loader_tags.py" in render
155. return compiled_parent._render(context)
File "C:\Program Files (x86)\Python36-32\lib\site-packages\django\template\base.py" in _render
167. return self.nodelist.render(context)
File "C:\Program Files (x86)\Python36-32\lib\site-packages\django\template\base.py" in render
943. bit = node.render_annotated(context)
File "C:\Program Files (x86)\Python36-32\lib\site-packages\django\template\base.py" in render_annotated
910. return self.render(context)
File "C:\Program Files (x86)\Python36-32\lib\site-packages\django\template\loader_tags.py" in render
67. result = block.nodelist.render(context)
File "C:\Program Files (x86)\Python36-32\lib\site-packages\django\template\base.py" in render
943. bit = node.render_annotated(context)
File "C:\Program Files (x86)\Python36-32\lib\site-packages\django\template\base.py" in render_annotated
910. return self.render(context)
File "C:\Program Files (x86)\Python36-32\lib\site-packages\django\template\loader_tags.py" in render
67. result = block.nodelist.render(context)
File "C:\Program Files (x86)\Python36-32\lib\site-packages\django\template\base.py" in render
943. bit = node.render_annotated(context)
File "C:\Program Files (x86)\Python36-32\lib\site-packages\django\template\base.py" in render_annotated
910. return self.render(context)
File "C:\Program Files (x86)\Python36-32\lib\site-packages\django_tables2\templatetags\django_tables2.py" in render
169. return template.render(context={'table': table}, request=request)
File "C:\Program Files (x86)\Python36-32\lib\site-packages\django\template\backends\django.py" in render
61. return self.template.render(context)
File "C:\Program Files (x86)\Python36-32\lib\site-packages\django\template\base.py" in render
175. return self._render(context)
File "C:\Program Files (x86)\Python36-32\lib\site-packages\django\template\base.py" in _render
167. return self.nodelist.render(context)
File "C:\Program Files (x86)\Python36-32\lib\site-packages\django\template\base.py" in render
943. bit = node.render_annotated(context)
File "C:\Program Files (x86)\Python36-32\lib\site-packages\django\template\base.py" in render_annotated
910. return self.render(context)
File "C:\Program Files (x86)\Python36-32\lib\site-packages\django\template\loader_tags.py" in render
155. return compiled_parent._render(context)
File "C:\Program Files (x86)\Python36-32\lib\site-packages\django\template\base.py" in _render
167. return self.nodelist.render(context)
File "C:\Program Files (x86)\Python36-32\lib\site-packages\django\template\base.py" in render
943. bit = node.render_annotated(context)
File "C:\Program Files (x86)\Python36-32\lib\site-packages\django\template\base.py" in render_annotated
910. return self.render(context)
File "C:\Program Files (x86)\Python36-32\lib\site-packages\django\template\loader_tags.py" in render
67. result = block.nodelist.render(context)
File "C:\Program Files (x86)\Python36-32\lib\site-packages\django\template\base.py" in render
943. bit = node.render_annotated(context)
File "C:\Program Files (x86)\Python36-32\lib\site-packages\django\template\base.py" in render_annotated
910. return self.render(context)
File "C:\Program Files (x86)\Python36-32\lib\site-packages\django\template\loader_tags.py" in render
67. result = block.nodelist.render(context)
File "C:\Program Files (x86)\Python36-32\lib\site-packages\django\template\base.py" in render
943. bit = node.render_annotated(context)
File "C:\Program Files (x86)\Python36-32\lib\site-packages\django\template\base.py" in render_annotated
910. return self.render(context)
File "C:\Program Files (x86)\Python36-32\lib\site-packages\django\template\base.py" in render
993. output = self.filter_expression.resolve(context)
File "C:\Program Files (x86)\Python36-32\lib\site-packages\django\template\base.py" in resolve
676. obj = self.var.resolve(context)
File "C:\Program Files (x86)\Python36-32\lib\site-packages\django\template\base.py" in resolve
802. value = self._resolve_lookup(context)
File "C:\Program Files (x86)\Python36-32\lib\site-packages\django\template\base.py" in _resolve_lookup
864. current = current()
File "C:\Program Files (x86)\Python36-32\lib\site-packages\django\template\loader_tags.py" in super
81. return mark_safe(self.render(self.context))
File "C:\Program Files (x86)\Python36-32\lib\site-packages\django\template\loader_tags.py" in render
67. result = block.nodelist.render(context)
File "C:\Program Files (x86)\Python36-32\lib\site-packages\django\template\base.py" in render
943. bit = node.render_annotated(context)
File "C:\Program Files (x86)\Python36-32\lib\site-packages\django\template\base.py" in render_annotated
910. return self.render(context)
File "C:\Program Files (x86)\Python36-32\lib\site-packages\django\template\loader_tags.py" in render
67. result = block.nodelist.render(context)
File "C:\Program Files (x86)\Python36-32\lib\site-packages\django\template\base.py" in render
943. bit = node.render_annotated(context)
File "C:\Program Files (x86)\Python36-32\lib\site-packages\django\template\base.py" in render_annotated
910. return self.render(context)
File "C:\Program Files (x86)\Python36-32\lib\site-packages\django\template\defaulttags.py" in render
314. return nodelist.render(context)
File "C:\Program Files (x86)\Python36-32\lib\site-packages\django\template\base.py" in render
943. bit = node.render_annotated(context)
File "C:\Program Files (x86)\Python36-32\lib\site-packages\django\template\base.py" in render_annotated
910. return self.render(context)
File "C:\Program Files (x86)\Python36-32\lib\site-packages\django\template\defaulttags.py" in render
168. len_values = len(values)
File "C:\Program Files (x86)\Python36-32\lib\site-packages\django_tables2\columns\base.py" in __len__
686. return len(self.visible())
File "C:\Program Files (x86)\Python36-32\lib\site-packages\django_tables2\columns\base.py" in visible
643. return list(self.itervisible())
File "C:\Program Files (x86)\Python36-32\lib\site-packages\django_tables2\columns\base.py" in <genexpr>
640. return (x for x in self.iterall() if x.visible)
File "C:\Program Files (x86)\Python36-32\lib\site-packages\django_tables2\columns\base.py" in <genexpr>
597. return (column for name, column in self.iteritems())
File "C:\Program Files (x86)\Python36-32\lib\site-packages\django_tables2\columns\base.py" in iteritems
614. yield (name, self.columns[name])
Exception Type: KeyError at /wakemeup/admin/student
Exception Value: 'edit_link'
I believe you have two issues with your code. Firstly the Meta
attribute class on StudentsTable
needs to inherit the UserTable.Meta
attribute, or else it will not have model
defined:
class StudentsTable(UsersTable):
# Call UsersTable constructor
def __init__(self, *args, **kwargs):
super(StudentsTable, self).__init__(*args, **kwargs)
print(self.edit_link) # Verify edit_link has been generated
class Meta(UsersTable.Meta):
sequence = ('firstname','lastname','emailaddress','phonenumber','defaultsignaturescanfile','classid')
Secondarily, the docs for django-tables2
says that sequence
enumerates columns. Columns are either fields
on the underlying model or column attributes of the table class
:
class StudentsTable(UsersTable):
edit_link = tables.LinkColumn(viewname='wakemeup:edit_object', text='Editar')
Rather than defining editLink
on the instance in the __init__
method.
To load keyword arguments for the link from the model and table instance, you'll need to pass accessor
instances to the Column
rather than the literal kwarg values. The docs for LinkColumn
indicate that should be done like this:
from django_tables2.utils import A
class StudentsTable(UsersTable):
edit_link = tables.LinkColumn(viewname='wakemeup:edit_object', text='Editar', kwargs={"name": A("name"))
This means you'll need to define which kwargs you need explicitly, rather than dynamically, which should not be a problem for you given that these are URL arguments that are defined as a contract somewhere.