Django στοιχεία Φίλτρο χρονική σήμανση GROUP ανά ημέρα, εβδομάδα, μήνα, έτος

ψήφοι
30

Έχω μια εφαρμογή Django (DRF) στον οποίο I αποθήκευση περιοδικών δεδομένα χρονοσειρές βασίζονται σε απόκριση ΑΡΙ. Εδώ είναι model.py μου

# Model to store the Alexa API Data
class Alexa(models.Model):
    created_at = models.DateTimeField(auto_now_add=True)
    extra = jsonfield.JSONField(null=True)
    rank =  models.PositiveIntegerField(default=0, null=True)

Είμαι με τη χρήση Django-φίλτρα για τα δεδομένα του ερωτήματος που βασίζεται σε μια σειρά (__lte, __gte). Όπως και /api/alexa/?created_at__lte=2020-02-14T09:15:52.329641Zνα επιστρέψει όλα τα δεδομένα που δημιουργήθηκαν πριν2020-02-14T09:15:52.329641Z

[
    {
        id: 1,
        created_at: 2020-02-03T19:30:57.868588Z,
        extra: {'load_time': 00, 'backlink': 0},
        rank: 0
    },
    ...
 ]

Είναι ένας τρόπος για να οικοδομήσουμε ένα τελικό σημείο για να επιστρέψει συγκεντρωτικά στοιχεία ομαδοποιούνται ανά ημέρα, εβδομάδα, μήνα και έτος με βάση τις παραμέτρους που ερώτημα που περνούν εκεί. Για παράδειγμα, /api/alexa/?created_at__lte=2020-02-14T09:15:52.329641Z&group_by=monthθα επιστρέψει

[
    {
        created_at: 2020-01-01T00:00:00.000000Z,
        extra: {'load_time': 00, 'backlink': 0}, <- Aggregated Data 
        rank: 0                                    <- Aggregated Data
    },
    {
        created_at: 2020-02-01T00:00:00.000000Z,
        extra: {'load_time': 00, 'backlink': 0}, <- Aggregated Data 
        rank: 0                                    <- Aggregated Data 
    },
 ]

Εδώ είναι τρέχουσες serializer.py μου

class AlexaViewSet(viewsets.ModelViewSet):
    queryset = Alexa.objects.all()
    filter_fields = {'created_at' : ['iexact', 'lte', 'gte']}
    http_method_names = ['get', 'post', 'head']

Έχω δει πολλά αποσπάσματα κάνει συνάθροιση αλλά κανένας δεν πληροί απολύτως τις απαιτήσεις μου, ούτε που μου έδωσε μια ολοκληρωμένη ιδέα για το θέμα.

Είμαι νέος στο Django και την οικοδόμηση analytics ταμπλό σε γενικές γραμμές, αν υπάρχει άλλος τρόπος αναπαράστασης δεδομένων, όπως χρονοσειρές για την κατανάλωση στο front-end γραφήματα, θα εκτιμούσα τις προτάσεις σας για αυτό επίσης.

Δημοσιεύθηκε 15/02/2020 στις 08:48
χρήστη
Σε άλλες γλώσσες...                            


1 απαντήσεις

ψήφοι
0

Πρώτα απ 'όλα, η τάξη AlexaViewSetδεν είναι ένα σειριακό αλλά ViewSet. Δεν διευκρίνισε την κατηγορία serializer σε αυτό το ViewSet γι 'αυτό θα πρέπει να διευκρινιστεί ότι.

Από την άλλη πλευρά, αν θέλετε να περάσετε μια παράμετρος προσαρμοσμένο ερώτημα σχετικά με τη διεύθυνση URL τότε θα πρέπει να παρακάμψετε τη listμέθοδο αυτή ViewSet και να αναλύσει τη συμβολοσειρά ερωτήματος πέρασε στο requestαντικείμενο για να ανακτήσει την αξία της group_by, την επικύρωση και, στη συνέχεια perfom τη συσσώρευση εαυτό σας .

Ένα άλλο πρόβλημα που βλέπω είναι ότι θα πρέπει, επίσης, να ορίσουμε τι είναι να συγκεντρώσει ένα πεδίο JSON, η οποία δεν υποστηρίζεται σε SQL και είναι πολύ σχετική, οπότε μπορεί να θέλετε να εξετάσει τον επανασχεδιασμό πώς μπορείτε να αποθηκεύσετε τις πληροφορίες αυτού του πεδίου JSON, αν θέλετε να perfom συναθροίσεων σε πεδία μέσα σε αυτό. Θα ήθελα να προτείνω την εξαγωγή τα πεδία που θέλετε να συγκεντρώσετε από το JSON (κατά την αποθήκευση τους στη βάση δεδομένων) και τα βάζουμε σε ένα SQL στήλη ξεχωριστά ώστε να μπορείτε να εκτελέσετε τις δέσμες αργότερα. Ο πελάτης μπορεί επίσης να περάσει τη λειτουργία agregation ως παράμετρο ερωτήματος, για παράδειγμα aggregation=sumή aggregation=avg.

