Django (django_tables2) ValueError: Ожидаемая таблица или набор запросов, а не str + для проблемы цикла - PullRequest
0 голосов
/ 18 октября 2018

У меня есть проект Django, который находится под сильным влиянием учебника Mozilla по Django (https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website). Я изменил books на samples, и каждый из них samples связан с исследователем / pi (он же author). Я создал отдельную модель с именем Variant, которая является иностранным ключом для модели Sample. Поскольку в этом поле будет разрешено несколько вариантов для каждого образца, при просмотре подробного вида образца яЯ хотел бы отобразить варианты (специфичные для отдельного образца) в виде отрисованной таблицы. Мне не удалось этого добиться, и я думаю, что просто не совсем правильно понимаю номенклатуру представления (а также язык в html-файле)Мои вопросы находятся в конце этого поста.

Вот мой код.

samples / models.py

class Variant(models.Model):
   gene = models.CharField('Gene', max_length=100, blank=True, default='')
   variant = models.CharField('Variant', max_length=50, blank=True, default='')
   call = models.CharField('Call', max_length=100, blank=True, default='')
   position = models.IntegerField('Position', blank=True, null=True) 

   def __str__(self):
      return f'{self.gene}, {self.position}, {self.variant}, {self.call}'

class Sample(models.Model):
   sample_name = models.CharField('Sample', max_length=16)
   pi = models.ForeignKey(PI, on_delete=models.SET_NULL, null=True)
   sample_variant = models.ForeignKey(Variant, on_delete=models.SET_NULL, null=True) 
     .
     .
     .
   def __str__(self):
      return self.sample_name

   def get_absolute_url(self):
      return reverse('sample-detail', args=[str(self.id)])

tables.py

class SampleTable(tables.Table):
   sample_name = tables.LinkColumn('sample-detail', args=[A('pk')])
   pi = tables.LinkColumn('sample-detail', args=[A('pk')])

   class Meta:
      model = Sample
#----------------------------------------------------------------------------

#----------------------------------------------------------------------------
class PISampleTable(tables.Table):
   sample_name = tables.LinkColumn('sample-detail', args=[A('pk')])

   class Meta:
      model = Sample
#----------------------------------------------------------------------------

...
#----------------------------------------------------------------------------
class VariantTable(tables.Table):
   gene = tables.LinkColumn('sample-detail', args=[A('pk')])

   class Meta:
      model = Variant
#----------------------------------------------------------------------------

Я не уверен, что установка гена (поле Variant), как я это сделал, является уксусной.

class SampleListView(generic.ListView):
   model = Sample
   paginate_by = 100

@login_required
def sam(request):
   table = SampleTable(Sample.objects.all())
   RequestConfig(request).configure(table)
   return render(request, 'samples/sample_list.html', {'sam': table}) 
#-------------------------------------------------------------------------------------------------

#-------------------------------------------------------------------------------------------------
class SampleDetailView(generic.DetailView):
    model = Sample
#-------------------------------------------------------------------------------------------------

    ...
#-------------------------------------------------------------------------------------------------
class VariantListView(generic.ListView):
   model = Variant
   paginate_by = 100

@login_required
def var(request):
   #table = VariantTable(Variant.objects.filter(pi=pk))
   table = VariantTable(Variant.objects.all())
   RequestConfig(request).configure(table)
   return render(request, 'samples/sample_detail.html', {'var': table}) 
#-------------------------------------------------------------------------------------------------

samples / urls.py

urlpatterns = [ 
   path('', views.index, name='index'),
   path('samples/', views.sam, name='sam'),
   path('sample/<int:pk>', views.SampleDetailView.as_view(), name='sample-detail'),
   path('pi/', views.pi_table, name='pi_table'),
   path('pi/<int:pk>', views.pi_view, name='pi-detail'),
   path('samples/new', views.pi_new, name='pi_new'),
   path('samples/new_sample', views.sample_new, name='sample_new'),
   #path('samples/', views.var, name='var'),
   #path('samples/<int:pk>', views.var, name='var'),
   path('samples/', views.VariantListView.as_view(), name='var'),
]

samples / templates / samples / sample_detail.html

 {% extends "base_generic.html" %}
{% load render_table from django_tables2 %}

{% block content %}
   <h1>Sample: {{ sample.sample_name }}</h1>

   <p><strong>PI:</strong> <a href="{% url 'pi-detail' sample.pi.pk %}">{{ sample.pi }}</a></p>
   ...
   <h3>Variant Results</h3>
   <p><strong>(gene, position, variant, call):</strong> {{ sample.sample_variant }}</p> <!-- this works, but only last item in list-->


  <p><strong>Variant:</strong> {% for variant in sample.sample_variant.all %} {{ variant }}{% if not forloop.last %}, {% endif %}{% endfor %}</p>

  {% if sample.sample_variant %}
  <ul>

   {% for variant in variant_list %}
     <li> <a href="{{ variant.get_absolute_url }}">{{ variant.gene }}</a> ({{variant.call}})</li>
   {% endfor %}
  </ul>
  {% else %}
    <p>There are no variants for this sample.</p>                                                                                                                                    

  {% endif %}       

