Мета-класс Python и наследование - атрибуты не распознаны (django-tables2) - PullRequest
0 голосов
/ 29 июня 2018

Я пытаюсь написать класс UsersTable с django-tables2, который будет классифицирован как StudentsTable. Этот код отлично работает:

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')

Однако, когда я пытаюсь сослаться на столбец edit_link, унаследованный от UsersTable, я получаю сообщение об ошибке:

Измененная таблица студентов

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')

Ошибка

Exception Type: KeyError
Exception Value: 'edit_link'

Кажется, что информация класса Meta читается до того, как генерируется унаследованный столбец edit_link. Строка print(edit_link) возвращает ожидаемый объект, поэтому поле доступно.

Я перепробовал все виды занятий с классом Meta, но не повезло.

Редактировать

Вот след:

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'

1 Ответ

0 голосов
/ 29 июня 2018

Я полагаю, у вас есть две проблемы с вашим кодом. Во-первых, класс атрибута Meta в StudentsTable должен наследовать атрибут UserTable.Meta, иначе он не будет определен model:

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')

Во-вторых, документы для django-tables2 говорят, что sequence перечисляет столбцы. Столбцы либо fields в базовой модели , либо атрибуты столбца таблицы class:

class StudentsTable(UsersTable):
    edit_link = tables.LinkColumn(viewname='wakemeup:edit_object', text='Editar')

Вместо определения editLink для экземпляра в методе __init__.

Чтобы загрузить ключевые аргументы для ссылки из экземпляра модели и таблицы, вам нужно передать accessor экземпляров в Column, а не в буквальные значения kwarg. Документы для LinkColumn указывают, что должно быть сделано , как это :

from django_tables2.utils import A 

class StudentsTable(UsersTable):
    edit_link = tables.LinkColumn(viewname='wakemeup:edit_object', text='Editar', kwargs={"name": A("name"))

Это означает, что вам нужно определить, какие kwargs вам нужны явно, а не динамически, что не должно быть проблемой для вас, учитывая, что это аргументы URL, которые где-то определены как контракт.

...