Django. Своя CMS. Часть 2

Дата публикации:29 апреля 2013 г. 1:33:17

Снова здравствуйте! В этой части урока по созданию своей CMS с помощью Django мы сделаем:

  • Файл urls.py
  • Файл views.py
  • Файл utils.py
  • Файл forms.py
  • Создадим свою модель пользователя(просто для примера). И сделаем регистрацию пользователя. Ее создание я описывал здесь.
  • И еще что-нибудь

 Итак, начнем. Для начала создадим файл 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.

Пока все. Третья часть опишет шаблонные теги и шаблоны. Спасибо за внимание!

Метки:django, cms, система управления, python