2017-03-04 4 views
2

私は数日間このことを理解しようとしていて、有用な情報をオンラインで見つけることができませんでした。 私がしようとしているのは、ドロップダウンメニューを使ってフィルタリングし、AJAX経由でPythonにデータを供給した後、モデルのオブジェクトをページ付けすることです。私は問題がどこにあるのか知っていますが、解決方法はわかりません。私は2つのテンプレートを持って、最初のものは次のとおりです。AJAXを使用してフィルタ処理された結果のDjangoページ番号

entry_index.html

{% if objects %} 
    {% for object in objects %} 
    do something 
    {% endfor %} 

    <div class="pagination"> 
    <span class="step-links"> 
     {% if objects.has_previous %} 
      <a href="?page={{ objects.previous_page_number }}">previous</a> 
     {% endif %} 

     <span class="current"> 
      Page {{ objects.number }} of {{ objects.paginator.num_pages }}. 
     </span> 

     {% if objects.has_next %} 
      <a href="?page={{ objects.next_page_number }}">next</a> 
     {% endif %} 
    </span> 
</div> 

{% extends 'main/base.html' %} 
<form action="" method="get" accept-charset="utf-8"> 
<select class="selectpicker" name="times" onchange="FilterCategories()" id="times"> 
    <option value="1">last 24 hours</option> 
    <option value="30">past month</option> 
    <option value="365">past year</option> 
    <option value="10000">all time</option> 
</select> 
</form> 

<ul id="all-games" class="list-unstyled"> 
{% include page_template %} 
</ul> 

上記テンプレートに含まれているテンプレートはentry_index_page.htmlですurls.py

url(r'^$', views.entry_index, name='index') 

views.py

def entry_index(
    request, 
    template='entry_index.html', 
    page_template='entry_index_page.html'): 

    date_from = timezone.now() - timezone.timedelta(days=1) 
    obj_list=Object.objects.filter(submitted__gte = date_from).order_by('-votes') 
    message=[] 
    context = { 
    'objects': obj_list, 
    'page_template': page_template} 

    if request.is_ajax(): 
     template = page_template 
     message = [] 

     if request.method == "GET": 
      time_range = request.GET.get('time_range') 
      if time_range is not None and time_range != u"": 
       time_range = request.GET['time_range'] 
       date_from = timezone.now() - timezone.timedelta(days=int(time_range)) 
       obj_list= Object.objects.filter.filter(submitted__gte=date_from) 

    paginator = Paginator(obj_list, 2) 

    page = request.GET.get('page') 
    try: 
     objects= paginator.page(page) 
    except PageNotAnInteger: 
     objects= paginator.page(1) 
    except EmptyPage: 
     objects= paginator.page(paginator.num_pages) 

    context.update({"message":message,"objects":objects}) 

    return render_to_response(
    template, context, context_instance=RequestContext(request)) 

ajax.js:今

function FilterCategories() { 
    var timePosted = document.getElementById('times'); 
    $.ajax({ 
     type: "GET", 
     url: "", 
     data: { 
      'time_range': timePosted.value, 
      'csrfmiddlewaretoken': $("input[csrfmiddlewaretoken]").val() 
     }, 
     success: filterResults, 
     dataType: 'html' 
    }); 
} 

私が起こっていると思うものを説明すると、うまくいけば、誰かが解決策を見つける私を助けることができます。

ホームページが読み込まれると(entry_index.html)、モデルはドロップダウンメニューの最初のオプションに基づいてフィルタリングされます(つまり、最終日に送信されたデータエントリをフィルタリングするvalue = "1")。 。 obj_list変数に値が設定され、ページ設定に渡され、すべてが期待通りに機能します。私は特定の数のページを取得し、ページをナビゲートすることができます。ここでもう一度ホームページにいると仮定して、ドロップダウンメニューから「すべての時間」を選択します。これにより、onchangeコールバックがトリガーされ、FilterCategories()関数が呼び出されます。 AJAXのURLは ""(空の文字列なので、インデックスページを指していることに注意してください)。 urls.pyによると、それは私のentry_index()ビューを呼び出すでしょう。 requestはajaxなので、使用されるテンプレートは変更されます(page_templateは新しいテンプレートpage_template = entry_index_page.htmlになります)。新しい時間範囲はドロップダウンメニューで指定され、ajaxで渡されるため、新しいobj_listを取得してページを作成し、「オブジェクト」を生成し、コンテキストとしてテンプレートに渡します。この時点までは、すべてが期待通りに機能します。私は適切な量のページを取得します。しかし、問題は、新しく選択したフィルタで次のページに移動しようとすると始まります。次のページボタンをクリックすると、行われているリクエストはajaxリクエストではないので、request.is_ajax()の条件にあるものはすべて実行されません。つまり、次のページをクリックすると、再びentry_indexビューが呼び出され、今回使用されているテンプレートはentry_index.htmlで、フィルタはデフォルト(「過去24時間」フィルタ)にリセットされます。したがって、次のページをクリックすると、実際にはデフォルトのホームページになり、新しく選択されたドロップダウンフィルターでオブジェクトの次のページが表示されます。

私の質問は、私は私のフィルタモデルのページをスクロールできるように、この問題を解決する簡単な方法はありますか?あるいは、私はこのアプローチを完全に断念し、これを行う簡単な方法がありますか?私は長いポストを謝罪し、誰かが私を助けてくれることを願っています。これを読んでいただきありがとうございます。

私はちょうどこの特定の手法を実践するために、ほとんどのブラウザのSFゲームをツーリングした。ここ

+0

