30

Class Based ListViewテーブルセットの選択を表示するを実現しようとしています。サイトが初めて要求された場合は、データセットが表示されます。私は POST 送信を希望しますが、GET も問題ありません。

これは で簡単に処理できた問題ですが、function based viewsクラスベースのビューでは理解するのに苦労します。

私の問題は、さまざまなエラーが発生することです。これは、分類されたビューの理解が限られているために発生します。さまざまなドキュメントを読み、直接クエリ リクエストのビューを理解しましたが、フォームをクエリ ステートメントに追加しようとすると、別のエラーが発生します。以下のコードでは、ValueError: Cannot use None as a query value.

フォーム エントリに応じたクラス ベースの ListView のベスト プラクティス ワークフローはどのようなものでしょうか (それ以外の場合はデータベース全体を選択します)。

これは私のサンプルコードです:

models.py

class Profile(models.Model):
    name = models.CharField(_('Name'), max_length=255)

    def __unicode__(self):
        return '%name' % {'name': self.name}

    @staticmethod
    def get_queryset(params):

        date_created = params.get('date_created')
        keyword = params.get('keyword')
        qset = Q(pk__gt = 0)
        if keyword:
            qset &= Q(title__icontains = keyword)
        if date_created:
            qset &= Q(date_created__gte = date_created)
        return qset

フォーム.py

class ProfileSearchForm(forms.Form):
    name = forms.CharField(required=False)

ビュー.py

class ProfileList(ListView):
    model = Profile
    form_class = ProfileSearchForm
    context_object_name = 'profiles'
    template_name = 'pages/profile/list_profiles.html'
    profiles = []


    def post(self, request, *args, **kwargs):
        self.show_results = False
        self.object_list = self.get_queryset()
        form = form_class(self.request.POST or None)
        if form.is_valid():
            self.show_results = True
            self.profiles = Profile.objects.filter(name__icontains=form.cleaned_data['name'])
        else:
            self.profiles = Profile.objects.all()
        return self.render_to_response(self.get_context_data(object_list=self.object_list, form=form))

    def get_context_data(self, **kwargs):
        context = super(ProfileList, self).get_context_data(**kwargs)
        if not self.profiles:
            self.profiles = Profile.objects.all()
        context.update({
            'profiles': self.profiles
        })
        return context

以下に、ジョブを実行する FBV を追加しました。この機能を CBV に変換するにはどうすればよいですか? 関数ベースのビューでは非常に単純に見えますが、クラスベースのビューではそうではありません。

def list_profiles(request):
    form_class = ProfileSearchForm
    model = Profile
    template_name = 'pages/profile/list_profiles.html'
    paginate_by = 10

    form = form_class(request.POST or None)
    if form.is_valid():
        profile_list = model.objects.filter(name__icontains=form.cleaned_data['name'])
    else:
        profile_list = model.objects.all()

    paginator = Paginator(profile_list, 10) # Show 10 contacts per page
    page = request.GET.get('page')
    try:
        profiles = paginator.page(page)
    except PageNotAnInteger:
        profiles = paginator.page(1)
    except EmptyPage:
        profiles = paginator.page(paginator.num_pages)

    return render_to_response(template_name, 
            {'form': form, 'profiles': suppliers,}, 
            context_instance=RequestContext(request))
4

7 に答える 7

51

あなたの目標は、フォームの送信に基づいてクエリセットをフィルタリングしようとしていると思います。そうであれば、 GET を使用します。

class ProfileSearchView(ListView)
    template_name = '/your/template.html'
    model = Person

    def get_queryset(self):
        name = self.kwargs.get('name', '')
        object_list = self.model.objects.all()
        if name:
            object_list = object_list.filter(name__icontains=name)
        return object_list

getあとは、テンプレートとコンテキストをレンダリングするメソッドを書くだけです。

最善のアプローチではないかもしれません。上記のコードを使用すると、Django フォームを定義する必要がなくなります。

クラスベースのビューは、テンプレートをレンダリングする方法、フォームを処理する方法などを分離します。同様に、getGET 応答をpost処理し、POST 応答を処理し、get_queryset自明get_objectです。利用可能なメソッドを知る簡単な方法は、シェルを起動して次のように入力することです。

from django.views.generic import ListViewについて知りたい場合ListView

を入力しdir(ListView)ます。そこでは、定義されたすべてのメソッドを確認し、ソース コードにアクセスして理解することができます。クエリセットを取得するために使用されるget_querysetメソッド。このように定義するだけでなく、それも機能します:

class FooView(ListView):
    template_name = 'foo.html'
    queryset = Photo.objects.all()  # or anything

上記のようにできますが、そのアプローチを使用して動的フィルタリングを行うことはできません。を使用get_querysetすることで、持っているデータ/値/情報を使用して動的フィルタリングを行うことができます。つまり、によって送信されたパラメーターを使用することもできnameます。GETkwargsself.kwargs["some_key"]some_key

于 2012-11-23T11:44:25.413 に答える
3

これは、動的フィルタリングの一般的なビューのトピックでうまく説明されています。

エディットミキシングから継承されていないため、この方法を使用することはできGETないと思います。POSTListView

あなたができることは次のとおりです。

urls.py

urlpatterns = patterns('', 
                (r'^search/(\w+)/$', ProfileSearchListView.as_view()),
              )

views.py

class ProfileSearchListView(ListView):
    model = Profile
    context_object_name = 'profiles'
    template_name = 'pages/profile/list_profiles.html'
    profiles = []

    def get_queryset(self):
         if len(self.args) > 0:
               return Profile.objects.filter(name__icontains=self.args[0])
         else:
               return Profile.objects.filter()
于 2012-11-23T13:49:12.113 に答える
1

あなたが得ているエラーはあなたのフォームが名前フィールドを必要としないためだと思います。したがって、フォームは有効ですが、nameフィールドのcleaned_dataは空です。

これらは問題のある行である可能性があります。

if form.is_valid():
    self.show_results = True
    self.profiles = Profile.objects.filter(name__icontains=form.cleaned_data['name'])

私があなたなら、行を変えてみます:

self.profiles = Profile.objects.filter(name__icontains=form.cleaned_data['name'])

これに:

self.profiles = Profile.objects.none()

エラーの受信を停止した場合(そしてテンプレートが空を受信した場合object_list)、問題は前に述べたことです。名前フィールドは不要です。

これが機能しない場合はお知らせください。

于 2012-11-24T04:55:22.847 に答える