こんにちは! このライブラリをありがとうございました! 私の現在のAPIでそれをテストすることはとても嬉しいことです!
School
とSchoolCourse
の2つのモデルがあります。 SchoolCourse
は、 School
とは逆の多対1の関係にあります。
SchoolCourse
のname
に基づいてSchool
オブジェクトをフィルタリングできるようにしたい
さらに、ストレッチゴールとして、最終的にはSchoolLesson
でフィルタリングできるようにしたいと思います。
class SchoolModel(Model):
name = CharField(max_length=24, unique=True)
REQUIRED_FIELDS = ["name"]
class Meta:
ordering = ("id",)
def get_courses(self):
school_courses = SchoolCourseModel.objects.filter(school=self)
return school_courses
class SchoolCourseModel(Model):
description = CharField(default="", max_length=200)
name = CharField(max_length=50)
school = ForeignKey(SchoolModel,
related_name="school_course",
on_delete=CASCADE)
REQUIRED_FIELDS = ["school", "name"]
class Meta:
ordering = ("id",)
unique_together = ("school", "name",)
def get_lessons(self):
school_lessons = SchoolLessonModel.objects.filter(course=self)
return school_lessons
これ-デバッグビューでこれらのモデルを試してみると、これが表示されます
all_school_models[50].school_course
(Pdb++) <django.db.models.fields.related_descriptors.create_reverse_many_to_one_manager.<locals>.RelatedManager object at 0x10a8177d0>
all_school_models[50].school_course.all()
(Pdb++) <QuerySet [<SchoolCourseModel: SchoolCourseModel object (151)>, <SchoolCourseModel: SchoolCourseModel object (152)>, <SchoolCourseModel: SchoolCourseModel object (153)>]>
all_school_models[50].school_course.all()[0]
(Pdb++) <SchoolCourseModel: SchoolCourseModel object (151)>
all_school_models[50].school_course.all()[0].name
(Pdb++) 'Nihongo Course One'
私が作ったフィルターはかなり簡単に思えます。
class SchoolFilter(FilterSet):
school_name = CharFilter(field_name="name",
lookup_expr="icontains")
# ---
course_name = CharFilter(field_name="school_course__name",
lookup_expr="icontains")
course_description = CharFilter(field_name="school_course__description",
lookup_expr="icontains")
class Meta:
model = SchoolModel
fields = [
"school_name",
# ---
"course_name",
"course_description"
]
ただし、これは機能しません。 私がこの要求をした場合:
{{API_URL}}/api/v1/schools/?course_name=Nihongo
私はこれを応答として返します
{
"schools": []
}
私はここで何が間違っているのですか?
django-filtersを誤解していますか? データモデルを接続する方法を誤解していますか?
どんな指導も大歓迎です!
こんにちは@loganknecht。 健全性チェックと同じように、URLが正しいことを確認できますか? サンプルURLでは、クエリ文字列は$#$ ?
$#$ではなく/
で始まります。
ああ@ rpkilby-申し訳ありませんが、これはPostman
からのコピーと貼り付けによる私の側の見落としでした。 URLは実際には{{API_URL}}/api/v1/schools/?offset=49&course_name=Nihongo
ですが、混乱を少なくするためにoffset
を削除し、反対のことを行うことに成功しました😂
あなたの例は私に明白な問題を提起しません。 私の推測では、APIビューに問題があると思います。 DjangoFilterBackend
を設定/ビューのfilter_backends
に追加しましたか? そして、 filterset_class = SchoolFilter
を設定しましたか(これは以前はfilter_class
であったことに注意してください)?
ねえ@rpkilby
これが私が持っているビューコードです
class SchoolViewSet(ViewSet):
http_method_names = ["get", "post"]
def list(self, request):
all_school_models = SchoolModel.objects.all()
filtered_school_models = SchoolFilter(request.GET, queryset=all_school_models)
# import pdb
# pdb.set_trace()
paginator = HeaderLinkPagination()
current_page_results = paginator.paginate_queryset(filtered_school_models.qs,
request)
all_schools_serializer = SchoolSerializer(current_page_results,
many=True)
response_data = {
"schools": all_schools_serializer.data
}
response_to_return = paginator.get_paginated_response(response_data)
return response_to_return
pdb.set_trace()
は、私が上記の尋問を投稿した場所です。
DjangoFilterBackend
はグローバル構成であると想定し、単一のエンドポイントでのみテストしているため、設定しませんでした。
さらに、同じ理由で、これをクラスにも設定しませんでした。
SchoolModel
の名前でこのフィルターを使用できることを知っておくことが重要ですが、逆外部キーschool_course
でフィルターをかけると機能しません。
お奨め-つまり、ビューで直接フィルターセットを作成しているのです。 その場合、ええ、フィルターバックエンド/フィルターセットクラスを設定する必要はありません。
データが正しいかどうか、エラーがあったかどうか、またはSQLクエリが正しく形成されているかどうかを確認できます。 試す:
filtered_school_models = SchoolFilter(request.GET, queryset=all_school_models)
print(filtered_school_models.data)
print(filtered_school_models.errors)
print(filtered_school_models.qs)
print(str(filtered_school_models.qs.query))
@rpkilbyこれが私が見るものです
<QueryDict: {'offset': ['49'], 'course_name': ['Nihongo']}>
<QuerySet [<SchoolModel: SchoolModel object (51)>]>
SELECT "piano_gym_api_schoolmodel"."id", "piano_gym_api_schoolmodel"."name", "piano_gym_api_schoolmodel"."school_board_id" FROM "piano_gym_api_schoolmodel" INNER JOIN "piano_gym_api_schoolcoursemodel" ON ("piano_gym_api_schoolmodel"."id" = "piano_gym_api_schoolcoursemodel"."school_id") WHERE UPPER("piano_gym_api_schoolcoursemodel"."name"::text) LIKE UPPER(%Nihongo%) ORDER BY "piano_gym_api_schoolmodel"."id" ASC
@rpkilbyこれは、次のように見える私のpaginator実装の問題である可能性があるようです
class HeaderLinkPagination(LimitOffsetPagination):
default_limit = settings.DEFAULT_LIMIT
max_limit = settings.DEFAULT_MAX_LIMIT
min_limit = settings.DEFAULT_MIN_LIMIT
min_offset = settings.DEFAULT_MIN_OFFSET
max_offset = settings.DEFAULT_MAX_OFFSET
def get_paginated_response(self, data):
next_url = self.get_next_link()
previous_url = self.get_previous_link()
links = []
header_data = (
(previous_url, "prev"),
(next_url, "next"),
)
for url, label in header_data:
if url is not None:
links.append("<{}>; rel=\"{}\"".format(url, label))
headers = {"Link": ", ".join(links)} if links else {}
return Response(data, headers=headers)
def paginate_queryset(self, queryset, request, view=None):
limit = request.query_params.get("limit")
offset = request.query_params.get("offset")
if limit is None:
limit = settings.DEFAULT_LIMIT
if offset is None:
offset = settings.DEFAULT_OFFSET
limit = int(limit)
if limit > self.max_limit:
error_message = ("Limit should be less than or equal to {0}"
).format(self.max_limit)
errors = {"limit": [error_message]}
raise ValidationError(errors)
elif limit < self.min_limit:
error_message = ("Limit should be greater than or equal to {0}"
).format(self.min_limit)
errors = {"limit": [error_message]}
raise ValidationError(errors)
offset = int(offset)
if offset > self.max_offset:
error_message = ("Offset should be less than or equal to {0}"
).format(self.max_offset)
errors = {"offset": [error_message]}
raise ValidationError(errors)
elif offset < self.min_offset:
error_message = ("Offset should be greater than or equal to {0}"
).format(self.min_offset)
errors = {"offset": [error_message]}
raise ValidationError(errors)
import pdb
pdb.set_trace()
return super(self.__class__, self).paginate_queryset(queryset, request, view)
解決策を見つけたら、私に知らせてください。 私がこれを振り払おうとしている間、お楽しみに。
私の推測では、これは与えられたオフセットに関連していると思います。 フィルタリングされたクエリセットにはオブジェクトが1つしかありませんが、リクエストは最初の49項目をスキップするようにページャに指示しています。 あなたがチェックした場合
print(filtered_school_models[49:])
<QuerySet []>
を取得すると思います。
これはページ付けの問題のように見えるので、閉じます。
ねえ@rpkilby
これを通して私に話してくれて本当にありがとうと言いたいです。 これはdjango-filter
の問題でもありませんでした。 私はただのディンガスでした。 あなたは私をラバーダックしてくれてとても感謝しています。
あなたは素晴らしいです、そしてもう一度、この素晴らしいライブラリに感謝します!
心配ない。 お力になれて、嬉しいです!
最も参考になるコメント
私の推測では、これは与えられたオフセットに関連していると思います。 フィルタリングされたクエリセットにはオブジェクトが1つしかありませんが、リクエストは最初の49項目をスキップするようにページャに指示しています。 あなたがチェックした場合
<QuerySet []>
を取得すると思います。これはページ付けの問題のように見えるので、閉じます。