私は完全にあなたのプロセスを以下ではないんだけど、あなたが見つけるかもしれません単一のテンプレートを使用する方が簡単で、新しいページの読み込みを行うのではなく、AJAXを使用してページ自体のHTMLのデータやチャンクを置き換えるだけです。それはより速く、動く部品が少なくなります。 –

答えて

1

は、私はジャンゴとAjaxを使用して、ページに表示される動的なコンテンツを持つことに取ったアプローチの例です。すべてが単一のビューで開催されました:

class GameViewport(TemplateView): 
    template_name = "game_viewport.html" 

    @cached_property 
    def slug(self): 
     return self.kwargs['slug'] 

    @cached_property 
    def game(self): 
     return Game.objects.get(url=self.kwargs['slug']) 

    @cached_property 
    def player(self): 
     return Player.objects.get(game=self.game) 

    @cached_property 
    def current_planet(self): 
     return self.player.current_planet 

    @cached_property 
    def left_column(self): 
     player = self.player 

     if player.current_location: 
      node = player.current_node 
      if len(Location.objects.filter(node=node)) == 0: 
       spawn_locations(node) 
       locations = Location.objects.filter(node=node) 
      else: 
       locations = Location.objects.filter(planet=node) 
      html = "Other Sites in ".format(str(node)) 
      for location in locations: 
       html += '<li><a href="" class="locationChoice"></a>{} ({})</li>'.format(location.name, location.type.name) 
      return html 

     elif player.current_node: 
      planet = player.current_planet 
      if len(Node.objects.filter(planet=planet)) == 0: 
       spawn_nodes(planet, get_name_choices()) 
       nodes = Node.objects.filter(planet=planet) 
      else: 
       nodes = Node.objects.filter(planet=planet) 
      html = '<h4><b>Other Starports on {}:</b></h4>'.format(planet.name) 
      for node in nodes: 
       html += '<li><a href="" class="nodeChoice"> {} </a> ({})</li>'.format(node.name, node.type.name) 
      return html 

     elif player.current_planet: 
      system = player.current_system 
      html = '<h4><b>Known Planets in {}:</b></h4>'.format(system.name) 
      for known_planet in player.known_planets.filter(solar_system=system): 
       html += '<li><a href="" class="planetChoice"> {} </a> ({})</li>'.format(
        known_planet.name, 
        known_planet.classification.name 
       ) 
      return html 
     else: 
      html = '<h4><bShip Status</b></h4>' 
      html += '<p><b>Fuel:</b> 100%</p>' 
      return html 

あなたが見ることができるように、左の列は、プレイヤーの現在の設定が何であるかに基づいて異なるHTMLデータを生成します。これはそうのようなテンプレートにプラグインすることになります。

<div class="col-md-3"> 
    <div class="leftColumn"> 
     {% autoescape off %} 
      {{ view.left_column }} 
     {% endautoescape %} 
    </div> 
</div> 
<a href="{% url "visit_planet" view.slug %}" id="visitPlanet"></a> 

ユーザーが新しい場所にクリックした場合、私はAJAXを通じて彼女の決定を送信します:

$(".planetChoice").click(function(){ 
    event.preventDefault(); 
    var submission_data = {planet: $(this).text()}; 
    console.log(submission_data); 
    $.ajax({ 
     url: $('#visitPlanet').attr('href'), 
     type: 'GET', 
     dataType: "json", 
     data: submission_data, 
     success: function(html_data) { 
       window.location.reload(); 
     }, 
     failure: function(data) { 
      alert('Something went wrong. Please refresh the page.'); 
     } 
    }); 
}); 

すべてこれはどうしたら更新プレイヤーの状態でありますそして彼女の新しい設定に従ってページをリロード:left_columnプロパティによって決定される

def visit_planet(request, slug): 
    player = Game.objects.get(url=slug).player_1 
    planet = Planet.objects.get(name=request.GET.get('planet', "").strip()) 

    if planet: 
     player.current_location = None 
     player.current_node = None 
     player.current_planet = planet 
     player.save() 

    response = {'status': 1, 'message': "Ok"} 

    return JsonResponse(response) 

はこのように、新しいデータを表示します。

私はこのことについて、データベースの状態を変更することで説明しましたが、セッション変数を使って簡単に行うこともできます。私はそれが動的コンテンツをサイクリングするのに比較的清潔でドライな方法であることを発見しました。また、Djangoにクリック間のデータを生成または変更する機会を与えるという利点もあります。

これがあなたの状況に当てはまるのかどうかはわかりませんが、うまくいけばいいと思います!

編集:必ずしもHTMLを出力する必要はありません。

<!--Product Tile #1--> 
{% if view.tile_data.0 %} 
<div class="col-md-4"> 
    <div class="card hoverable"> 
     <!--Card content--> 
     <div class="card-block" id="tile_{{ view.tile_data.0.invoice }}_id"> 
      <!--Title--> 
      <h4 class="card-title">Shipment {{ view.tile_data.0.invoice }}</h4> 
      <!--Text--> 
      <p class="card-text">{{ view.tile_data.0.supplier.name }} 
      <br> 
      <b>{{ view.tile_data.0.lbs|floatformat }} Lbs @ {{ view.tile_data.0.price }} USD</b> 
      <br> 
      {{ view.tile_data.0.variety.commodity }} {{ view.tile_data.0.variety }} {{ view.tile_data.0.inshell|shell_display }}</p> 
     </div> 
     <!--/.Card content--> 
    </div> 
</div> 
{% endif %} 
<!--./Product Tile #1--> 

このデータを直接モデルマネージャからの眺めを介して供給されています:ここで私は別のアプリケーションで使用していたアプローチだ

def tile_data(self, status, first, last): 
    return self.model.objects.filter(status=status)[first:last]