Снова здравствуйте! В этой части урока по созданию своей CMS с помощью Django мы сделаем:
Итак, начнем. Для начала создадим файл urls.py в каталоге app и добавим в него несколько строк кода.
Файл urls.py
#! /usr/bin/python
# -*- coding: utf-8 -*-
from django.conf.urls import patterns, url
# Здесь мы добавим возможность регистрации и авторизации пользователям
urlpatterns = patterns('app.views',
url(r'^profile/$', 'profile'),
url(r'^login/$', 'login_user'),
url(r'^logout/$', 'logout_user'),
url(r'^registration/$', 'registration'),
)
# Здесь наши страницы
urlpatterns += patterns('app.pages.views',
url(r'^$', 'index'),
url(r'^page/[a-z0-9-_]+', 'page'),
)
Комментарии излишни, но все же я их добавил. Дальше поработаем с файлом views в каталоге app.
Файл views.py
#! /usr/bin/python
# -*- coding: utf-8 -*-
from django.template import RequestContext
from django.http import Http404, HttpResponse
from django.utils.translation import ugettext as _
from django.contrib.auth.forms import AuthenticationForm
from django.shortcuts import render_to_response, redirect
from django.contrib.auth.decorators import login_required
from django.contrib.auth import authenticate, login, logout
from django.core.exceptions import ObjectDoesNotExist, ValidationError
from app.forms import RegistrationForm
def registration(request, backend = None):
if request.user.is_authenticated():
return redirect('app.pages.views.index')
form = RegistrationForm()
if request.method == 'POST':
form = RegistrationForm(request.POST)
if form.is_valid():
user = form
user.save()
user = authenticate(
username = form.cleaned_data['email'],
password = form.cleaned_data['password']
)
if user is not None:
login(request, user)
return redirect(index)
return render_to_response(
'registration.html', {
'form': form,
},
context_instance = RequestContext(request)
)
@login_required
def profile(request):
message = _('Your Personal Information has been changed. Thanks!')
form = RegistrationForm(instance = request.user)
if request.method == 'POST':
form = RegistrationForm(request.POST, instance = request.user)
if form.is_valid():
user = form
user.save()
return render_to_response(
'user_info.html', {
'form': form,
'message': message,
},
context_instance = RequestContext(request)
)
return render_to_response(
'user_info.html', {
'form': form,
},
context_instance = RequestContext(request)
)
def login_user(request):
if request.user.is_authenticated():
return redirect('app.pages.views.index')
form = AuthenticationForm()
if request.method == 'POST':
form = AuthenticationForm(data = request.POST)
if form.is_valid():
user = authenticate(
username = form.cleaned_data['username'],
password = form.cleaned_data['password']
)
if user is not None:
login(request, user)
return redirect(request.META['HTTP_REFERER'])
return render_to_response(
'login.html', {
'form': form
},
context_instance = RequestContext(request)
)
@login_required
def logout_user(request):
logout(request)
return redirect('app.pages.views.index')
Итак, здесь мы обращаемся к стандартной форме авторизации Django, а также, подключаем свою для регистрации и изменения профиля. Идем дальше. Теперь нужно создать форму регистрации. Создаем файл forms.py в папке app.
Файл forms.py
#! /usr/bin/python
# -*- coding: utf-8 -*-
from django import forms
from django.utils.translation import ugettext as _
# Подключаем свою модель пользователя
from app.models import User
class RegistrationForm(forms.ModelForm):
confirm_password = forms.CharField(
label = _('Confirm password'),
widget = forms.PasswordInput()
)
def clean(self):
cleaned_data = super(RegistrationForm, self).clean()
password = cleaned_data.get('password')
confirm_password = cleaned_data.get('confirm_password')
# Проверяем пароли на совпадение
if password and confirm_password and password != confirm_password:
msg = _('Passwords don\'t match')
self._errors['password'] = self.error_class([msg])
self._errors['confirm_password'] = self.error_class([msg])
del cleaned_data['password']
del cleaned_data['confirm_password']
return cleaned_data
def save(self, commit = True):
user = super(RegistrationForm, self).save(commit = False)
user.set_password(self.cleaned_data['password'])
if commit:
user.save()
return user
class Meta:
model = User
fields = (
'email', 'password', 'confirm_password', 'full_name',
)
widgets = {
'password': forms.PasswordInput(),
}
Далее, нам нужно создать шаблоны. Здесь, я думаю вы сами разберетесь. Теперь, создадим файл admin.py в каталоге pages.
Файл admin.py
#! /usr/bin/python
# -*- coding: utf-8 -*-
from django.contrib import admin
from django.utils.translation import ugettext as _
from app.pages.models import *
class PageMetaInfInline(admin.TabularInline):
model = PageMetaInf
extra = 0
class PageAdmin(admin.ModelAdmin):
prepopulated_fields = {
'slug': ('title',)
}
inlines = [
PageMetaInfInline,
]
fieldsets = (
(None, {
'fields': (
'title',
'slug',
'publish',
'homepage',
'content',
'parent',
'menu'
)
}),
)
list_display = (
'title',
'get_absolute_url',
'parent',
'publish',
'homepage',
'pub_date',
'change_date',
)
list_filter = (
'parent',
'homepage',
'publish',
)
admin.site.register(Page, PageAdmin)
Я думаю, пояснять его не нужно. Если он вызывает у вас вопросы, то вам лучше сходить почитать документацию по Django. Теперь создадим файл utils.py в том же каталоге, который будет возвращать урл страницы с учетом всех родителей.
Файл utils.py
#! /usr/bin/python
# -*- coding: utf-8 -*-
def get_all_ancestors(parent, url = ''):
url = '%s/%s' % (parent.slug, url)
if parent.parent:
return get_all_ancestors(parent.parent, url)
else:
return '/%s/' % url
Здесь представлена рекурсивная функция. Эта функция будет вызываться из метода get_absolute_url в классе Page. Идем дальше, осталось совсем чуть-чуть. Теперь создадим файл views.py в каталоге pages.
Файл views.py
#! /usr/bin/python
# -*- coding: utf-8 -*-
from django.http import Http404
from django.template import RequestContext
from django.shortcuts import render_to_response
from django.utils.translation import ugettext as _
from django.core.exceptions import ObjectDoesNotExist
from app.pages.models import Page
def index(request):
try:
page = Page.objects.get(homepage = True, publish = True)
except ObjectDoesNotExist:
raise Http404
return render_to_response(
'index.html',
{'page': page},
context_instance = RequestContext(request)
)
def page(request):
try:
path = request.path.lstrip('page')
path = path.strip('/').split('/')
page = Page.objects.get(
slug = path[-1], homepage = False, publish = True,
) or Page.objects.get(
slug = path[-1],
parent__slug = path[-2],
homepage = False,
publish = True,
)
except ObjectDoesNotExist:
raise Http404
return render_to_response(
'page.html',
{'page': page},
context_instance = RequestContext(request)
)
Немного поясню про path. Поскольку, урл у нас может быть довольно длинным(здесь зависит от количества родителей страницы), мы убираем из начала и конца символ / и с помощью функции split формируем список, который будет содержать каждого родителя и сам slug страницы. Дальше, поскольку у нас всегда должны быть уникальными slug родителя и slug самой страницы - их мы и отдаем по ключам -1 и -2.
Пока все. Третья часть опишет шаблонные теги и шаблоны. Спасибо за внимание!