Django (django_tables2) ValueError: Expected table or queryset, not str + for loop issue
Django (django_tables2) ValueError: Expected table or queryset, not str + for loop issue
我有一个受 Mozilla 的 Django 教程 (https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website) 影响很大的 Django 项目。我已将 books
修改为 samples
,其中每个 samples
都隶属于研究员/pi
(又名 author
)。我创建了一个名为 Variant
的单独模型,它是 Sample
模型的外键。由于此字段将允许每个样本有多个变体,因此在查看样本的详细视图时,我想将变体(特定于单个样本)显示为渲染 table。我没有成功实现这一目标,我认为我只是没有完全正确地命名视图(以及 html 文件中的语言)。我的问题在这个 post 的末尾。
这是我的代码。
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
#----------------------------------------------------------------------------
我不确定像我这样设置基因(变异域)是否是copacetic。
samples/views.py
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 class 对象引起的,但我还没有想出如何解决它。
django_tables2 版本是最新的,正在渲染其他 table 没有问题。
- 我以与其他模型(
sample_name
和 pi
)中的字段类似的方式将 gene
链接到一个列 - 它是否正确?
- 我如何安排 for 循环以正确显示列表中的所有变体?
- 我需要在(假设)views.py 文件中更改什么才能正确呈现
var
table?
- 我不相信我在 urls.py 中正确列出了路径(我尝试了几种变体但没有成功),如果不正确应该如何正确构建?
非常感谢和赞赏任何帮助。
好的 -- 非常感谢一位朋友 (AR) 帮助我找出错误。
第一个问题是我关系错了;外键需要在 Variant
模型中,而不是 Sample
模型中(Sample
模型中的 sample_variant
已删除)。
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 %}
问题已解决,table 呈现。
我有一个受 Mozilla 的 Django 教程 (https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website) 影响很大的 Django 项目。我已将 books
修改为 samples
,其中每个 samples
都隶属于研究员/pi
(又名 author
)。我创建了一个名为 Variant
的单独模型,它是 Sample
模型的外键。由于此字段将允许每个样本有多个变体,因此在查看样本的详细视图时,我想将变体(特定于单个样本)显示为渲染 table。我没有成功实现这一目标,我认为我只是没有完全正确地命名视图(以及 html 文件中的语言)。我的问题在这个 post 的末尾。
这是我的代码。
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
#----------------------------------------------------------------------------
我不确定像我这样设置基因(变异域)是否是copacetic。
samples/views.py
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 class 对象引起的,但我还没有想出如何解决它。
django_tables2 版本是最新的,正在渲染其他 table 没有问题。
- 我以与其他模型(
sample_name
和pi
)中的字段类似的方式将gene
链接到一个列 - 它是否正确? - 我如何安排 for 循环以正确显示列表中的所有变体?
- 我需要在(假设)views.py 文件中更改什么才能正确呈现
var
table? - 我不相信我在 urls.py 中正确列出了路径(我尝试了几种变体但没有成功),如果不正确应该如何正确构建?
非常感谢和赞赏任何帮助。
好的 -- 非常感谢一位朋友 (AR) 帮助我找出错误。
第一个问题是我关系错了;外键需要在 Variant
模型中,而不是 Sample
模型中(Sample
模型中的 sample_variant
已删除)。
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 %}
问题已解决,table 呈现。