Σε μια απλή περίπτωση, όπου το μόνο που χρειάζεται ο μέσος όρος των κατατάσσεται αυτό θα πρέπει να είναι χρήσιμη ως παράδειγμα (μπορείτε να προσθέσετε TruncQuarter, κ.λπ.):

class AlexaViewSet(viewsets.ModelViewSet):
    serializer_class = AlexaSerializer
    queryset = Alexa.objects.all()
    filter_fields = {'created_at': ['iexact', 'lte', 'gte']}
    http_method_names = ['get', 'post', 'head']

    GROUP_CASTING_MAP = {  # Used for outputing the reset datetime when grouping
        'day': Cast(TruncDate('created_at'), output_field=DateTimeField()),
        'month': Cast(TruncMonth('created_at'), output_field=DateTimeField()),
        'week': Cast(TruncWeek('created_at'), output_field=DateTimeField()),
        'year': Cast(TruncYear('created_at'), output_field=DateTimeField()),
    }

    GROUP_ANNOTATIONS_MAP = {  # Defines the fields used for grouping
        'day': {
            'day': TruncDay('created_at'),
            'month': TruncMonth('created_at'),
            'year': TruncYear('created_at'),
        },
        'week': {
            'week': TruncWeek('created_at')
        },
        'month': {
            'month': TruncMonth('created_at'),
            'year': TruncYear('created_at'),
        },
        'year': {
            'year': TruncYear('created_at'),
        },
    }

    def list(self, request, *args, **kwargs):
        group_by_field = request.GET.get('group_by', None)
        if group_by_field and group_by_field not in self.GROUP_CASTING_MAP.keys():  # validate possible values
            return Response(status=status.HTTP_400_BAD_REQUEST)

        queryset = self.filter_queryset(self.get_queryset())

        if group_by_field:
            queryset = queryset.annotate(**self.GROUP_ANNOTATIONS_MAP[group_by_field]) \
                .values(*self.GROUP_ANNOTATIONS_MAP[group_by_field]) \
                .annotate(rank=Avg('rank'), created_at=self.GROUP_CASTING_MAP[group_by_field]) \
                .values('rank', 'created_at')

        page = self.paginate_queryset(queryset)
        if page is not None:
            serializer = self.get_serializer(page, many=True)
            return self.get_paginated_response(serializer.data)

        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)

Για αυτές τις τιμές:

GET /alexa
[
    {
        "id": 1,
        "created_at": "2020-03-16T12:04:59.096098Z",
        "extra": "{}",
        "rank": 2
    },
    {
        "id": 2,
        "created_at": "2020-02-15T12:05:01.907920Z",
        "extra": "{}",
        "rank": 64
    },
    {
        "id": 3,
        "created_at": "2020-02-15T12:05:03.890150Z",
        "extra": "{}",
        "rank": 232
    },
    {
        "id": 4,
        "created_at": "2020-02-15T12:05:06.357748Z",
        "extra": "{}",
        "rank": 12
    }
]
GET /alexa/?group_by=day
[
    {
        "created_at": "2020-02-15T00:00:00Z",
        "extra": null,
        "rank": 102
    },
    {
        "created_at": "2020-03-16T00:00:00Z",
        "extra": null,
        "rank": 2
    }
]
GET /alexa/?group_by=week
[
    {
        "created_at": "2020-02-10T00:00:00Z",
        "extra": null,
        "rank": 102
    },
    {
        "created_at": "2020-03-16T00:00:00Z",
        "extra": null,
        "rank": 2
    }
]

GET /alexa/?group_by=month
[
    {
        "created_at": "2020-02-01T00:00:00Z",
        "extra": null,
        "rank": 102
    },
    {
        "created_at": "2020-03-01T00:00:00Z",
        "extra": null,
        "rank": 2
    }
]
GET /alexa/?group_by=year
[
    {
        "created_at": "2020-01-01T00:00:00Z",
        "extra": null,
        "rank": 77
    }
]
Απαντήθηκε 15/02/2020 στις 20:34
πηγή χρήστη

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more