You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Django REST Framework结合MongoDB实现带过滤的数据查询

Adding Filtered Querying to DRF with MongoDB Replica Set

Hey there! Let's walk through how to add filtered data querying to your Django REST Framework (DRF) setup that uses a MongoDB replica set. Since your MyModel stores structured data in a JSONField, we’ve got practical approaches to cover both structured, predefined filters and flexible ad-hoc filtering.

Step 1: Set Up Dependencies

First, install django-filter—the standard tool for adding filtering capabilities to DRF views:

pip install django-filter

Then add it to your Django project's INSTALLED_APPS and configure DRF to use its filter backend by default:

# settings.py
INSTALLED_APPS = [
    # ... other existing apps
    'django_filters',
]

REST_FRAMEWORK = {
    # ... other DRF settings
    'DEFAULT_FILTER_BACKENDS': [
        'django_filters.rest_framework.DjangoFilterBackend',
    ]
}

Step 2: Create a Custom FilterSet

Since your data field is a JSONField (stored as binary in MongoDB), we can leverage MongoDB's native support for querying nested JSON properties. Create a filters.py file to define your filter rules:

# filters.py
import django_filters
from .models import MyModel

class MyModelFilter(django_filters.FilterSet):
    # Example 1: Exact match for a nested key in `data`
    user_id = django_filters.NumberFilter(method='filter_user_id')
    # Example 2: Case-insensitive partial match for a string key
    username = django_filters.CharFilter(method='filter_username')
    # Example 3: Filter records where `data.price` is greater than or equal to a value
    min_price = django_filters.NumberFilter(method='filter_min_price')

    class Meta:
        model = MyModel
        fields = ['user_id', 'username', 'min_price']

    def filter_user_id(self, queryset, name, value):
        # Use double underscores to access nested JSON keys (djongo handles this for MongoDB)
        return queryset.filter(data__user_id=value)

    def filter_username(self, queryset, name, value):
        # Use MongoDB's $regex for partial matches
        return queryset.filter(data__username__regex=value)

    def filter_min_price(self, queryset, name, value):
        # Use `gte` for greater-than-or-equal filtering
        return queryset.filter(data__price__gte=value)

Step 3: Attach FilterSet to Your DRF View

Update your view to use the MyModelFilter so it accepts filter parameters via query strings:

# views.py
from rest_framework import generics
from .models import MyModel
from .serializers import MySerializer
from .filters import MyModelFilter

class MyModelListView(generics.ListAPIView):
    queryset = MyModel.objects.all()
    serializer_class = MySerializer
    filterset_class = MyModelFilter

Now you can make requests like:

  • GET /api/mymodels/?user_id=123 to get records where data.user_id equals 123
  • GET /api/mymodels/?username=john to get records where data.username contains "john"
  • GET /api/mymodels/?min_price=50 to get records where data.price is ≥50

Step 4: Add Flexible Ad-Hoc Filtering (Optional)

If you need to support dynamic filter conditions sent as JSON from the frontend, create a custom filter backend:

# views.py
from rest_framework import filters
import json

class JSONFilterBackend(filters.BaseFilterBackend):
    def filter_queryset(self, request, queryset, view):
        # Get the JSON filter parameter from the request
        filter_json = request.query_params.get('filter', None)
        if not filter_json:
            return queryset
        
        try:
            # Parse the JSON into a dictionary
            filter_dict = json.loads(filter_json)
            # Map the keys to MongoDB's nested query format
            mongo_filter = {f'data__{key}': value for key, value in filter_dict.items()}
            return queryset.filter(**mongo_filter)
        except json.JSONDecodeError:
            # Return unfiltered queryset if JSON is invalid
            return queryset

# Update your view to include this backend
class MyModelListView(generics.ListAPIView):
    queryset = MyModel.objects.all()
    serializer_class = MySerializer
    filterset_class = MyModelFilter
    filter_backends = [
        'django_filters.rest_framework.DjangoFilterBackend',
        JSONFilterBackend
    ]

Now you can send complex filters via a single query parameter:
GET /api/mymodels/?filter={"user_id":123,"status":"active","price":{"$lt":100}}

Key Notes for MongoDB Replica Set

Ensure your Django database configuration is correctly set up for the replica set—this ensures queries are routed appropriately (read preferences are handled by djongo/MongoDB driver):

# settings.py
DATABASES = {
    'default': {
        'ENGINE': 'djongo',
        'NAME': 'your_database_name',
        'CLIENT': {
            'host': 'mongodb://replica-node-1:27017,replica-node-2:27017,replica-node-3:27017/?replicaSet=your-replica-set-name',
            'username': 'your_db_user',
            'password': 'your_db_password',
            'authSource': 'admin',
        }
    }
}

The binary=True flag on your serializer's JSONField doesn't affect filtering—djongo automatically deserializes the binary JSON for querying.

内容的提问来源于stack exchange,提问作者Albert

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:07:15