简体   繁体   English

使 Django 中的其他方法(和视图)可以访问一种方法的上下文变量

[英]making context variable from one method accessible to other other methods (and views) in Django

i'm working on a dashboard project (django + charts.js) that currently looks like this:我正在开发一个仪表板项目(django + charts.js),目前看起来像这样: 在此处输入图像描述

currently, all of the charts are based on all the data in the database (approx 1.5 mil lines).目前,所有图表均基于数据库中的所有数据(约 150 万行)。 however, i'd like these charts to be responsive to the dates indicated in the start date/end date HTML widget - eg show payment methods, taxi orders by the hour/day of week according to the start/end dates indicated.但是,我希望这些图表能够响应开始日期/结束日期 HTML 小部件中指示的日期 - 例如,根据指示的开始/结束日期按小时/星期几显示付款方式、出租车订单。

my date_input method gets the start and end dates from the frontend, and queries my MySQL database according to the dates selected.我的date_input方法从前端获取开始和结束日期,并根据选择的日期查询我的 MySQL 数据库。 these queries are then rendered to the context variable of date_input - however, i'd like the context variable in date_input to be available to all methods (each chart is rendered by a different method, based on the JsonResponse returned to different endpoints).然后将这些查询呈现给date_inputcontext变量 - 但是,我希望date_input中的context变量可用于所有方法(每个图表由不同的方法呈现,基于返回到不同端点的 JsonResponse)。

i've tried making context available as a global variable by defining it outside date_input as queryset = date_input(request) - NameError: name 'request' is not defined .我已经尝试通过在date_input之外将上下文定义为queryset = date_input(request) - NameError: name 'request' is not defined使context作为全局变量可用。 i've looked into context processors , but that seems to be an option only if i didn't have a request (eg start/end date input from the frontend).我已经研究过context processors ,但这似乎是一个选项,只有当我没有请求时(例如,来自前端的开始/结束日期输入)。 i'm rather confused and would appreciate some help.我很困惑,希望能得到一些帮助。

here's my views.py code:这是我的views.py代码:

def date_input(request):       
    if request.method == "POST": 
        context = {}

        start_date = request.POST.get("start_date", None) # type unicode
        end_date = request.POST.get("end_date", None)
        
        form = DateForm(request.POST or None)

        if form.is_valid():
            start_date = form.cleaned_data['start_date']
            end_date = form.cleaned_data['end_date']

            context['start_date'] = Order.objects.filter(member_created_time__gte=(start_date)) # this works
            context['end_date'] = Order.objects.filter(order_ended_time__lte=(end_date))

            print("weeeeeee!")
            print(context['start_date']) # type queryset
            print("----")
            print(context['end_date'])

            return render(request, 'date_input.html', context) # return JSON response to frontend
            # return JsonResponse({
            #     "context": float(context),
            # })

    else:
        form = DateForm()
        # print("form is not valid")

    # return JsonResponse({
    #     "form": float(form),
    # })
    return render(request, 'date_input.html', {
        "form": form
    })

dow_queryset = Member.objects.order_by('member_created_time').values_list('member_created_time', flat=True)

hkt = pytz.timezone('Asia/Shanghai')
dt_obj = [hkt.localize(datetime.datetime.fromtimestamp(x)) for x in dow_queryset]


def charts(request):  # pie chart for payment type
    queryset = Order.objects.order_by('payment').values(
       'payment').annotate(payment_type=Count('payment'))
    default = list(queryset.values_list('payment_type', flat=True))
    labels = list(queryset.values_list('payment', flat=True))
    
    return JsonResponse({
        'labels': labels,  # payment methods
        'default': default,  # payment methods
    })

def hourly(request): # bar chart to show taxi orders by hour of day
    hour_count = OrderedDict()
    hour_count['midnight'] = 0
    hour_count['early_morning'] = 0
    hour_count['morning'] = 0
    hour_count['afternoon'] = 0
    hour_count['night'] = 0

    for obj in dt_obj:
        if obj.hour == 0:
            hour_count['midnight'] += 1   
        elif obj.hour < 6:
            hour_count['early_morning'] += 1
        elif obj.hour < 12:
            hour_count['morning'] += 1  
        elif obj.hour < 19:
            hour_count['afternoon'] += 1
        else:
            hour_count['night'] += 1

    return JsonResponse({
        'labels_hour': list(hour_count.keys()),
        'data_hour': list(hour_count.values()),
    })

def dow(request): # bar chart to show no. of rides for each day fo the week 
    weekday_count = OrderedDict()
    weekday_count['monday'] = 0
    weekday_count['tuesday'] = 0
    weekday_count['wednesday'] = 0
    weekday_count['thursday'] = 0
    weekday_count['friday'] = 0
    weekday_count['saturday'] = 0
    weekday_count['sunday'] = 0

    for obj in dt_obj:
        if obj.weekday() == 0:
            weekday_count['monday'] += 1
        elif obj.weekday() == 1:
            weekday_count['tuesday'] += 1
        elif obj.weekday() == 2:
            weekday_count['wednesday'] += 1
        elif obj.weekday() == 3:
            weekday_count['thursday'] += 1
        elif obj.weekday() == 4:
            weekday_count['friday'] += 1
        elif obj.weekday() == 5:
            weekday_count['saturday'] += 1
        elif obj.weekday() == 6:
            weekday_count['sunday'] += 1
    
    return JsonResponse({
        'labels_day' : list(weekday_count.keys()),
        'data_day': list(weekday_count.values()),
    })

