简体   繁体   English

Django和Backbone逐步增强 - 如何整合这两者?

[英]Progressive enhancement with Django and Backbone - how to integrate the two?

I have a very simple Django app that lets users submit a form and see a filtered list of holidays, based on country, duration and price. 我有一个非常简单的Django应用程序,它允许用户根据国家,持续时间和价格提交表单并查看过滤的假期列表。

I would like to use Backbone in the front-end, so that users with JS enabled don't need to GET to see results, but can load them dynamically. 我想在前端使用Backbone,因此启用JS的用户不需要GET来查看结果,但可以动态加载它们。

I want to use progressive enhancement , so that users with JS get the Backbone experience, and users without JS can still use the form. 我想使用渐进增强功能 ,以便拥有JS的用户获得Backbone体验,而没有JS的用户仍然可以使用该表单。 I also want to follow the DRY principle . 我也想遵循DRY原则

My question is how best to do this. 我的问题是如何最好地做到这一点。 Are there examples of using the two together with minimal repetition? 是否有将两者一起使用且重复次数最少的例子? I'm thinking in particular of: 我特别在想:

  1. Routing a URL like /italy/1-week/from-500-to-1000/ - do I now need to write two sets of routing code, one in Django's urls.py and one in Backbone's router, to get the country/duration/price parameters? 路由一个像/italy/1-week/from-500-to-1000/的URL我现在需要编写两组路由代码,一个在Django的urls.py ,一个在Backbone的路由器中,以获取国家/持续时间/价格参数?
  2. Filtering the data, based on the parameters - do I need to write two separate ways of doing this, one in views.py and one in Backbone? 根据参数过滤数据 - 我是否需要编写两种不同的方法,一种在views.py ,一种在Backbone中? (I assume I can at least use a single API for both calls.) (我假设我至少可以为这两个调用使用一个API。)
  3. Rendering in templates - do I need to write one list template for Django and another for Backbone, or can both use the same templates? 在模板中渲染 - 我是否需要为Django编写一个列表模板,为Backbone编写另一个列表模板,还是可以使用相同的模板?

The best (only) example I've found of integrating Backbone into Django so far is Josh Bohde's Django Backbone repo , which is not progressively enhanced. 到目前为止,我发现将Backbone整合到Django中的最好(唯一)示例是Josh Bohde的Django Backbone repo ,它没有逐步增强。

I've also found this blog post on progressive enhancement with Backbone and Rails , but it would be really useful to see something similar for Django. 我也发现这篇关于使用Backbone和Rails进行渐进增强的博客文章 ,但看到类似于Django的东西真的很有用。

UPDATE: Just found this SO question on a similar topic - is the situation really as hopeless as the answer makes it sound? 更新:刚刚在一个类似的主题上发现了这个问题 - 这种情况真的是无望的,因为答案听起来很合理吗?

is the situation really as hopeless as the answer makes it sound? 这种情况真的是无望的,因为答案听起来很合理吗?

Pretty much. 差不多。 But, since I work on a site that used to be Django-based but is now becoming Backbone-based, I can offer a few thoughts: 但是,由于我在一个曾经基于Django但现在变成基于Backbone的网站上工作,我可以提供一些想法:

Routing a URL like /italy/1-week/from-500-to-1000/ - do I now need to write two sets of routing code, one in Django's urls.py and one in Backbone's router, to get the country/duration/price parameters? 路由一个像/ italy / 1-week / from-500-to-1000 /的URL我现在需要编写两组路由代码,一个在Django的urls.py中,一个在Backbone的路由器中,以获取国家/持续时间/价格参数?

Yes, but there are ways to minimize duplication. 是的,但有办法减少重复。 The approach we took was to have Django spit out all the URLs as JS variables on to our main HTML page template: 我们采用的方法是让Django将所有URL作为JS变量吐出到我们的主HTML页面模板上:

<script>
URLS.report_error = "{% url app.log_client_error_view %}";
URLS.access_file = "{% url app.access_file_view 12345 %}";
</script>

Now we have a pattern of using 12345 for the parameters in every URL we generate; 现在我们有一个模式,使用12345作为我们生成的每个URL中的参数; this makes it easy to convert that URL back in to a Backbone route regex, because we can basically replace 12345 with ([^/]+) . 这样可以很容易地将该URL转换回Backbone路由正则表达式,因为我们基本上可以用([^/]+)替换12345

In the interest of full disclosure, we do have a bunch of route regexs that are written "by hand", but this isn't because we couldn't automate them; 为了完全公开,我们确实有一堆“手工”写的路由正则表达式,但这不是因为我们无法自动化它们; it's just that we're moving away from the Django side of things, so we have no reason to clean that code up. 只是我们正在离开Django方面,所以我们没有理由清理那些代码。 If you want to get hard-core about supporting both, you should be able to come up with a pretty easy/simple translation scheme. 如果你想获得支持两者的核心,你应该能够提出一个非常简单/简单的翻译方案。

Filtering the data, based on the parameters - do I need to write two separate ways of doing this, one in views.py and one in Backbone? 根据参数过滤数据 - 我是否需要编写两种不同的方法,一种在views.py中,一种在Backbone中? (I assume I can at least use a single API for both calls.) (我假设我至少可以为这两个调用使用一个API。)

This is a basically unavoidable problem on any site, not just Backbone/Django. 这在任何网站上都是一个基本上不可避免的问题,而不仅仅是Backbone / Django。 You have to filter data on the server-side because you can never trust the client-side (the user could disable JS, for instance). 必须在服务器端过滤数据,因为您永远不能信任客户端(例如,用户可以禁用JS)。 At the same time, server-side-only filtering is sooo 1990's, so you need to create (duplicate) logic for filtering on the client-side also (that way you can tell the user "you forgot to provide field X" without waiting for a round-trip to the server). 同时,仅服务器端过滤是sooo 1990,所以你需要创建(复制)逻辑以在客户端进行过滤(这样你就可以告诉用户“你忘了提供字段X”而无需等待用于往返服务器)。

However, there are ways to limit this duplication. 但是,有一些方法可以限制这种重复。 I didn't work on this piece myself, but I know a co-worker managed to use Django forms in an odd way (he took the form Django provided, then parsed them slightly before using them as a template for a Backbone View). 我自己并没有在这篇文章上工作,但我知道一个同事设法以奇怪的方式使用Django表单(他采用了Django提供的形式,然后稍微解析它们,然后将它们用作Backbone View的模板)。 This didn't eliminate duplication entirely, and unfortunately I can't remember any details, but it did help. 这并没有完全消除重复,不幸的是我不记得任何细节,但它确实有所帮助。

Rendering in templates - do I need to write one list template for Django and another for Backbone, or can both use the same templates? 在模板中渲染 - 我是否需要为Django编写一个列表模板,为Backbone编写另一个列表模板,还是可以使用相同的模板?

Handlebars templates have a similar syntax to Django templates if all you're doing is variables ( {{foo}} ). 如果您所做的只是变量( {{foo}} ),则Handlebars模板具有与Django模板类似的语法。 If you want to share logic between, the two have slightly different syntax ( {% if foo %} vs. {{#if foo}} ), but they're close enough that if you don't mind doing a little parsing work you should easily be able to convert one in to another. 如果你想在它们之间共享逻辑,那么两者的语法略有不同( {% if foo %} vs. {{#if foo}} ),但它们足够接近,如果你不介意做一点解析工作你应该很容易将一个转换成另一个。

So yeah, you're taking on A LOT of work just to support a very small subset of your users (the ones with browsers that can't support Backbone). 所以,是的,你承担了很多工作只是为了支持你的一小部分用户(那些使用不支持Backbone的浏览器)。 I strongly recommend you look at your user's browser stats on somewhere like Google Analytics (or look at general web stats if your site isn't up yet) to decide if all that trouble really is worth it for such a small percentage of your user base. 强烈建议您在某些地方查看用户的浏览器统计信息(如果您的网站尚未启动,请查看常规网络统计信息),以确定是否所有这些问题确实值得您这么小比例的用户群。 Without statistics, you can't know how small that percentage is, and obviously a key factor in that decision. 如果没有统计数据,您无法知道该百分比有多小,显然是该决定的关键因素。

For us the choice was obvious: require our users to use browsers made this century (which is pretty much all Backbone needs) and just go all Backbone. 对我们来说,选择是显而易见的:要求我们的用户使用本世纪开发的浏览器(这几乎都是Backbone需要的),并且只需要使用所有Backbone。 But if that choice isn't as obvious for you ... good luck trying to DRY up your Django and Backbone code :-) 但是,如果这个选择对你来说不那么明显......祝你好运,试图干掉你的Django和Backbone代码:-)

I just read about a totally different solution to this problem that I thought I'd share: HTML Snapshots (https://developers.google.com/webmasters/ajax-crawling/docs/html-snapshot). 我刚刚读到了一个完全不同的解决方案,我认为我会分享这个问题:HTML快照(https://developers.google.com/webmasters/ajax-crawling/docs/html-snapshot)。 The page I linked is Java-based, but you could certainly set something similar up in Python/Django. 我链接的页面是基于Java的,但你可以在Python / Django中设置类似的东西。

The basic idea is that you setup a headless Javascript runner on your server, and when a web crawler hits your site you use that JS runner to generate the HTML that your Backbone code would have generated had it been run normally in the client. 基本思想是在服务器上设置无头Javascript运行器,当网络爬虫到达您的站点时,您使用该JS运行器生成Backbone代码在客户端正常运行时生成的HTML。 It then sends that HTML back to the web crawler, letting you have one set of code for both client and server. 然后它将该HTML发送回Web爬虫,让您拥有一组客户端和服务器代码。

There may be some minor potential issues with running a headless JS runner (they're not 100% identical to a web browser's built-in JS) but when used for this "HTML Snapshot" approach they shouldn't be too relevant. 运行无头JS运行器可能存在一些小的潜在问题(它们与Web浏览器的内置JS不完全相同)但是当用于这种“HTML快照”方法时,它们应该不太相关。

Not sure if you're still grappling with this but I have been working on finding some solutions to this problem. 不确定你是否还在努力解决这个问题,但我一直在努力寻找解决这个问题的方法。 I wrote up a preliminary blog post on it: 我写了一篇关于它的初步博客文章:

JavaScript frameworks interoperability with Django JavaScript框架与Django的互操作性

which I will be following up in a couple of weeks with a full on example of a "Notes" app done using Django + Backbone + Marionette + Some Other Plugins. 我将使用Django + Backbone + Marionette +一些其他插件完成关于“Notes”应用程序的完整示例,我将在几周后跟进。

The code will demonstrate how to use Django templates at the client side as well, so it may be useful to you. 代码将演示如何在客户端使用Django模板,因此它可能对您有用。

If interested you can either following my blog or twitter (better) @sid_azad 如果有兴趣,您可以关注我的博客或推特(更好)@sid_azad

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

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