有关基于Django项目的A / B测试的想法吗?

时间:2009-04-15 17:50:31

标签: django testing ab-testing

我们刚刚开始为基于Django的项目进行A / B测试。我是否可以获得有关此A / B测试的最佳实践或有用见解的一些信息。

理想情况下,每个新的测试页面都会使用单个参数进行区分(就像Gmail一样)。 mysite.com/?ui=2应该给出不同的页面。因此,对于每个视图,我需要编写一个装饰器来根据'ui'参数值加载不同的模板。而且我不想在装饰器中硬编码任何模板名称。那么urls.py url模式将如何?

9 个答案:

答案 0 :(得分:95)

答案 1 :(得分:12)

Django lean是A / B测试的好选择

http://bitbucket.org/akoha/django-lean/wiki/Home

答案 2 :(得分:7)

如果你使用像你建议的GET参数(?ui=2),那么你根本不需要触摸urls.py。你的装饰师可以检查request.GET['ui']并找到它需要的东西。

为避免硬编码模板名称,也许您可​​以从视图函数中包装返回值?您可以返回(template_name, context)的元组并让装饰器破坏模板名称,而不是返回render_to_response的输出。这样的事怎么样? 警告:我尚未测试此代码

def ab_test(view):
    def wrapped_view(request, *args, **kwargs):
        template_name, context = view(request, *args, **kwargs)
        if 'ui' in request.GET:
             template_name = '%s_%s' % (template_name, request.GET['ui'])
             # ie, 'folder/template.html' becomes 'folder/template.html_2'
        return render_to_response(template_name, context)
    return wrapped_view

这是一个非常基本的例子,但我希望它可以解决这个问题。您可以修改有关响应的其他几个内容,例如向模板上下文添加信息。您可以使用这些上下文变量与您的网站分析集成,例如Google Analytics。

作为奖励,如果你决定停止使用GET参数并转移到基于cookie等的东西,你可以在将来重构这个装饰者。

更新如果您已经编写了大量视图,并且不想全部修改它们,则可以编写自己的render_to_response版本。

def render_to_response(template_list, dictionary, context_instance, mimetype):
    return (template_list, dictionary, context_instance, mimetype)

def ab_test(view):
    from django.shortcuts import render_to_response as old_render_to_response
    def wrapped_view(request, *args, **kwargs):
        template_name, context, context_instance, mimetype = view(request, *args, **kwargs)
        if 'ui' in request.GET:
             template_name = '%s_%s' % (template_name, request.GET['ui'])
             # ie, 'folder/template.html' becomes 'folder/template.html_2'
        return old_render_to_response(template_name, context, context_instance=context_instance, mimetype=mimetype)
    return wrapped_view

@ab_test
def my_legacy_view(request, param):
     return render_to_response('mytemplate.html', {'param': param})

答案 3 :(得分:1)

Justin的回答是对的...我建议你投票给那个,因为他是第一个。如果您有多个需要此A / B调整的视图,他的方法特别有用。

但请注意,如果您只有少量视图,则不需要装饰器或urls.py的更改。如果您将urls.py文件保留原样...

(r'^foo/', my.view.here),

...您可以使用request.GET来确定所请求的视图变体:

def here(request):
    variant = request.GET.get('ui', some_default)

如果您想避免为单个A / B / C / etc视图编写模板名称的硬编码,只需在模板命名方案中使它们成为惯例(正如Justin的方法也推荐):

def here(request):
    variant = request.GET.get('ui', some_default)
    template_name = 'heretemplates/page%s.html' % variant
    try:
        return render_to_response(template_name)
    except TemplateDoesNotExist:
        return render_to_response('oops.html')

答案 4 :(得分:1)

基于Justin Voss的代码:

def ab_test(force = None):
    def _ab_test(view):
        def wrapped_view(request, *args, **kwargs):
            request, template_name, cont = view(request, *args, **kwargs)
            if 'ui' in request.GET:
                request.session['ui'] = request.GET['ui']
            if 'ui' in request.session:
                cont['ui'] = request.session['ui']
            else:
                if force is None:
                    cont['ui'] = '0'
                else:
                    return redirect_to(request, force)
            return direct_to_template(request, template_name, extra_context = cont)
        return wrapped_view
    return _ab_test

使用代码的示例函数:

@ab_test()
def index1(request):
    return (request,'website/index.html', locals())

@ab_test('?ui=33')
def index2(request):
    return (request,'website/index.html', locals())

这里发生了什么: 1.传递的UI参数存储在会话变量中 2.每次加载相同的模板,但上下文变量{{ui}}存储UI id(您可以使用它来修改模板) 3.如果用户进入没有?ui = xx的页面,那么在index2的情况下,他被重定向到'?ui = 33',在index1的情况下,UI变量被设置为0。

我使用3从主页面重定向到Google网站优化工具,后者又会使用正确的?ui参数重定向回主页面。

答案 5 :(得分:1)

这些答案似乎陈旧。如今,Google Analytics可能是大多数网站上最受欢迎且最好的免费选项。以下是将django与Google Analytics集成的一些资源:

<强>插件

如何

答案 6 :(得分:1)

Django-lean看起来很棒。我打算试着弄清楚它。我最终推出了自己的解决方案,这足以满足我的目标。我试图很好地打包它,让初学者使用起来很方便。这是超级基础,试一试:

https://github.com/crobertsbmw/RobertsAB

答案 7 :(得分:0)

我为django编写了一个拆分测试示例,任何看这个的人都会觉得有用 -

https://github.com/DanAncona/django-mini-lean

喜欢听到你对此的看法,以及如何让它更有帮助!

答案 8 :(得分:0)

您还可以使用Google Optimize进行A / B测试。为此,您必须将Google Analytics(分析)添加到您的网站,然后在创建Google Optimize实验时,每个用户都会获得一个具有不同实验变体的Cookie(根据每个变体的权重)。然后,您可以从Cookie中提取变体并显示应用程序的各种版本。您可以使用以下代码段提取变体:

ga_exp = self.request.COOKIES.get("_gaexp")

parts = ga_exp.split(".")
experiments_part = ".".join(parts[2:])
experiments = experiments_part.split("!")
for experiment_str in experiments:
    experiment_parts = experiment_str.split(".")
    experiment_id = experiment_parts[0]
    variation_id = int(experiment_parts[2])
    experiment_variations[experiment_id] = variation_id

但是,有一个django软件包可以很好地与Google Optimize集成:https://github.com/adinhodovic/django-google-optimize/

这是有关如何使用该软件包以及Google Optimize如何工作的博客文章:https://hodovi.cc/blog/django-b-testing-google-optimize/