Начав изучать django 2 месяца назад, я столкнулся со многими проблемами, в частности с очень малым освещением django в рунете, а те рецепты, которые есть либо уже устарели, либо сложны для начинающего. В данном рецепте хочу поделиться с начинающими «джангерами» своим опытом. Буду рад получить конструктивную критику, помощь в оптимизации и улучшении кода от опытных пользователей.
Итак, задача:
- Сделать форму обратной связи;
- Предусмотреть валидацию на стороне клиента (Ajax) и на стороне сервера;
- Защита от спама с использованием ReCaptcha;
- Предусмотреть тот вариант что клиент отключит поддержку Javascript в своем браузере;
- При нажатии кнопки отправить отправлять письмо на ваш email (my@mail.ry) и вывод страницы thanks.html.
Начнем...
Скачиваем модуль ReCaptcha для django и устанавливаем его.
Получаем 2 ключа.
В вашем файле settings.ру прописываем полученные значения
RECAPTCHA_PUBLIC_KEY = '*Key here*'
RECAPTCHA_PRIVATE_KEY = '*Key here*'
В вашем проекте создаем 2 файла: fields.py, widgets.py.
Код fields.py:
from django.conf import settings
from django import forms
from django.utils.encoding import smart_unicode
from django.utils.translation import ugettext_lazy as _
from widgets import ReCaptcha
from recaptcha.client import captcha
class ReCaptchaField(forms.CharField):
default_error_messages = {
'captcha_invalid': _(u'Invalid captcha')
}
def __init__(self, *args, **kwargs):
self.widget = ReCaptcha
self.required = True
super(ReCaptchaField, self).__init__(*args, **kwargs)
def clean(self, values):
super(ReCaptchaField, self).clean(values[1])
recaptcha_challenge_value = smart_unicode(values[0])
recaptcha_response_value = smart_unicode(values[1])
check_captcha = captcha.submit(recaptcha_challenge_value,
recaptcha_response_value,
settings.RECAPTCHA_PRIVATE_KEY, {})
if not check_captcha.is_valid:
raise forms.util.ValidationError(self.error_messages['captcha_invalid'])
return values[0]
Код widgets.py:
from django import forms
from django.utils.safestring import mark_safe
from django.conf import settings
from recaptcha.client import captcha
class ReCaptcha(forms.widgets.Widget):
recaptcha_challenge_name = 'recaptcha_challenge_field'
recaptcha_response_name = 'recaptcha_response_field'
def render(self, name, value, attrs=None):
return mark_safe(u'%s' % captcha.displayhtml(settings.RECAPTCHA_PUBLIC_KEY))
def value_from_datadict(self, data, files, name):
return [data.get(self.recaptcha_challenge_name, None),
data.get(self.recaptcha_response_name, None)]
Код views.py:
# -*- coding: utf-8 -*-
from django.shortcuts import render_to_response
from django.core.mail import send_mail
from django.http import HttpResponse
from django.template import RequestContext
from django.http import HttpResponseRedirect
from forms import *
def contact(request):
form = ReCaptchaForm()
if request.POST:
form = ReCaptchaForm(request.POST)
if form.is_valid():
cd = form.cleaned_data
send_mail(
cd['subject'],
cd['message'],
cd.get('email', 'noreply@example.com'),
['my@mail.ru'],
)
return HttpResponseRedirect('/contact/thanks/')
else:
form = ReCaptchaForm()
return render_to_response('contact.html', {'form': form}, context_instance=RequestContext(request))
def thanks(request):
return render_to_response('thanks.html')
Код contact.html:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title></title>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<meta name="Keywords" content=""/>
<meta name="description" content=""/>
<link rel="stylesheet" href="/site_media/css/validationEngine.jquery.css" type="text/css"/>
<link rel="stylesheet" href="/site_media/css/template.css" type="text/css"/>
<script src="/site_media/js/jquery-1.4.4.min.js" type="text/javascript">
</script>
<script src="/site_media/js/jquery.validationEngine-ru.js" type="text/javascript" charset="utf-8">
</script>
<script src="/site_media/js/jquery.validationEngine.js" type="text/javascript" charset="utf-8">
</script>
<script>
jQuery(document).ready(function(){
// binds form submission and fields to the validation engine
jQuery("#formID").validationEngine();
});
/**
*
* @param {jqObject} the field where the validation applies
* @param {Array[String]} validation rules for this field
* @param {int} rule index
* @param {Map} form options
* @return an error string if validation failed
*/
</script>
</head>
<body>
<form id="formID" class="formular" method="post" action="">
{% csrf_token %}
<fieldset>
{% if form.errors %}
<p style="color: red;" align="center"><strong>Please correct the error{{ form.errors|pluralize }} below.</strong><br></p>
{% endif %}
<legend>
Форма обратной связи<br />
</legend>
<label>
<strong><br />{{ form.subject.errors }}</strong>
<span>Vvedite temu soobshenia : </span>
{{ form.subject }}
</label>
<label>
<strong><br />{{ form.email.errors }}</strong>
<span>Vvedite email adress: </span>
{{ form.email }}
</label>
<label>
<strong><br />{{ form.message.errors }}</strong>
<span>Vvedite vashe soobshenie:</span>
{{ form.message }}
</label>
{% if form.recaptcha.errors %}
<div class="errmsg" style=" color: red;">
<strong>
<br /><br />
{{ form.recaptcha.errors|join:", " }}
</strong>
</div>
{% endif %}
<br />
{{ form.recaptcha }}
<input type="submit" class="submit" value="Send Form" />
</fieldset>
</form>
</body>
</html>
Код thanks.html:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title></title>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<meta name="Keywords" content=""/>
<meta name="description" content=""/>
</head>
<body>
<p>спасибо</p>
</body>
</html>
Код forms.py:
from django import forms
from fields import ReCaptchaField
class ReCaptchaForm(forms.Form):
subject = forms.CharField(
label='Your subject',
widget=forms.TextInput(
attrs={'class': 'validate[required] text-input'}))
email = forms.EmailField(
label='Your e-mail address',
required=False,
widget=forms.TextInput(attrs={'class': 'validate[required,custom[email]] text-input'}))
message = forms.CharField(
label='Your message',
widget=forms.Textarea(attrs={'class': 'validate[required,custom[onlyLetterNumber]] text-input'}))
recaptcha = ReCaptchaField()
Код urls.py:
from django.conf.urls.defaults import *
from django.conf import settings
from views import *
urlpatterns = patterns('',
# Example:
(r'contact/$',contact),
(r'^thanks/$', thanks),
)
Готовый Javascript скачиваем тут.
Результат можно посмотреть тут.
P.S. Коды, которые тут представлены можно найти https://github.com/posabsolute/jQuery-Validation-Engine и http://www.rkblog.rk.edu.pl/w/p/recaptach-django-forms/
Жду ваших конструктивной критики и помощь в оптимизации и улучшении кода от опытных пользователей.