{% render_table var %}

{% endblock %} 

Чтобы проверить это, у меня есть один пример, к которому я добавил два варианта - однако толькопоследний вариант отображается из этого (понятно):

<p><strong>(gene, position, variant, call):</strong> {{ sample.sample_variant }}

Код цикла - это то, с чем я играл, но он не работает вообще, и если я буду держать строку {% render_table var %} там, я будуполучить эту ошибку:

  File "/opt/miniconda3/envs/py37/lib/python3.7/site-packages/django/template/response.py", line 83, in rendered_content
    content = template.render(context, self._request)
  File "/opt/miniconda3/envs/py37/lib/python3.7/site-packages/django/template/backends/django.py", line 61, in render
    return self.template.render(context)
  File "/opt/miniconda3/envs/py37/lib/python3.7/site-packages/django/template/base.py", line 171, in render
    return self._render(context)
  File "/opt/miniconda3/envs/py37/lib/python3.7/site-packages/django/template/base.py", line 163, in _render
    return self.nodelist.render(context)
  File "/opt/miniconda3/envs/py37/lib/python3.7/site-packages/django/template/base.py", line 937, in render
    bit = node.render_annotated(context)
  File "/opt/miniconda3/envs/py37/lib/python3.7/site-packages/django/template/base.py", line 904, in render_annotated
    return self.render(context)
  File "/opt/miniconda3/envs/py37/lib/python3.7/site-packages/django/template/loader_tags.py", line 150, in render
    return compiled_parent._render(context)
  File "/opt/miniconda3/envs/py37/lib/python3.7/site-packages/django/template/base.py", line 163, in _render
    return self.nodelist.render(context)
  File "/opt/miniconda3/envs/py37/lib/python3.7/site-packages/django/template/base.py", line 937, in render
    bit = node.render_annotated(context)
  File "/opt/miniconda3/envs/py37/lib/python3.7/site-packages/django/template/base.py", line 904, in render_annotated
    return self.render(context)
  File "/opt/miniconda3/envs/py37/lib/python3.7/site-packages/django/template/loader_tags.py", line 62, in render
    result = block.nodelist.render(context)
  File "/opt/miniconda3/envs/py37/lib/python3.7/site-packages/django/template/base.py", line 937, in render
    bit = node.render_annotated(context)
  File "/opt/miniconda3/envs/py37/lib/python3.7/site-packages/django/template/base.py", line 904, in render_annotated
    return self.render(context)
  File "/opt/miniconda3/envs/py37/lib/python3.7/site-packages/django_tables2/templatetags/django_tables2.py", line 148, in render
    raise ValueError("Expected table or queryset, not {}".format(klass))
ValueError: Expected table or queryset, not str

Я понимаю, что ошибка вызвана передачей строки вместо объекта класса queryset / table, но я не выяснил, как ее исправить.

Версия django_tables2 является текущей и отображает другие таблицы без проблем.

  1. Я связал gene со столбцом аналогично тому, как я делал для полей в других моделях (sample_name иpi) - это правильно?
  2. Как я мог организовать цикл for для правильного отображения всех вариантов в списке?
  3. Что мне нужно изменить (при условии)файл views.py для правильной визуализации varтаблица?
  4. Я не уверен, что правильно указал путь (я пробовал несколько вариантов безуспешно) в urls.py, как его правильно структурировать, если он неверен?

Огромная благодарность и благодарность за любую помощь.

1 Ответ

0 голосов
/ 19 октября 2018

Хорошо - большое спасибо другу (AR), который помог мне отследить ошибку.

Первая проблема заключается в том, что у меня были неправильные отношения;иностранный ключ должен быть в модели Variant, а не в модели Sample (sample_variant в Sample модель была удалена).

models.py

class Variant(models.Model):                                                              
   gene = models.CharField('Gene', max_length=100, blank=True, default='')
   nucleotide_variant = models.CharField('Variant', max_length=50, blank=True, default='')   call = models.CharField('Call', max_length=100, blank=True, default='')
   position = models.IntegerField('Position', blank=True, null=True) 
   sample_n = models.ForeignKey(Sample, on_delete=models.SET_NULL, null=True)

   class Meta:
      ordering = ('sample_n', 'gene', 'position', 'nucleotide_variant', 'call')

   def __str__(self):
      return f'{self.sample_n}, {self.gene}, {self.position}, {self.nucleotide_variant}, {self.call}'

Следующее, что я изменил поле variant на nucleotide_variant.Это может быть ненужным, но для меня это стало понятнее.

views.py

class VariantListView(generic.ListView):
   model = Variant
   paginate_by = 100 

@login_required
def var(request):
   variant = Variant.objects.get(pk = pk) 
   table = VariantTable(Variant.objects.filter(variant=pk))
   RequestConfig(request).configure(table)                                                
   return render(request, 'samples/sample_detail.html', {'variant': variant, 'var': table}) 

urls.py

path('samples/', views.var, name='var'),

html

   <h3>Variant Results</h3>
   {% render_table sample.variant_set.all %}

Проблема решена, таблица обработана.

...