うまくいけば、これは私を助けるための簡単なものであるべきです。
3つの項目を含むドロップダウンメニューのあるページがあります。
<form method="GET">
<select name="browse">
<option>Cats</option>
<option>Dogs</option>
<option>Worms</option>
</select>
<input type="submit" value="Submit" />
</form>
<!-- Output table -->
<table id="myTable">
<thead>
<tr>
<th>Name</th>
<th>Colour</th>
</tr>
</thead>
<tbody>
{% for object in object_list %}
<tr>
<td>{{ object.name }}</td>
<td>{{ object.colour }}</td>
</tr>
{% endfor %}
</tbody>
</table>
<!-- Pagination controls -->
<div class="pagination">
<span class="page-links">
{% if page_obj.has_previous %}
<a href="?page={{ page_obj.previous_page_number }}">previous</a>
{% endif %}
<span class="page-current">
Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}.
</span>
{% if page_obj.has_next %}
<a href="?page={{ page_obj.next_page_number }}">next</a>
{% endif %}
</span>
</div>
ユーザーがアイテムを選択して送信を押すと、一般的なListViewによって生成された結果がテーブルに表示されます。
class Browse(generic.ListView):
template_name = 'app/browse.html'
paginate_by = 25
def get_queryset(self):
queryset = Cats.objects.all()
if self.request.GET.get("browse"):
selection = self.request.GET.get("browse")
if selection == "Cats":
queryset = Cats.objects.all()
Elif selection == "Dogs":
queryset = Dogs.objects.all()
Elif selection == "Worms":
queryset = Worms.objects.all()
else:
queryset = Cats.objects.all()
return queryset
ただし、ページネーションコントロールを使用してページをめくろうとすると、フォームデータがリセットされているため、クエリセットが最初の(デフォルトの)項目である猫にリセットされます。
この問題を回避する方法はありますか?
ありがとう!
PS:ああ、そのメモで、クエリセットを最初からなしに設定することは可能ですか?とても感謝しております!
更新:Catsクエリセットでページネーションを使用すると、正常に動作するため、バグは他の2つのセットでのみ表示されます。
この問題を解決するために、フォームからのgetリクエストとURL文字列のページ番号の両方に対応するように、ページネーションHTMLを変更しました。
<div class="pagination">
<span class="page-links">
{% if page_obj.has_previous %}
<a href="/browse/?browse={{ input }}&page={{ page_obj.previous_page_number }}">previous</a>
{% endif %}
<span class="page-current">
Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}.
</span>
{% if page_obj.has_next %}
<a href="/browse/?browse={{ input }}&page={{ page_obj.next_page_number }}">next</a>
{% endif %}
</span>
</div>
ここでの{{input}}は、フォームを介して送信されたオプションを含む文字列です。 「猫」または「ワーム」。
これをテンプレートに渡すことができるように、クラスベースビューのget_context_dataメソッドを次のように変更しました。
class Browse(generic.ListView):
template_name = 'app/browse.html'
paginate_by = 25
# Modifying the get_context_data method
def get_context_data(self, **kwargs):
context = super(Browse, self).get_context_data(**kwargs)
q = self.request.GET.get("browse")
context['input'] = q
return context
def get_queryset(self):
queryset = Cats.objects.all()
if self.request.GET.get("browse"):
selection = self.request.GET.get("browse")
if selection == "Cats":
queryset = Cats.objects.all()
Elif selection == "Dogs":
queryset = Dogs.objects.all()
Elif selection == "Worms":
queryset = Worms.objects.all()
else:
queryset = Cats.objects.all()
return queryset
これで、url文字列は次のようになります。
/browse/?browse=Cats&page=3
つまり、ページネーションはフォームのgetメソッドと一緒に機能するようになりました。
シラーの答え に基づくクエリの使用を支援するために、テンプレートタグをまとめました。例:
<a href="{% url view_url %}?{% query query_params page=num %}">{{ num }}</a>
クエリパラメータが辞書の場合{'foo': 'bar'}
コンテキストで渡されると、次のようにレンダリングされます。
<a href="myview/?foo=bar&page=2">2</a>
構文:
{% query var_name param=value 'name_only_param' other_param=value|default:'x' another_var %}
変数は、リスト、辞書、文字列、またはなし(なしはスキップされます)です。
コード:
from Django import template
from Django.utils.encoding import force_text
from Django.template.base import Node, TemplateSyntaxError, kwarg_re, FilterExpression
register = template.Library()
@register.tag
def query(parser, token):
bits = token.split_contents()
args = []
asvar = None
bits = bits[1:]
if len(bits) >= 2 and bits[-2] == 'as':
asvar = bits[-1]
bits = bits[:-2]
if len(bits):
for bit in bits:
match = kwarg_re.match(bit)
if not match:
raise TemplateSyntaxError("Malformed arguments to url tag")
name, value = match.groups()
if name:
args.append({name: parser.compile_filter(value)})
else:
args.append(parser.compile_filter(value))
return QueryNode(args, asvar)
class QueryNode(Node):
def __init__(self, args, asvar):
self.args = args
self.asvar = asvar
def render(self, context):
def join(thing, lst):
if isinstance(thing, dict):
for k, v in thing.items():
if isinstance(v, FilterExpression):
v = force_text(v.resolve(context))
if v is None:
continue
lst.append('{}={}'.format(k, v))
Elif isinstance(thing, list):
for it in thing:
if isinstance(it, FilterExpression):
it = it.resolve(context)
join(it, lst)
Elif isinstance(thing, str):
lst.append(thing + '=')
Elif thing is None:
pass
else:
raise TypeError('Cannot join: %r' % thing)
query_lst = []
join(self.args, query_lst)
query = '&'.join(query_lst)
if self.asvar:
context[self.asvar] = query
return ''
else:
return query