date_input.html (i have html files, titled charts.html , day.html , and hour.html for each chart respectively. the code is all quite similar in that they all use AJAX requests) date_input.html (i have html files, titled charts.html , day.html , and hour.html for each chart respectively. the code is all quite similar in that they all use AJAX requests)

{% load static %}

{% block content %}

<div class="date">
    <br>
    <h3>Select to view distance and orders by timeframe</h3>
    <form name="date-input" method="POST" action="/date-input/">
        <label for="start">Start date:</label>
        <input type="date" id="start" name="start_date" value="2019-01-01" min="2019-01-01" max="2019-06-30">

        <label for="end">End date:</label>
        <input type="date" id="end" name="end_date" value="2019-01-01" min="2019-01-01" max="2019-07-01">

        <br>
        <br>
    </form>
</div>

{% endblock content %}

<script src="https://code.jquery.com/jquery-3.5.1.js"></script>
<script>

var start_date = Date.parse($("#start").val())/1000; // const can't be re-assigned or redeclared. Date() to convert datetime into epoch time
var end_date = Date.parse($("#end").val())/1000;  // divide by 1000 to get 10 digits (compatible with values in DB)

    function ajaxRequest (){
        var start_date = Date.parse($("#start").val())/1000;
        var end_date = Date.parse($("#end").val())/1000;

        $.ajax({                       // initialize an AJAX request
            type: "POST",
            url: '/date-input/', // calls data from /date-input/ endpoint
            data: {
                'start_date': start_date,       // add the order id to the POST parameters
                'end_date': end_date,
                'csrfmiddlewaretoken': "{{csrf_token}}",
            },
            success: function (data) {   // `data` is from `homepage` view function
                console.log("this block of code isn't useless!!")
                console.log(data.start_date)
                console.log(data.end_date)
            },
            error: function (data, xhr, status, error) {
                console.log("yikes")
            }
        });
    }

    $("#start, #end").change(function() { // calling select id
        start_date = Date.parse($("#start").val())/1000;
        end_date = Date.parse($("#end").val())/1000;  // get the selected subject ID from the HTML dropdown list 

        if (start_date < end_date) {
            ajaxRequest();
        } 
    });
        

</script>

You can use Session Django Docs .您可以使用Session Django 文档

Edit the MIDDLEWARE setting and make sure it contains:编辑 MIDDLEWARE 设置并确保它包含:

MIDDLEWARE = [
    ...
    'django.contrib.sessions.middleware.SessionMiddleware',
    ...
]

And in your view then:然后在你看来:


def date_input(request):       
    if request.method == "POST": 
        context = {}

        start_date = request.POST.get("start_date", None) # type unicode
        end_date = request.POST.get("end_date", None)
        
        form = DateForm(request.POST or None)

        if form.is_valid():
            start_date = form.cleaned_data['start_date']
            end_date = form.cleaned_data['end_date']
            #  ADD your start_date and end_date to session
            request.session['start_date'] = start_date.strftime("%d/%m/%Y")
            request.session['end_date'] = end_date.strftime("%d/%m/%Y")
            # Here i would rename context variables to order_start_date and order_end_date to make more clear.
            # Because its QuerySet not date
            context['order_start_date'] = Order.objects.filter(member_created_time__gte=start_date) # this works
            context['order_end_date'] = Order.objects.filter(order_ended_time__lte=end_date)

            return render(request, 'date_input.html', context) # return JSON response to frontend
        else:
            print("form is not valid")  
    else:
        form = DateForm()
    return render(request, 'date_input.html', {
                  "form": form })

And any other view:以及任何其他观点:


from datetime import datetime

def charts(request):  # pie chart for payment type
    try:
        start_date = datetime.strptime(request.session.get('start_date'), "%d/%m/%Y")
        end_data = datetime.strptime(request.session.get('end_date'), "%d/%m/%Y") 
    except:
        start_date = "default_value"
        end_date = "default_value"
    # filter
    queryset = Order.objects.order_by('payment').values(
       'payment').annotate(payment_type=Count('payment'))
    
    default = list(queryset.values_list('payment_type', flat=True))
    labels = list(queryset.values_list('payment', flat=True))
    
    return JsonResponse({
        'labels': labels,  # payment methods
        'default': default,  # payment methods
    })

Create a context processor.创建上下文处理器。 it is a function that takes the request object as an argument and returns a dictionary that will be added to the request context.它是一个 function,它将请求 object 作为参数并返回将添加到请求上下文中的字典。 It will make your object globally available.它将使您的 object 全球可用。 Example, in a file called context_processors in your app named 'app'例如,在名为“app”的应用中名为 context_processors 的文件中

# app.context_processors.chart
def charts(request):
    return {'labels': yourquersethere}

Then register it, for it to be accessible然后注册它,以便它可以访问

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
                'app.context_processors.chart',
            ],
        },
    },
]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM