• Aucun résultat trouvé

Adding Akismet Support

Dans le document Projects Django (Page 152-155)

Now let’s add in the second layer of spam prevention: statistical spam analysis by the Akismet web service. The first thing you’ll need is an Akismet API key—all access to Akismet’s service requires this key. Luckily, it’s free for personal, noncommercial use. Just follow the instructions on the Akismet web site (http://akismet.com/personal/) to get a key. Once you’ve got it, open up the Django settings file for the cmsproject and add the following line to it:

AKISMET_API_KEY = 'your API key goes here'

By making this a custom setting, you’ll be able to reuse the Akismet spam filtering on other sites, even if they have different API keys.

Akismet is a web-based service. You send information about a comment to the service using an HTTP request, and it sends back an HTTP response telling you whether Akismet thinks that comment is spam. You could build up the code necessary to do this, but—as you’ll often find when working with Python—someone else has already done it and made the code available for free.

In this case, it’s a module called akismet, which is available from the author, Michael Foord, at his web site: www.voidspace.org.uk/python/modules.shtml#akismet. Go ahead and download and unpack it (it should come in a .zip file). This will give you a file named akismet.pythat you can put on your Python import path (ideally, in the same location as thecoltranedirectory that holds the weblog application).

The akismetmodule includes a class called Akismetthat handles the API. This class has two methods you’ll be using: one called verify_key(), which ensures you’re using a valid API key, and one called comment_check(), which submits a comment to Akismet and returns Trueif Akismet thinks the comment is spam.

So the first thing you’ll need to do is import the Akismetclass:

from akismet import Akismet

The Akismet API requires both the API key you’ve been assigned and the address of the site you’re submitting the comment from. You could hard-code the URL of your site in here, but that would hurt the reusability of the code. A better option is to use Django’s bundled sites framework (it lives in django.contrib.sites), which provides a model that represents a partic-ular web site and knows which site is currently active.

You’ll recall that back in Chapter 2, when you set up the simple CMS, you edited a Site object so it would “know” where you were running the development server. Whenever you’re running with this database and settings file, you can get that Siteobject with the following:

from django.contrib.sites.models import Site current_site = Site.objects.get_current()

This works because the Sitemodel has a custom manager that defines the get_current() method. The Siteobject it returns has a field called domain, which you can use to fill in the information Akismet wants. This information is the keyword argument blog_urlwhen creat-ing an instance of the API (along with the API key, which comes from your settcreat-ings file and is the keyword argument key):

from django.conf import settings

from django.contrib.sites.models import Site akismet_api = Akismet(key=settings.AKISMET_API_KEY,

blog_url="http:/%s/" %

Site.objects.get_current().domain)

Then you can check your API key with the verify_key()method and, if it’s valid, submit a comment for analysis with the comment_check()method. The comment_check()method is going to expect three arguments:

• The text of the comment to check.

• Some additional “metadata” about the comment, in a dictionary.

• A boolean (Trueor False) argument telling it whether to try to work out additional metadata on its own.

The text of the comment is easy enough to get, since it’s a field on the comment itself. The dictionary of metadata needs to have at least four values in it, even if some of them are blank (because you don’t necessarily know what they are). These values are the type of comment (which, for simple uses like this, is simply the string comment), the HTTP Refererheader value, the IP address from which the comment was sent (also a field on the commentmodel), and the HTTP User-Agentof the commenter. Finally, you’ll tell the akismetmodule to go ahead and work out any additional metadata it can find. More information means better accuracy, espe-cially since the akismetmodule can, under some server setups, find some useful information automatically. The code looks like this:

from django.utils.encoding import smart_str if akismet_api.verify_key():

akismet_data = { 'comment_type': 'comment', 'referrer': '',

'user_ip': instance.ip_address,

Remember that Django uses Unicode strings everywhere, so whenever you use an exter-nal API, you should convert Unicode strings to bytestrings by using the helper function django.utils.encoding.smart_str().

And note that since you don’t know what the HTTP Refererand User-Agentheaders are—

that information is only available inside the view function that processes the submission, since it has access to the HTTP request—you simply leave them as empty strings.

Once you put it all together, the complete comment-moderation function, with both age-based and statistical Akismet filtering, looks like this:

import datetime

The best place to put this is near the bottom of coltrane/models.pyso that the

dispatcher.connect()line will be read and executed when the weblog’s models are imported.

This also does away with the need for at least one of the imports—the import datetimeline—

because it’s already been imported in that file.

Dans le document Projects Django (Page 152-155)