close

Вход

Забыли?

вход по аккаунту

Котов Роман Игоревич. Моделирование и реализация ядра приложения для подачи заявок на повышенную стипендию

код для вставки
Аннотация
Магистерская диссертация на тему «Моделирование и реализация ядра приложения для подачи заявок на повышенную стипендию» содержит 61
страницу текста, рисунков – 28, использованных источников – 15.
В настоящий момент веб приложения востребованы в связи с нарастающей
необходимостью автоматизации процесса бумажного делопроизводства.
Ключевые слова: веб-приложение, повышенная стипендия, база-данных, ре-
ализация ядра приложения.
Предмет исследования: Проектирование и разработка ядра веб приложения
для подачи заявок на повышенную стипендию.
Объект исследования: Ядро веб приложения приложения для подачи заявок
на повышенную стипендию.
Цель работы: Разработать структуру ядра веб приложения с учетом особен-
ностей подачи заявок на повышенную стипендию. Выполнить программную
реализацию приложения на современном языке программирования. Произвести апробацию приложения и выполнить тестирование.
Разработка приложения: Для разработки применяется высокоуровневый
язык программирования Python, а так же веб фреймворк django.
Результаты
работы:
В
магистерской
диссертации
разработано
веб-
приложение на языке Python, позволяющее студентам подавать заявки на
повышенную стипендию.
Работа имеет теоретическое и практическое значение, т.к. разработан-
ный комплекс программ может применяться для дальнейшего расширения
системы, по автоматизации процессов ведения документооборота Орловского Государственного Университета им. И.С. Тургенева.
4
Abstract
Master’s thesis on "Modeling and implementing the application core for
applying for an advanced scholarship"contains 61 pages of text, figures 28, of
sources used - 15.
At the moment, web applications are in demand in connection with the growing
need to automate the paper workflow process.
Keywords:
web
application,
increased
scholarship,
database-data,
implementation of the application kernel.
Subject of study. Designing and developing a web application core for applying
for an advanced scholarship.
Object of the research. The core of the application web application for applying
for an advanced scholarship.
The purpose of the work. Develop the structure of a web application kernel
with taking into account the specifics of applying for an advanced scholarship.
Implement the software implementation of the application in modern language
programming. Test the application and run testing.
Application
development.
To
develop
a
high-level
programming
language
Python, as well as the web framework django.
The results of the work. In master’s thesis a web application in Python language
was developed, which allows students to apply for an advanced scholarship.
The work has theoretical and practical importance, because the developed
software can be used for further expand the system, to automate the processes
of document management Orel State University.
5
Содержание
Введение
7
Глава I Постановка задачи
13
§1.1 Описание предметной области.
§1.2 Постановка задачи
. . . . . . . . . . . . . . . . . .
13
. . . . . . . . . . . . . . . . . . . . . . . . .
15
Глава II Разработка приложения
17
§2.1 Модель . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
17
§2.2 Аутентификация
. . . . . . . . . . . . . . . . . . . . . . . . . .
23
§2.3 Регистрация студентов . . . . . . . . . . . . . . . . . . . . . . .
25
§2.4 Авторизация студентов . . . . . . . . . . . . . . . . . . . . . . .
30
§2.5 Достижения студентов
. . . . . . . . . . . . . . . . . . . . . . .
34
§2.6 Регистрация заявок на повышенную стипендию . . . . . . . . .
41
§2.7 Проверка заявок администратором системы . . . . . . . . . . .
49
Глава III Тестирование приложения
54
§2.1 Авторизация и аутентификация . . . . . . . . . . . . . . . . . .
54
§2.1 Подача заявки на повышенную стипендию . . . . . . . . . . . .
57
Заключение
60
Список литературы
62
Приложение
64
6
Введение
Обоснование выбора темы и ее актуальность
Правильное и качественное хранение и предоставление информации
всегда являлось одной из важнейших проблем. Какая бы отрасль человеческой деятельности не была приведена в пример, так или иначе, она завязана на хранении больших объемов информации, к которым необходим
беспрепятственный доступ, и количество потерь которой должно быть сведено к минимуму. В частности, область деятельности успешного студента
вуза ставит его перед необходимостью подачи заявок на повышенную государственную академическую стипендию. Выполнение данного аспекта является важной и ответственной задачей: необходимо применять индивидуальный подход к организации своих достижений и их отличительных черт.
Беря во внимание кропотливость выполняемой работы, поставленная задача становится одной из важнейших, в рамках упрощения и систематизации
всей деятельности как преподавателей ВУЗа, так и его студентов.
Необходимость рационального подхода к образовательной деятельности, приводит к необходимости автоматизации ее составляющих. Наиболее
качественно, поставленную цель можно выполнить, прибегнув к использованию баз банных (БД). Для больших информационных ресурсов, связанных
между собой определенной логикой, применение БД подходит как нельзя
лучше. Для операций же над ними существуют Системы Управления Базами Данных (СУБД). БД составляют основы комплексов обработки информации, которые называют Информационными Системами (ИС). Для того,
чтобы качественно и эффективно спроектировать БД для ИС, необходимо,
прежде всего, охватить описание предметной области всесторонне полно.
Не менее важно и то, что правильное проектирование БД должно сокра-
7
тить избыточность хранимых данных, не нарушить их целостность, а также
максимально уменьшить затраты на обработку информации.
Кроме того, решения поставленной задачи, целесообразно достичь при
помощи современных веб-технологий, таких как веб-фреймворк, т.е. программного обеспечения, облегчающего разработку и объединение разных
компонентов большого программного проекта. Данная отрасль программирования помогает реализовать проект наиболее интуитивно: представить конечный результат визуально просто, сделав разработанное приложение наиболее наглядным, что и будет наиболее полным образом отвечать требованиям заданной предметной области.
Таким
образом
актуальность
темы
определяется
необходимостью
упростить трудоемкий процесс составления заявок на получение повышенной государственной академической стипендии и, как следствие, избавления
от необходимости заполнения данных документов на бумажном носителе [1].
Степень разработанности проблемы
В ходе работы, был проведен обзор доступных средств сбора научной
деятельности с целью нахождения варианта, в полной мере удовлетворяющего сформулированным требованиям.
Истина [2] - система управления информацией о результатах научно-
исследовательской и педагогической деятельности. Система предназначена
для сбора, учета, систематизации, хранения, анализа и выдачи по запросу
информации, характеризующей результаты деятельности научных и образовательных организаций.
Эта система управления информацией не удовлетворяет заданным требованиям в полном объеме, и в следствии чего является неподходящей, в
рамках заданной предметной области.
1С:Университет [3] - решение для автоматизации управленческой де-
ятельности вуза. Продукт охватывает все уровни деятельности основных
8
подразделений учреждения высшего профессионального образования и интегрируется с типовыми решениями фирмы «1С» для бухгалтерии и отдела
кадров.
Вышеописанная система плохо отвечает требованиям для подачи заявок на повышенную стипендию, что делает ее неподходящим инструментом
в рамках выполнения поставленной задачи.
Academic Line [4] - система управления научно-исследовательской де-
ятельностью, разработанная специалистами VP GROUP, предназначена для
того, чтобы обеспечить информационную и организационную поддержку деятельности вуза.
Данный инструмент, в том, что касается выполнения поручений, имеющих отношение к учебной части, является недостаточно подходящим и как
следствие непригодным.
Предмет исследования
Cодержательные и практические аспекты проектирования БД, а так
же практические аспекты разработки ядра веб-приложения для подачи заявок на повышенную стипендию согласно принципу MTV.
Объект исследования
Процесс проектирования и реализации полнофункциональный информационной системы, отвечающей требованиям заданной предметной области, а так же создание веб-интерфейса-инструмента, позволяющего осуществить взаимодействие с реализованной БД.
Цель работы
Смоделировать и разработать структуру ядра приложения для подачи
заявок на повышенную стипендию с учетом особенностей вузовской органи-
9
зации данного процесса.
Основные задачи исследования:
∙
Спроектировать БД, в которой будут храниться данные о достижениях студентов Орловского Государственного Университета имени И.С.
Тургенева;
∙
Результат
проектирования
представить
в
виде
набора
объектно-
реляционных моделей в контексте фреймворка Django;
∙
Разработать веб-интерфейс для взаимодействия с набором объектнореляционных моделей в контексте фреймворка Django таким образом,
что бы он мог предоставить CRUD-доступ (создание, чтение, изменение, удаление) к представленным моделям.
Метод исследования
Для реализации поставленных задач использовались несколько методов исследования:
∙
по степени автоматизации проектирования – метод компьютерного
проектирования, который производит генерацию или конфигурацию
(настройку) проектных решений на основе использования специальных инструментальных программных средств;
∙
по степени использования типовых проектных решений – метод оригинального (индивидуального) проектирования, когда проектные решения разрабатываются «с нуля» в соответствии с требованиями к веб
приложению;
10
Теоретическое и практическое значение работы
Разработанный комплекс программ может применяться для дальнейшего расширения системы, по автоматизации процессов ведения документооборота Орловского Государственного Университета им. И.С. Тургенева.
Содержание работы
Анализ регламента подачи документов и конкурсного отбора на получение повышенной государственной академической стипендии, используемого в вузе. Разработка и моделирование базы данных и связей между ее
объектами для веб приложения [5]. Разработка программного кода обработчиков форм и запросов со стороны клиента.
Апробация работы
Промежуточные результаты разработки были опубликованы в следующих научных работах:
1. Проектирование базы данных для приложения по подаче заявок
на повышенную стипендию // Вестник науки. Сборник научныхработ аспирантов, магистрантов и студентов физико-математического факультета,
г. Орел, Орловский государственный университет им. И.С. Тургенева, 26
декабря 2017 г. С. 28-30.
2. Моделирование и реализация интерфейса приложения для подачи
заявок на повышенную стипендию // семинар «Вычислительные технологии
и их приложения» г. Орел, ОГУ им. И.С. Тургенева, на основании Распоряжения ректора ОГУ от 15.11.2017 № 577р, 28 июня 2018 г.
Выбор инструментов:
∙
MySQL Workbench [6]. Позволяет осуществить визуальное проектирование базы данных;
11
∙
Язык программирования Python [7]. Он обладает простым и интуитивным синтаксисом, подробной документацией, а так же он совместим со
множеством современных платформ;
∙
Фреймворк для создания веб-приложений Django [8]. Так же обладает подробной документацией, основан на языке Python, поддерживает
архитектуру MTV и встроенный ORM;
∙
Система контроля версий проекта Git [9]. Необходим для создания резервных копий проекта на разных его стадиях;
Практическая ценность работы: настоящая работа охватывает индивидуальные особенности составления заявок на получение повышенной
государственной академической стипендии, учитывает возникшую необходимость анализа данных, позволяя, в значительной степени, упростить и
максимально автоматизировать процесс составления заявок на получение
повышенной государственной академической стипендии.
Структура работы:
в первой главе проводится постановка задачи
на основе анализа процесса составления заявки на получение повышенной
государственной академической стипендии. Вторая глава сосредоточена на
описании реализации правильно спроектированной БД [10] и принципов реализации веб-интерфейса-инструмента, осуществляющего взаимодействие с
спроектированной БД, с использованием основных инструментов.
12
Глава I Постановка задачи
1.1 Описание предметной области.
Каждый
учебный
семестр
студенты
Орловского
Государственного
Университета им. И.С. Тургенева, обучающиеся по очной форме обучения за
счет бюджетных ассигнований федерального бюджета и имеющие особые достижения в учебной, научно-исследовательской, общественной, культурнотворческой и спортивной деятельности могут сформировать портфолио, которое включает в себя:
- заявление на имя ректора на участие в конкурсе на получение повышенной государственной академической стипендии;
- характеристику, подписанную директором института/деканом факультета, руководителем направления, которая должна носить строго индивидуальный характер, с обязательным указанием среднего балла зачетной
книжки за последние два семестра;
- копию зачетной книжки, заверенную в деканате;
- копию зачетной книжки активиста;
- список опубликованных научных работ, исполняемых проектов (грантов), объектов интеллектуальной собственности, заверенных в деканате или
заведующим кафедрой;
- копии опубликованных научных работ (титульный лист, содержание,
статья), заверенные у заведующего кафедрой/научного руководителя студента;
- копии дипломов, грамот и сертификатов, подтверждающие участие
обучающегося в мероприятиях, проводимых университетом, при участии
университета или по направлению университета;
Таким образом систематическое составление портфолио для получения повышенной государственной академической стипендии имеет опреде-
13
ленную структуру, соблюдение которой, в конечном итоге, приводит к формирования обозначенного документа, пригодного для сдачи.
Каждый учебный год у студентов Орловского Государственного Университета им. И.С. Тургенева возникает необходимость составления анкеты
на получение повышенной государственной академической стипендии. Особенность структуры данного документа состоит в указании индивидуальных
достижений отдельно взятого студента. Ими могут быть: грамоты, дипломы,
похвальные листы, те или иные сертификаты и т.п.[11]
14
1.2 Постановка задачи
Была поставлена задача разработать веб-приложение, позволяющее
максимально просто составлять заявки на получение повышенной государственной
академической
стипендии.
Функциональность
данного
веб-
приложения должна позволять пользователю добавлять/изменять, а так же
сохранять/загружать все данные, задействованные при генерации такой анкеты.
Для достижения поставленной задачи необходимо правильно спроектировать базу данных, которая должна хранить в себе информацию об индивидуальных достижениях студентов. Затем, на основании спроектированной
БД, разработать веб-итерфейс для взаимодействия с ней, тем самым максимально автоматизировав процесс подачи заявок на получение повышенной
государственной академической стипендии.
Данный продукт должен соответствовать следующим требованиям:
∙
Функциональность: веб-приложение должно предоставлять пользователю возможность добавлять/изменять, а также сохранять/загружать
все данные, задействованные при добавлении индивидуальных достижений;
∙
Простота использования: интерфейс веб-приложения должен быть
простым настолько, насколько это возможно;
∙
Конфиденциальность: каждый пользователь должен иметь доступ
только к своим личным данным;
∙
БД должна быть спроектирована в соответствии с требованиями заданной предметной области;
∙
БД должна быть нормализована, т.е. должны быть устранены все недостатки структуры, приводящие к избыточности, которая, в свою оче-
15
редь, потенциально приводит к различным аномалиям и нарушениям
целостности данных;
∙
Спроектированная БД должна быть описана средствами языка Python
в виде набора объектно-реляционных моделей в контексте фреймворка
Django;
∙
Фреймворк Django должен быть использован таким образом, чтобы
написанный код был связным, т.е. сосредоточенным на выполнении
одной единственной вещи;
∙
Фреймворк Django должен быть использован таким образом, чтобы
написанный код был тестируемым, т.е. таким, чтобы в нем легко можно
было обнаружить проблемы;
∙
Веб-интерфейс
должен
использовать
возможности
ORM
(Object-
Relational Mapping), которые предоставляет фреймворк Django;
∙
Веб-интерфейс должен предоставить возможность выполнения всех
базовых операций (создание, чтение, изменение, удаление) для взаимодействия с каждой из таблиц, представленных в базе данных.
∙
Использовать фреймворк Semantic UI с расчетом на написание удобочитаемого программного кода;
∙
Созданные элементы интерфейса на Semantic UI не должны противоречить принципам создания интерфейса на Django.
16
Глава II Разработка приложения
§2.1 Модель
Поскольку основным инструментом для создания приложения является фреймворк Django, то для хранения информации необходимо использовать модели. Модель – важнейшая часть приложения, которое постоянно
обращается к данным при любом запросе из любой сессии. Она содержит
поля и методы для работы с данными, которые необходимо хранить. Любая
модель в Django является стандартным Python классом [12].
Все данные хранятся в нескольких таблицах. Эти таблицы заданы
с помощью Объектно-Реляционного Отображения (ORM) в виде Djangoмоделей.
Так, каждый студент, зарегистрированный в системе, может добавить
в систему достижение, полученное им в процессе учебной деятельности. Затем на основе этих достижений у пользователя будет возможность сформировать заявку для получения повышенной стипендии. Во время приема
заявок студент может подать свою заявку или заявки на рассмотрение. В
свою очередь ответственный за проверку заявок может, как одобрить, так и
отклонить заявку, для ее исправления. Каждый вид деятельности содержит
в себе определенные аспекты, которые необходимо учитывать при формировании заявки.
Так как для подачи заявки необходимо быть пользователем системы
была создана таблица student, в которой хранится информация о студентах. Для того чтобы отделить преподавателей и студентов таблица student
связана с таблицей auth_user которая содержит информацию для входа в
систему. Чтобы создавать заявки была добавлена таблица application в которой хранится информация о заявке. Заявка должна относиться к одному
из видов деятельность, и содержать в себе только те достижения, которые
17
Рис. 1: Схема базы данных.
относятся к указанному в заявке. Для хранения видов деятельности создана таблица activitytype. К каждой заявке необходимо прикреплять достижения, информация о которых хранится в таблице achievement. Так же для
достижения необходимо указать его тип, информация о типах достижений
хранится в таблице achievementtype. Для достижение нужны подтверждающие их документы они хранятся в таблице scan. Все необходимые данные
18
для максимальной автоматизации процесса подачи заявок на повышенную
стипендию хранятся в представленных на рисунке 1 таблицах.
1
# −*− coding : utf −8 −*−
2
3
from django . c o n t r i b . auth . models import User
4
from django . db import models
5
import d a t e t i m e
6
7
8
9
def y e a r _ c h o i c e s ( ) :
return [ ( r , r ) for r in range ( d a t e t i m e . d a t e . today ( ) . year − 4, d a t e t i m e . d a t e .
today ( ) . y e a r +2) ]
10
11
12
13
def c u r r e n t _ y e a r ( ) :
return d a t e t i m e . d a t e . today ( ) . y e a r
14
15
16
c l a s s Student ( models . Model ) :
17
owner = models . OneToOneField ( User , o n _ d e l e t e=models .CASCADE)
18
f i r s t _ n a m e = models . C h a r F i e l d ( " s t u d e n t ␣ f i r s t ␣name" , max_length =100 ,
19
20
n u l l=F a l s e , blank=F a l s e )
last_name = models . C h a r F i e l d ( " s t u d e n t ␣ l a s t ␣name" , max_length =100 ,
21
n u l l=F a l s e , blank=F a l s e )
22
23
24
def __unicode__ ( s e l f ) :
return u ’%s ␣%s ’ % ( s e l f . last_name , s e l f . f i r s t _ n a m e )
Листинг 1: Таблицы, содержащие информацию о студентах.
1
# −*− coding : utf −8 −*−
2
3
import d a t e t i m e
4
from django . c o n f import s e t t i n g s
5
from django . c o n t r i b . auth . models import User
6
from django . db import models
7
from django . t e m p l a t e . l o a d e r import r e n d e r _ t o _ s t r i n g
8
from r e g i s t r a t i o n . models import R e g i s t r a t i o n M a n a g e r
9
from django . u t i l s . t r a n s l a t i o n import u g e t t e x t _ l a z y a s _
10
19
11
12
13
14
try :
from django . u t i l s . t i m e z o n e import now a s datetime_now
except I m p o r t E r r o r :
datetime_now = d a t e t i m e . d a t e t i m e . now
15
16
17
18
c l a s s S t u d e n t R e g i s t r a t i o n P r o f i l e ( models . Model ) :
ACTIVATED = u"ALREADY_ACTIVATED"
19
20
u s e r = models . ForeignKey ( User , unique=True , verbose_name=_( ’ u s e r ’ ) )
21
a c t i v a t i o n _ k e y = models . C h a r F i e l d (_( ’ a c t i v a t i o n ␣ key ’ ) , max_length =40)
22
23
o b j e c t s = RegistrationManager ()
24
25
26
def s e n d _ a c t i v a t i o n _ e m a i l ( s e l f , s i t e ) :
ctx_dict = { ’ activation_key ’ : s e l f . activation_key ,
27
’ e x p i r a t i o n _ d a y s ’ : s e t t i n g s .ACCOUNT_ACTIVATION_DAYS,
28
’ site ’ : site}
29
s u b j e c t = r e n d e r _ t o _ s t r i n g ( ’ student_auth / a c t i v a t i o n _ e m a i l _ s u b j e c t . t x t ’ ,
30
31
ctx_dict )
subject = ’ ’ . join ( subject . s p l i t l i n e s () )
32
33
message = r e n d e r _ t o _ s t r i n g ( ’ student_auth / a c t i v a t i o n _ e m a i l . t x t ’ ,
34
ctx_dict )
35
36
s e l f . u s e r . e m a i l _ u s e r ( s u b j e c t , message , s e t t i n g s .DEFAULT_FROM_EMAIL)
37
38
c l a s s Meta :
39
verbose_name = _( ’ r e g i s t r a t i o n ␣ p r o f i l e ’ )
40
verbose_name_plural = _( ’ r e g i s t r a t i o n ␣ p r o f i l e s ’ )
41
db_table = ’ r e g i s t r a t i o n _ r e g i s t r a t i o n p r o f i l e ’
42
43
44
def __unicode__ ( s e l f ) :
return u" R e g i s t r a t i o n ␣ i n f o r m a t i o n ␣ f o r ␣%s " % s e l f . u s e r
45
46
47
def a c t i v a t i o n _ k e y _ e x p i r e d ( s e l f ) :
e x p i r a t i o n _ d a t e = d a t e t i m e . t i m e d e l t a ( days=s e t t i n g s .
ACCOUNT_ACTIVATION_DAYS)
48
49
return s e l f . a c t i v a t i o n _ k e y == s e l f .ACTIVATED or \
( s e l f . u s e r . d a t e _ j o i n e d + e x p i r a t i o n _ d a t e <= datetime_now ( ) )
20
50
a c t i v a t i o n _ k e y _ e x p i r e d . b o o l e a n = True
Листинг 2: Таблицы, содержащие информацию о регистрации студентов в
системе.
1
# −*− coding : utf −8 −*−
2
3
from django . db import models
4
5
from s t u d e n t . models import Student
6
7
8
9
c l a s s Event ( models . Model ) :
y e a r = models . I n t e g e r F i e l d ( )
10
begin_date = models . D a t e F i e l d ( )
11
end_date = models . D a t e F i e l d ( )
12
s t a t u s = models . C h a r F i e l d ( " e v e n t ␣ s t a t u s " , max_length =50 , n u l l=F a l s e ,
13
blank=F a l s e )
14
15
16
17
c l a s s A c t i v i t y T y p e ( models . Model ) :
name = models . C h a r F i e l d ( "name␣ o f ␣ a c t i v i t y ␣ type " , max_length =50 ,
18
n u l l=F a l s e , blank=F a l s e )
19
20
21
def __unicode__ ( s e l f ) :
return s e l f . name
22
23
24
25
c l a s s AchievementType ( models . Model ) :
name = models . C h a r F i e l d ( "name␣ o f ␣ achievement ␣ type " , max_length =50 ,
26
27
n u l l=F a l s e , blank=F a l s e )
a c t i v i t y _ t y p e = models . ForeignKey ( A c t i v i t y T y p e )
28
29
30
def __unicode__ ( s e l f ) :
return s e l f . name
31
32
33
c l a s s Achievement ( models . Model ) :
34
a c t i v i t y _ t y p e = models . ForeignKey ( A c t i v i t y T y p e )
35
achievement_type = models . ForeignKey ( AchievementType )
36
s t u d e n t = models . ForeignKey ( Student )
21
37
obtain_date = models . D a t e F i e l d ( )
38
39
40
def __unicode__ ( s e l f ) :
return s e l f . achievement_type . name
41
42
43
c l a s s A p p l i c a t i o n ( models . Model ) :
44
a c t i v i t y _ t y p e = models . ForeignKey ( A c t i v i t y T y p e )
45
e v e n t = models . ForeignKey ( Event , n u l l=True , blank=True )
46
a c h i e v e m e n t s = models . ManyToManyField ( Achievement )
47
s t u d e n t = models . ForeignKey ( Student , n u l l=True , blank=True )
48
s t a t u s = models . C h a r F i e l d ( " a p p l i c a t i o n ␣ s t a t u s " , max_length =50 , n u l l=True ,
49
blank=True )
50
f e e d b a c k = models . T e x t F i e l d ( " a p p l i c a t i o n ␣ f e e d b a c k " , n u l l=True , blank=True )
51
s e n d _ s t a t u s = models . I n t e g e r F i e l d ( d e f a u l t =0)
52
53
54
c l a s s Scan ( models . Model ) :
55
achievement = models . ForeignKey ( Achievement )
56
f i l e n a m e = models . F i l e F i e l d ( upload_to= ’ . / s c a n / s t u d e n t ’ , blank=True )
Листинг 3: Таблицы, содержащие информацию о повышенной стипендии,
представленные в виде моделей.
22
§2.2 Аутентификация
Веб-фреймворк django предоставляет систему аутентификации и авторизации ("permission") пользователя, реализованную на основе фреймворка
работы с сессиями. Система аутентификации и авторизации позволяет проверять полномочия пользователей и определять какие кому соответствуют.
Данный фреймворк включает в себя встроенные модели для Пользователей и Групп (основной способ применения авторизации для более чем одного пользователя), непосредственно саму систему разграничения доступа
(permissions)/флаги, которые определяют какую задачу, с какой формой и
отображением, инструментом отображения, может работать тот, или иной
пользователь [13].
Для того, чтобы студенты Орловского Государственного Университета
им. И.С. Тургенева могли подавать заявки на повышенную государственную
стипендию им необходимо иметь аккаунт в системе НИР.
Методы авторизации и аутентификации применяемые в приложении
разработаны и используются, в основном, для авторизации и регистрации
исключительно преподавателей и сотрудников вуза, поскольку изначально
система не предполагала иметь функционал для взаимодействия со студентами. Расширение существующей системы авторизации, для того, чтобы студенты могли регистрироваться в системе, повлекло бы за собой значительные изменения в функционале и интерфейсе системы, а так же создало бы
путаницу в базе данных, поскольку и студент и сотрудник вуза имели бы
одинаковый набор персональных данных. Таким образом существующая в
приложении система аутентификации является не пригодной для авторизации студентов.
Использовать существующую в приложении аутентификацию для студентов является невозможным, поскольку это может нарушать права доступа в приложении. Таким образом необходимо разработать отдельный модуль
23
Рис. 2: Страница авторизации для преподавателей и сотрудников вуза
для регистрации и авторизации студентов, для того, чтобы они самостоятельно могли выполнять вышеописанные действия, при этом не затрагивая
функционал доступный преподавателям и сотрудникам вуза.
24
§2.3 Регистрация студентов
Система аутентификации, входящая в состав Django, отлично подходит для решения многих типичных задач, однако для реализации алгоритма
регистрации студентов её функциональности, предоставляемой “из коробки” не хватает. Таким образом необходимо полностью заменить стандартную модель User используемую для регистрации пользователей фреймворком Django и реализовать собственный механизм регистрации студентов.
Для того, чтобы студент мог воспользоваться системой и ее возможностями, для начала, ему необходимо зарегестрироваться.
По адресу
/accounts/student/register находится страница регистра-
ции студетов.
Рис. 3: Страница регистрации студентов.
Данная страница практически полностью повторяет страницу регистрации преподавателей, за исключением механизма создания учетной записи.
25
Класс StudentRegistrationView отвечает за рендеринг шаблона регистрации для студентов, а так же обрабатывает данные, приходящие с формы регистрации. Как только студент заполнит требуемые поля и нажмет
кнопку "Зарегистрироваться данные с формы будут переданы на сервер, и
их обработает метод register.
1
from django . c o n t r i b . auth import REDIRECT_FIELD_NAME, l o g i n a s a u t h _ l o g i n
2
from django . c o n t r i b . s i t e s . models import R e q u e s t S i t e
3
from django . c o n t r i b . s i t e s . models import S i t e
4
from django . c o n t r i b . s i t e s . models import g e t _ c u r r e n t _ s i t e
5
from django . h t t p import H t t p R e s p o n s e R e d i r e c t
6
from django . s h o r t c u t s import r e s o l v e _ u r l
7
from django . t e m p l a t e . r e s p o n s e import TemplateResponse
8
from django . u t i l s . h t t p import i s _ s a f e _ u r l
9
from django . v i e w s . d e c o r a t o r s . c a c h e import never_cache
10
from django . v i e w s . d e c o r a t o r s . c s r f import c s r f _ p r o t e c t
11
from django . v i e w s . d e c o r a t o r s . debug import s e n s i t i v e _ p o s t _ p a r a m e t e r s
12
from r e g i s t r a t i o n . backends . d e f a u l t . v i e w s import R e g i s t r a t i o n V i e w ,
ActivationView
13
14
from student_auth import s i g n a l s
15
from student_auth . models import S t u d e n t R e g i s t r a t i o n P r o f i l e
16
from student_auth . forms import S t ud e n tA u t h en t i ca t i on F o rm
17
18 LOGIN_REDIRECT_URL = ’ / s t u d e n t ’
19
20
21
class StudentRegistrationView ( RegistrationView ) :
22
def r e g i s t e r ( s e l f , r e q u e s t , ** cleaned_data ) :
23
username , email , password = cleaned_data [ ’ username ’ ] , cleaned_data [ ’
e m a i l ’ ] , cleaned_data [ ’ password1 ’ ]
24
25
26
27
28
29
30
i f S i t e . _meta . i n s t a l l e d :
s i t e = S i t e . o b j e c t s . get_current ()
else :
s i t e = RequestSite ( request )
new_user = S t u d e n t R e g i s t r a t i o n P r o f i l e . o b j e c t s . c r e a t e _ i n a c t i v e _ u s e r (
username , email , password , s i t e )
s i g n a l s . s t u d e n t _ r e g i s t e r e d . send_robust ( s e n d e r= s e l f . __class__ ,
31
u s e r=new_user ,
32
r e q u e s t=r e q u e s t )
26
33
return new_user
34
35
36
def g e t _ s u c c e s s _ u r l ( s e l f , r e q u e s t , u s e r ) :
return ( ’ s t u d e n t _ r e g i s t r a t i o n _ c o m p l e t e ’ , ( ) , { } )
Листинг 4: метод register.
Функция получает с шаблона такие данные как: имя пользователя, его
электронный почтовый адресс и пароль, затем создает новый не активный
профиль студента, и в случае успешного создания профиля, отправляется
сигнал student_registered, который в свою очередь обрабатывает обработчик
student_registered_handler.
1
from django . d i s p a t c h import S i g n a l
2
3
4
# A new student has registered .
5
s t u d e n t _ r e g i s t e r e d = S i g n a l ( p r o v i d i n g _ a r g s =[" u s e r " , " r e q u e s t " ] )
Листинг 5: событие регистрации студента.
Данный метод просто регистрирует сигнал в системе стандартными
средствами фрейворка django.
1
from django . d i s p a t c h import r e c e i v e r
2
from student_auth . s i g n a l s import s t u d e n t _ r e g i s t e r e d
3
from s t u d e n t . models import Student
4
5
6
@receiver ( student_registered )
7
def s t u d e n t _ r e g i s t e r e d _ h a n d l e r ( s e n d e r , u s e r , r e q u e s t , ** kwargs ) :
8
p r o f i l e = Student ( owner=u s e r )
9
p r o f i l e . middle_name = r e q u e s t .POST[ ’ middle_name ’ ]
10
p r o f i l e . f i r s t _ n a m e = r e q u e s t .POST[ ’ f i r s t _ n a m e ’ ]
11
p r o f i l e . last_name = r e q u e s t .POST[ ’ last_name ’ ]
12
p r o f i l e . save ( )
Листинг 6: обработчик события student_registered.
Данный обработчик при срабатывании события student_registered создает запись в базе данных с персональными данными студента, а так же
27
связывает данную запись с профилем студента.
После обработки данных, сервер перенаправляет пользователя на
страницу
/accounts/student/register/complete.
Страница представляет
собой простой шаблон и информирует пользователя о необходимости активации аккаунта, путем перехода по ссылке, содержащейся в письме, отправленном на почту.
Рис. 4: Страница успешной регистрации.
За перенаправление пользователя на конкретную страницу отвечает
метод get_success_url.
1
2
def g e t _ s u c c e s s _ u r l ( s e l f , r e q u e s t , u s e r ) :
return ( ’ s t u d e n t _ r e g i s t r a t i o n _ c o m p l e t e ’ , ( ) , { } )
Листинг 7: метод перенаправления пользователя.
Пользователю на почту, указанную при регистрации, отправляется
письмо, содержащее информацию о том, как активировать аккаут. Активация аккаунта происходит переходом по ссылке в письме. Перейдя по ссыл28
ке, аккаунт студента считается активным. Пользователя перенаправляет на
страницу успешной активации аккаунта.
Рис. 5: Страница успешной активации аккаунта.
За перенаправление на страницу успешной активации аккаунта студента отвечает метод StudentActivationView.
1
2
3
class StudentActivationView ( ActivationView ) :
def g e t _ s u c c e s s _ u r l ( s e l f , r e q u e s t , u s e r ) :
return ( ’ s t u d e n t _ r e g i s t r a t i o n _ a c t i v a t i o n _ c o m p l e t e ’ , ( ) , { } )
Листинг 8: метод успешной активации аккаунта.
Данные метод по ключу активации, отправленному в письме ищет
пользователя в базе данных и активирует его аккаунт. Затем, в случае успеха, перенаправляет пользователя на страницу с информацией об успешной
активации аккаунта и о возможности войти в систему.
29
§2.4 Авторизация студентов
Фреймворк django предоставляет возможности авторизации и аутентификации пользователей, обычно этот механизм называют системой аутентификации, т.к. эти функции связаны [14].
После того, как студент прошел регистрацию и успешно активировал свой аккаунт, ему необходимо авторизоваться в системе. По адресу
/accounts/student/register
находится страница авторизации для студен-
тов.
Рис. 6: Страница авторизации студентов.
На данной странице пользователь может зарегистрироваться как студет, восстановить пароль в случае его потери, а так же авторизоваться.
За проверку подлинности логина и пароля отвечает следующий метод:
30
1
@sensitive_post_parameters ( )
2
@csrf_protect
3
@never_cache
4
def l o g i n ( r e q u e s t , template_name= ’ student_auth / l o g i n . html ’ ,
5
r e d i r e c t _ f i e l d _ n a m e=REDIRECT_FIELD_NAME,
6
a u t h e n t i c a t i o n _ f o r m=StudentAuthenticationForm ,
7
current_app=None , e x t r a _ c o n t e x t=None ) :
8
r e d i r e c t _ t o = r e q u e s t .REQUEST. g e t ( r e d i r e c t _ f i e l d _ n a m e , ’ ’ )
9
10
i f r e q u e s t . method == "POST" :
11
form = a u t h e n t i c a t i o n _ f o r m ( r e q u e s t , data=r e q u e s t .POST)
12
i f form . i s _ v a l i d ( ) :
13
i f not i s _ s a f e _ u r l ( u r l=r e d i r e c t _ t o , h o s t=r e q u e s t . get_host ( ) ) :
14
15
r e d i r e c t _ t o = r e s o l v e _ u r l (LOGIN_REDIRECT_URL)
16
17
a u t h _ l o g i n ( r e q u e s t , form . g e t _ u s e r ( ) )
18
return H t t p R e s p o n s e R e d i r e c t ( r e d i r e c t _ t o )
19
20
else :
21
form = a u t h e n t i c a t i o n _ f o r m ( r e q u e s t )
22
23
current_site = get_current_site ( request )
24
25
context = {
26
’ form ’ : form ,
27
redirect_field_name : redirect_to ,
28
’ s i t e ’ : current_site ,
29
’ site_name ’ : c u r r e n t _ s i t e . name ,
30
}
31
i f e x t r a _ c o n t e x t i s not None :
32
33
34
c o n t e x t . update ( e x t r a _ c o n t e x t )
return TemplateResponse ( r e q u e s t , template_name , c o n t e x t ,
current_app=current_app )
Листинг 9: метод авторизации студентов.
Данный метод, в случае приема данных от клиента, ищет по указанным пользователем логину и паролю запись в базе данных. Если учетная
запись найдена, и она является записью студента, сервер авторизует поль31
зователя. Так же если в параметрах запроса указана страница перенаправления, то сервер перенаправит авторизованного пользователя на указанную
страницу. В случае отсутствия записи, сервер вернет ошибку о неправильно
введенном логине или пароле.
Введя корректные логин и пароль, студент попадает на "домашнюю"страницу студента. Cтраница информирует пользователя о его воз-
Рис. 7: Домашняя страница студента.
можностях в сервисе: редактирование профиля, управление учебными достижениями, а так же подача заявки на повышенную стипендию.
За отображение данной страницы отвечает следующий класс:
1
c l a s s StudentIndexView ( LoginRequiredMixin , EventStatusMixin , StudentAccessMixin
, TemplateView ) :
2
template_name = ’ s t u d e n t / i n d e x . html ’
3
32
4
5
def get_context_data ( s e l f , * a r g s , ** kwargs ) :
c o n t e x t = super ( StudentIndexView , s e l f ) . get_context_data ( * a r g s , **
kwargs )
6
u s e r _ i d = s e l f . r e q u e s t . u s e r . pk
7
c o n t e x t [ ’ u s e r ’ ] = User . o b j e c t s . g e t ( id=u s e r _ i d )
8
c o n t e x t [ ’ template_main ’ ] = ’ a c t i v e ’
9
return c o n t e x t
Листинг 10: класс для отображения домашней страницы студента.
Данный класс устнавливает флаг активности главной страницы для
навигации, а так же получает информацию о текущем пользователе, затем
находит запись в базе данных о нем, и отправляет эти данные на шаблон
для отображения страницы.
33
§2.5 Достижения студентов
Каждый студент, зарегестрированный в системе может добавить одно
или несколько достижений, полученных в процессе обучения в соответствии
с действующим регламентом.
Перейдя по адресу
/studentship/achievements/ студент попадает на
страницу с информацией о его достижениях.
Рис. 8: Страница, для заполнения данными.
Данный шаблон представляет собой пользовательский интерфейс, на
котором пользователь может добавлять, редактировать, удалять информацию о личных достижениях по каждому виду деятельности: учебному,
научно-исследовательскому, общественному, культурно-творческому, а так
же спортивному.
Как только пользователь отправит запрос по указанному выше адресу, этот запрос обработает специальный класс, который отправит клиенту
необходимый шаблон для отображения в браузере.
34
1
c l a s s A c h i e v e m e n t L i s t ( LoginRequiredMixin , StudentAccessMixin , L i s t V i e w ) :
2
paginate_by = 5
3
model = Achievement
4
5
6
def get_context_data ( s e l f , * a r g s , ** kwargs ) :
c o n t e x t = super ( AchievementList , s e l f ) . get_context_data ( * a r g s , ** kwargs
)
7
c o n t e x t [ ’ template_achievements ’ ] = ’ a c t i v e ’
8
return c o n t e x t
Листинг 11: Класс, отвечающий за загрузку информации о достижениях.
Этот класс на основе текущего пользователя собирает из базы данных
его достижения, ранее добавленные им. Затем эти достижения отобразятся
в виде списка на странице по пять штук. Если данные в базе данных отсутствуют, пользователь получит соответствующее сообщение и предложение
добавить новое достижение.
Рис. 9: Форма добавления нового достижения.
1
c l a s s AchievementCreate ( LoginRequiredMixin , StudentAccessMixin , CreateView ) :
2
f o r m _ c l a s s = AchievementCreateForm
3
template_name = ’ s t u d e n t s h i p / achievement_form . html ’
4
35
5
6
def get_context_data ( s e l f , * a r g s , ** kwargs ) :
c o n t e x t = super ( AchievementCreate , s e l f ) . get_context_data ( * a r g s , **
kwargs )
7
c o n t e x t [ ’ template_achievements ’ ] = ’ a c t i v e ’
8
return c o n t e x t
9
10
def form_valid ( s e l f , form ) :
11
form . i n s t a n c e . s t u d e n t = s e l f . r e q u e s t . u s e r . s t u d e n t
12
super ( AchievementCreate , s e l f ) . form_valid ( form )
13
form . i n s t a n c e . s c a n _ s e t . c r e a t e ( f i l e n a m e=form . cleaned_data [ ’ s c a n ’ ] )
14
return super ( AchievementCreate , s e l f ) . form_valid ( form )
15
16
17
def g e t _ s u c c e s s _ u r l ( s e l f ) :
return r e v e r s e _ l a z y ( ’ a c h i e v e m e n t _ l i s t ’ )
Листинг 12: Метод создания нового достижения.
Данный метод определяет шаблон для рендеринга, затем устанавливает в меню навигации активной вкладку "Достижения"и при сохранении нового достижения сохраняет информацию о подтверждающем документе в базу данных. В качестве обработчика данных используется класс
AchievementCreateForm.
1
2
c l a s s AchievementCreateForm ( forms . ModelForm ) :
s c a n = forms . F i l e F i e l d ( w i d g e t=forms . F i l e I n p u t ( a t t r s ={ ’ a c c e p t ’ : ’ a p p l i c a t i o n
/ pdf ’ } ) )
3
activity_types = [ ]
4
for a c t i v i t y _ t y p e in A c t i v i t y T y p e . o b j e c t s . a l l ( ) . p r e f e t c h _ r e l a t e d ( ’
achievementtype_set ’ ) :
5
a c t i v i t y _ t y p e s . append (
6
{
7
’ i d ’ : a c t i v i t y _ t y p e . id ,
8
’ name ’ : a c t i v i t y _ t y p e . name ,
9
’ achievement_types ’ : [
10
{ ’ i d ’ : achievement_type . id , ’ name ’ : achievement_type . name}
11
for achievement_type in a c t i v i t y _ t y p e . a c h i e v e m e n t t y p e _ s e t .
all ()
12
]
13
14
}
)
36
15
a c t i v i t y _ t y p e s = j s o n . dumps ( a c t i v i t y _ t y p e s )
16
17
c l a s s Meta :
18
model = Achievement
19
fields = [
20
’ activity_type ’ ,
21
’ achievement_type ’ ,
22
’ obtain_date ’ ,
23
’ scan ’
24
]
Листинг 13: Класс AchievementCreateForm для генерации страницы
создания достижения.
Данный класс устанавливает для подтверждающего документа разрешенное расширение файла - pdf. Затем, для корректного отображения страницы, группирует типы достижений по видам деятельности, для того, чтобы
пользователь по ошибке не указал неверные данные, а так же определяет
обязательные поля для заполнения для создания нового достижения в системе. После создания очередного достижения, студента перенаправляет на
страницу со списком достижений.
Рис. 10: Страница с данными.
37
Каждое достижение имеет следующие поля: вид деятельности, тип достижения, дата получения, а так же подтверждающий документ. Так же
пользователю доступны действия редактирования достижения и его удаление, а так же добавление нового достижения.
В случае необходимости внесения изменений в уже существующее достижение, пользователю нужно нажать кнопку ‘редактировать‘. По нажатию данной кнопки, сервер загрузит страницу редактирования выбранного
достижения.
Рис. 11: Страница редактирования достижения.
за отображения данной страницы отвечает следующий класс:
1
c l a s s AchievementUpdate ( LoginRequiredMixin , StudentAccessMixin , UpdateView ) :
2
model = Achievement
3
f o r m _ c l a s s = AchievementUpdateForm
4
template_name = ’ s t u d e n t s h i p / achievement_form . html ’
5
6
def get_context_data ( s e l f , ** kwargs ) :
7
c o n t e x t = super ( AchievementUpdate , s e l f ) . get_context_data ( * * kwargs )
8
c o n t e x t [ ’ uploaded_scan ’ ] = Scan . o b j e c t s . f i l t e r ( achievement= s e l f . kwargs [
’ pk ’ ] ) . l a s t ( )
9
c o n t e x t [ ’ template_achievements ’ ] = ’ a c t i v e ’
38
10
return c o n t e x t
11
12
def form_valid ( s e l f , form ) :
13
form . i n s t a n c e . s t u d e n t = s e l f . r e q u e s t . u s e r . s t u d e n t
14
super ( AchievementUpdate , s e l f ) . form_valid ( form )
15
i f form . cleaned_data [ ’ s c a n ’ ] :
16
17
form . i n s t a n c e . s c a n _ s e t . update ( f i l e n a m e=form . cleaned_data [ ’ s c a n ’ ] )
return super ( AchievementUpdate , s e l f ) . form_valid ( form )
18
19
20
def g e t _ s u c c e s s _ u r l ( s e l f ) :
return r e v e r s e _ l a z y ( ’ a c h i e v e m e n t _ l i s t ’ )
Листинг 14: Класс редактирования достижения.
Данный класс собирает необходимые для отображения на странице
данные, определяет ранее загруженный подтверждающий документ и затем
передает эти данные на шаблон. Затем при обновлении достижения, в случае изменения подтверждающего файла, поизойдет замена соответствующей
информации в базе данных.
Класс AchievementUpdate в своей основе использует класс формы
AchievementUpdateForm который в свою очередь определяет требуемы для
редактирования поля и заполняет их данными из базы данных.
1
c l a s s AchievementUpdateForm ( forms . ModelForm ) :
2
s c a n = forms . F i l e F i e l d ( r e q u i r e d=F a l s e )
3
activity_types = [ ]
4
for a c t i v i t y _ t y p e in A c t i v i t y T y p e . o b j e c t s . a l l ( ) . p r e f e t c h _ r e l a t e d ( ’
achievementtype_set ’ ) :
5
a c t i v i t y _ t y p e s . append (
6
{
7
’ i d ’ : a c t i v i t y _ t y p e . id ,
8
’ name ’ : a c t i v i t y _ t y p e . name ,
9
’ achievement_types ’ : [
10
{ ’ i d ’ : achievement_type . id , ’ name ’ : achievement_type . name}
11
for achievement_type in a c t i v i t y _ t y p e . a c h i e v e m e n t t y p e _ s e t .
all ()
12
]
13
14
}
)
39
15
a c t i v i t y _ t y p e s = j s o n . dumps ( a c t i v i t y _ t y p e s )
16
17
c l a s s Meta :
18
model = Achievement
19
fields = [
20
’ activity_type ’ ,
21
’ achievement_type ’ ,
22
’ obtain_date ’ ,
23
’ scan ’
24
]
Листинг 15: Класс формы редактирования достижения.
Данный класс определяет список видо деятельности, и по ним группирует типы достижений, передавая эти данные на шаблон.
В случае необходимости удаления достижения, необходимо на сервер
отправить запрос на удаление выбранного достижения. За обработку такого
запроса отвечает класс AchievementDelete.
1
c l a s s AchievementDelete ( LoginRequiredMixin , StudentAccessMixin , DeleteView ) :
2
model = Achievement
3
success_url = reverse_lazy ( ’ achievement_list ’ )
4
5
6
def get_context_data ( s e l f , * a r g s , ** kwargs ) :
c o n t e x t = super ( AchievementDelete , s e l f ) . get_context_data ( * a r g s , **
kwargs )
7
c o n t e x t [ ’ template_achievements ’ ] = ’ a c t i v e ’
8
return c o n t e x t
Листинг 16: Класс удаления достижения.
Данный класс определяет страницу в случае успешного удаления достижения, а так же проверяет наличие записи о достижении в базе данных
и в случае успеха удаляет найденную информацию.
40
§2.6 Регистрация заявок на повышенную стипендию
Каждый студент, обучающийся в Орловском государственном университете им. И.С. Тургенева, успешно сдавший сессию, и имеющий хотя бы
одно достижение, в течении двух последних семестров, может претендовать
на повышенную государственную академическую стипендию.
Для того, чтобы подать заявку на повышенную стипендию, достаточно
иметь в системе хотя бы одно зарегестрированное достижение, а так же
удовлетворять условиям, описанным выше.
Так, для подачи заявки на повышенную стипендию через систему необходимо перейти по адресу
/studentship/applications/.
Данная страница
содержит информацию о текущих поданных заявках, а так же отображает
историю ранее поданных заявок.
Рис. 12: Страница заявок.
За отображение данной страницы отвечает следующий класс:
41
1
c l a s s A p p l i c a t i o n L i s t ( LoginRequiredMixin , EventStatusMixin , StudentAccessMixin ,
ListView ) :
2
paginate_by = 8
3
model = A p p l i c a t i o n
4
5
6
def get_context_data ( s e l f , * a r g s , ** kwargs ) :
c o n t e x t = super ( A p p l i c a t i o n L i s t , s e l f ) . get_context_data ( * a r g s , ** kwargs
)
7
context [ ’ template_studentship ’ ] = ’ a c t i v e ’
8
return c o n t e x t
Листинг 17: Класс загрузки списка заявок.
Для того, чтобы создать новую заявку, пользователю достаточно отправить запрос по адресу
/studentship/applications/new/. Обратившись
по данному адресу сервер загружает шаблон для создания новой заявки.
Рис. 13: Страница создания заявки.
За отображение данного шаблона, а так же за сохранение данных с
42
формы отвечает следующий класс:
1
c l a s s A p p l i c a t i o n C r e a t e ( LoginRequiredMixin , StudentAccessMixin , CreateView ) :
2
form_class = ApplicationCreateForm
3
template_name = ’ s t u d e n t s h i p / a p p l i c a t i o n _ f o r m . html ’
4
5
6
def get_context_data ( s e l f , * a r g s , ** kwargs ) :
c o n t e x t = super ( A p p l i c a t i o n C r e a t e , s e l f ) . get_context_data ( * a r g s , **
kwargs )
7
context [ ’ template_studentship ’ ] = ’ a c t i v e ’
8
return c o n t e x t
9
10
def get_form_kwargs ( s e l f ) :
11
kwargs = super ( A p p l i c a t i o n C r e a t e , s e l f ) . get_form_kwargs ( )
12
kwargs [ ’ u s e r ’ ] = s e l f . r e q u e s t . u s e r
13
return kwargs
14
15
def form_valid ( s e l f , form ) :
16
form . i n s t a n c e . s t u d e n t = s e l f . r e q u e s t . u s e r . s t u d e n t
17
form . i n s t a n c e . s t a t u s = ’ none_status ’
18
return super ( A p p l i c a t i o n C r e a t e , s e l f ) . form_valid ( form )
19
20
21
def g e t _ s u c c e s s _ u r l ( s e l f ) :
return r e v e r s e _ l a z y ( ’ a p p l i c a t i o n _ l i s t ’ )
Листинг 18: Класс создания новой заявки.
Класс определяет шаблон для загрузки, затем, при формировании
страницы, устанавливает флаг активной вкладки управления заявками для
навигационного меню, опеделяет текущего пользователя системы и передает
эти данные на шаблон. При отправке данных с клиента, данный класс устанавливает для заявки статус по умолчанию - "не отслеживается поскольку
заявка еще не отправлена на рассмотрение.
Так же, данный класс для генерации страницы создания новой заявки
использует другой класс ApplicationCreateForm.
1
2
3
c l a s s A p p l i c a t i o n C r e a t e F o r m ( forms . ModelForm ) :
def __init__ ( s e l f , * a r g s , ** kwargs ) :
a c t i v i t y _ t y p e s = s e l f . g e t _ a c t i v i t y _ t y p e s ( kwargs . pop ( ’ u s e r ’ , None ) .
student )
43
4
s e l f . a c t i v i t y _ t y p e s = j s o n . dumps ( a c t i v i t y _ t y p e s )
5
super ( ApplicationCreateForm , s e l f ) . __init__ ( * a r g s , ** kwargs )
6
7
def g e t _ a c t i v i t y _ t y p e s ( s e l f , s t u d e n t ) :
8
activity_types = [ ]
9
t y p e s = A c t i v i t y T y p e . o b j e c t s . f i l t e r ( achievement__student=s t u d e n t . id ) .
distinct ()
for type in t y p e s :
10
11
a c t i v i t y _ t y p e s . append (
12
{
13
’ i d ’ : type . id ,
14
’ name ’ : type . name ,
15
’ achievements ’ : [
16
{ ’ i d ’ : achievement . id , ’ name ’ : unicode ( achievement ) }
17
for achievement in type . achievement_set . f i l t e r ( s t u d e n t=
s t u d e n t . id )
18
]
19
}
20
)
return a c t i v i t y _ t y p e s
21
22
c l a s s Meta :
23
24
model = A p p l i c a t i o n
25
fields = [
26
’ activity_type ’ ,
27
’ event ’ ,
28
’ student ’ ,
29
’ status ’ ,
30
’ feedback ’ ,
31
’ achievements ’
32
]
Листинг 19: Класс обрабокти данных для создания новой заявки.
Данный класс устанавливает необходимые поля для заполнения, а так
же группирует достижения студента по типам деятельности.
В
ную
случае
заявку,
необходимости
пользователю
внесения
достаточно
изменений
отправить
уже
запрос
/studentship/applications/update/<application_id>
44
в
по
созданадресу
для редактиро-
вания указанной заявки. При получении данного запроса, сервер загрузит
страницу редактирования выбранной заявки.
Рис. 14: Страница редактирования заявки.
за отображения данной страницы отвечает следующий класс:
1
c l a s s A p p l i c a t i o n U p d a t e ( LoginRequiredMixin , StudentAccessMixin , UpdateView ) :
2
f o r m _ c l a s s = ApplicationUpdateForm
3
model = A p p l i c a t i o n
4
template_name = ’ s t u d e n t s h i p / a p p l i c a t i o n _ f o r m . html ’
5
6
7
def get_context_data ( s e l f , * a r g s , ** kwargs ) :
c o n t e x t = super ( A p p l i c a t i o n U p d a t e , s e l f ) . get_context_data ( * a r g s , **
kwargs )
8
context [ ’ template_studentship ’ ] = ’ a c t i v e ’
9
return c o n t e x t
10
11
def get_form_kwargs ( s e l f ) :
12
kwargs = super ( A p p l i c a t i o n U p d a t e , s e l f ) . get_form_kwargs ( )
13
kwargs [ ’ u s e r ’ ] = s e l f . r e q u e s t . u s e r
45
14
return kwargs
15
16
def form_valid ( s e l f , form ) :
17
form . i n s t a n c e . s t u d e n t = s e l f . r e q u e s t . u s e r . s t u d e n t
18
form . i n s t a n c e . s t a t u s = ’ none_status ’
19
return super ( A p p l i c a t i o n U p d a t e , s e l f ) . form_valid ( form )
20
21
22
def g e t _ s u c c e s s _ u r l ( s e l f ) :
return r e v e r s e _ l a z y ( ’ a p p l i c a t i o n _ l i s t ’ )
Листинг 20: Класс редактирования заявки.
Данный класс определяет шаблон для генерации пользователю, и загружает необходимые для отображения шаблона данные. В своей основе
данный класс использует класс формы ApplicationUpdateForm.
1
2
3
c l a s s ApplicationUpdateForm ( forms . ModelForm ) :
def __init__ ( s e l f , * a r g s , ** kwargs ) :
a c t i v i t y _ t y p e s = s e l f . g e t _ a c t i v i t y _ t y p e s ( kwargs . pop ( ’ u s e r ’ , None ) .
student )
4
s e l f . a c t i v i t y _ t y p e s = j s o n . dumps ( a c t i v i t y _ t y p e s )
5
super ( ApplicationUpdateForm , s e l f ) . __init__ ( * a r g s , ** kwargs )
6
7
def g e t _ a c t i v i t y _ t y p e s ( s e l f , s t u d e n t ) :
8
activity_types = [ ]
9
t y p e s = A c t i v i t y T y p e . o b j e c t s . f i l t e r ( achievement__student=s t u d e n t . id ) .
distinct ()
10
11
for type in t y p e s :
a c t i v i t y _ t y p e s . append (
12
{
13
’ i d ’ : type . id ,
14
’ name ’ : type . name ,
15
’ achievements ’ : [
16
{ ’ i d ’ : achievement . id , ’ name ’ : unicode ( achievement ) }
17
for achievement in type . achievement_set . f i l t e r ( s t u d e n t=
s t u d e n t . id )
18
]
19
20
21
}
)
return a c t i v i t y _ t y p e s
22
46
23
c l a s s Meta :
24
model = A p p l i c a t i o n
25
fields = [
26
’ activity_type ’ ,
27
’ event ’ ,
28
’ student ’ ,
29
’ status ’ ,
30
’ feedback ’ ,
31
’ achievements ’
32
]
Листинг 21: Класс обрабокти данных для редактирования заявки.
После успешного обновления заявки, пользователя перенаправит на
страницу со списком его заявок.
При открытии приема заявок от студентов, или же в случае если прием уже идет, студент может отправить свои заявки на рассмотрение комиссией. для этого ему необходимо отправить запрос по адресу
/studentship/applications/send. Запрос по указанному адресу обработает
класс ApplicationSend.
1
2
3
c l a s s A p p l i c a t i o n S e n d ( LoginRequiredMixin , StudentAccessMixin , TemplateView ) :
def p o s t ( s e l f , * a r g s , ** kwargs ) :
i f s e l f . r e q u e s t . method == "POST" :
4
a p p l i c a t i o n _ i d = s e l f . r e q u e s t .POST[ ’ a p p l i c a t i o n _ i d ’ ]
5
a p p l i c a t i o n = get_object_or_404 ( A p p l i c a t i o n , pk=a p p l i c a t i o n _ i d )
6
application . status = ’ waiting ’
7
a p p l i c a t i o n . event_id = s e l f . r e q u e s t .POST[ ’ event_id ’ ]
8
a p p l i c a t i o n . send_status = 1
9
a p p l i c a t i o n . save ( )
10
return H t t p R e s p o n s e R e d i r e c t ( r e v e r s e ( ’ a p p l i c a t i o n _ l i s t ’ ) )
Листинг 22: Класс отправки заявки на рассмотрение.
Данный класс по параметрам запроса определяет идентификатор заявки в базе данных, затем по идентификатору находит информацию о заявке, устанавливает её статус как "ожидание проверки прикрепляет данную
заявку к текущему приему и устанавливает флаг информирующий о том,
47
что заявка отправлена на рассмотрение.
В
случае
зователь
необходимости
должен
удаления
отправить
запрос
/studentship/applications/delete/<application_id>.
заявки,
по
За
польадресу
обработку
действия удаления отвечает следующий класс:
1
c l a s s A p p l i c a t i o n D e l e t e ( LoginRequiredMixin , StudentAccessMixin , DeleteView ) :
2
model = A p p l i c a t i o n
3
success_url = reverse_lazy ( ’ application_list ’ )
4
5
6
def get_context_data ( s e l f , * a r g s , ** kwargs ) :
c o n t e x t = super ( A p p l i c a t i o n D e l e t e , s e l f ) . get_context_data ( * a r g s , **
kwargs )
7
context [ ’ template_studentship ’ ] = ’ a c t i v e ’
8
return c o n t e x t
Листинг 23: Класс удаления заявки.
Данный класс удалит выбранную заявку, и затем перенаправит пользователя на страницу содержащую актуальный список заявок.
48
§2.7 Проверка заявок администратором системы
Заявки созданные студентами могут быть не всегда корректными и
правильно заполненными, поэтому они требуют проверки.
Для того, чтобы определить является ли поданная студентом заявка
корректной, сотруднику, ответственному за прием заявок на повышенную
стипендию, необходимо данную заявку проверить вручную.
Для организации проверки заявок студентов на повышенную стипендию был реализован соответствующий интерфейс [15] для сотрудников вуза.
По адресу
/studentship/employee/
находится веб-интерфейс для
управления заявками.
Рис. 15: Страница управления заявками.
за отображение списка заявок для сотрудника отвечает следующий
класс:
1
2
c l a s s EmployeeIndex ( LoginRequiredMixin , EmployeeAccessMixin , TemplateView ) :
template_name = ’ s t u d e n t s h i p / employee / i n d e x . html ’
3
4
5
def get_context_data ( s e l f , * a r g s , ** kwargs ) :
c o n t e x t = super ( EmployeeIndex , s e l f ) . get_context_data ( * a r g s , ** kwargs )
49
6
c o n t e x t [ ’ a p p l i c a t i o n ’ ] = A p p l i c a t i o n . o b j e c t s . e x t r a ( where =[" s e n d _ s t a t u s
= ’1 ’ " ] )
return c o n t e x t
7
Листинг 24: Класс загрузки списка заявок.
Данный класс загружает весь список заявок, отправленных студентами на рассмотрение.
Для
ки,
более
сотруднику
детального
необходимо
просмотра
обратиться
заяв-
по
/studentship/employee/applications/<application_id>.
адресу
За
отоб-
ражение страницы с детальной информацией о заявке отвечает следующий
класс.
1
c l a s s EmployeeApplicationShow ( LoginRequiredMixin , EmployeeAccessMixin ,
TemplateView ) :
2
template_name = ’ s t u d e n t s h i p / employee / a p p l i c a t i o n /show . html ’
3
4
5
def get_context_data ( s e l f , * a r g s , ** kwargs ) :
c o n t e x t = super ( EmployeeApplicationShow , s e l f ) . get_context_data ( * a r g s ,
** kwargs )
6
a p p l i c a t i o n = A p p l i c a t i o n . o b j e c t s . g e t ( id=kwargs [ " a p p l i c a t i o n _ i d " ] )
7
context [ ’ application ’ ] = application
8
context [ ’ achievements ’ ] = a p p l i c a t i o n . achievements . a l l ( ) .
p r e f e t c h _ r e l a t e d ( ’ scan_set ’ )
9
c o n t e x t [ ’ form ’ ] = ApplicationShowForm ( { ’ s t a t u s ’ : a p p l i c a t i o n . s t a t u s , ’
feedback ’ : a p p l i c a t i o n . feedback })
10
return c o n t e x t
11
12
13
def p o s t ( s e l f , * a r g s , ** kwargs ) :
i f s e l f . r e q u e s t . method == "POST" :
14
a p p l i c a t i o n _ i d = kwargs [ " a p p l i c a t i o n _ i d " ]
15
a p p l i c a t i o n = get_object_or_404 ( A p p l i c a t i o n , pk=a p p l i c a t i o n _ i d )
16
a p p l i c a t i o n . s t a t u s = s e l f . r e q u e s t .POST[ ’ s t a t u s ’ ]
17
a p p l i c a t i o n . f e e d b a c k = s e l f . r e q u e s t .POST[ ’ f e e d b a c k ’ ]
18
a p p l i c a t i o n . save ( )
19
return H t t p R e s p o n s e R e d i r e c t ( r e v e r s e ( ’ a p p l i c a t i o n s _ l i s t ’ ) )
Листинг 25: Класс отображения детальной информации о заявке.
50
Так же данный веб-интерфей позволяет управлять списками типов деятельности, по которой можно подать заявку, списками видов достижений
а так же сроками подачи заявок.
Рис. 16: Меню настроек процесса подачи заявок.
Поскольку прием заявок от студентов является ограниченным по срокам событием, данный интерфейс предоставляет возможность открывать
или закрывать приемом заявок от студентов, а так же управлять датами
начала приема и его закрытия.
За отображение данного списка отвечает следующий класс:
1
c l a s s EventIndex ( LoginRequiredMixin , EmployeeAccessMixin , L i s t V i e w ) :
2
paginate_by = 8
3
model = Event
4
template_name = ’ s t u d e n t s h i p / employee / e v e n t / i n d e x . html ’
Листинг 26: Класс отображения списка дат приема заявок.
Для создания нового приема заявок сотруднику необходимо нажать
кнопку ‘Создать‘. За обработку данного действия отвечает следующий
класс:
1
c l a s s EventCreate ( LoginRequiredMixin , EmployeeAccessMixin , CreateView ) :
2
f o r m _ c l a s s = EventCreateForm
3
template_name = ’ s t u d e n t s h i p / employee / e v e n t / c r e a t e . html ’
4
success_url = reverse_lazy ( ’ events_list ’ )
51
Рис. 17: Страница со списком дат приёма заявок.
Листинг 27: Класс создания нового приема.
В случае необходимости изменить статус или сроки приема, необходимо нажать кнопку ‘редактировать‘ на текущем актуальном приеме. По
нажатию данной кнопки отобразится форма редактирования информации о
приеме.
За отображение данной формы отвечает следующий класс:
1
2
c l a s s EventEdit ( LoginRequiredMixin , EmployeeAccessMixin , TemplateView ) :
template_name = ’ s t u d e n t s h i p / employee / e v e n t / e d i t . html ’
3
4
def get_context_data ( s e l f , * a r g s , ** kwargs ) :
5
c o n t e x t = super ( EventEdit , s e l f ) . get_context_data ( * a r g s , ** kwargs )
6
c o n t e x t [ ’ e v e n t ’ ] = Event . o b j e c t s . g e t ( id=kwargs [ " event_id " ] )
7
return c o n t e x t
8
9
def p o s t ( s e l f , * a r g s , ** kwargs ) :
10
i f s e l f . r e q u e s t . method == "POST" :
11
event_id = kwargs [ " event_id " ]
12
e v e n t = get_object_or_404 ( Event , pk=event_id )
13
e v e n t . y e a r = s e l f . r e q u e s t .POST[ ’ y e a r ’ ]
52
Рис. 18: Редактирование информации о приеме.
14
e v e n t . begin_date = s e l f . r e q u e s t .POST[ ’ begin_date ’ ]
15
e v e n t . end_date = s e l f . r e q u e s t .POST[ ’ end_date ’ ]
16
e v e n t . s t a t u s = s e l f . r e q u e s t .POST[ ’ s t a t u s ’ ]
17
event . save ( )
18
return H t t p R e s p o n s e R e d i r e c t ( r e v e r s e ( ’ e v e n t s _ l i s t ’ ) )
Листинг 28: Класс изменения информации о приеме.
Данный класс получает параметры из запроса, и обновляет соответствующие этим параметрам поля в записи о приеме.
53
Глава III Тестирование приложения
§3.1 Авторизация и аутентификация
Для того, чтобы студент мог начать пользоваться системой необходимо зарегестрироваться. Перейдя по адресу
/accounts/student/register/
пользователь попадает на форму регистрации студента.
Рис. 19: Регистрация студента.
Введя свои персональные данные, и отправив форму на сервер, пользователя перенаправит на страницу, содержащую информацию о необходимости подтверждения электронной почты.
Подтвердив свой адрес электронной почты, пользователь получит сообщение о том, что его аккаунт активирован, и он может войти в систему.
Для
входа
в
систему
достаточно
перейти
по
адресу
/accounts/student/login/.
Введя логин и пароль используемые при регистрации пользователь
попадает на ‘домашнюю‘ страницу студента.
54
Рис. 20: Требование активации аккаунта.
Рис. 21: Успешная активация аккаунта.
55
Рис. 22: Вход для студентов.
Рис. 23: Домашняя страница студента.
56
§3.2 Подача заявки на повышенную стипендию
Для просмотра списка достижений студенту достаточно перейти по
адресу
/studentship/achievements/.
Рис. 24: Список достижений.
Чтобы добавить новое достижение необходимо нажать кнопку ‘Добавить‘.
Заполнив все необходимые поля, и нажав кнопку сохранить пользователь создаст запись о новом достижении в системе.
По нажатию кнопки ‘Редактировать‘ пользователь может изменить
уже добавленное в систему достижени. Для того, чтобы удалить достижение,
необходимо нажать кнопку ‘Удалить‘.
Для
подачи
заявки
необходимо
перейти
по
адресу
/studentship/applications/.
На данной странице отображается список поданных студентом заявок.
Так же имеется возможность редактирования и удаления поданных заявок.
Для того, чтобы подать заявку необходимо нажать кнопку ‘Добавить‘.
В свою очередь проверяющий для проверки заявок, и их подтвержде-
57
Рис. 25: Форма создания достижения.
Рис. 26: Список заявок.
ния или отклонения должен перейти по адресу
/studentship/teacher/. На
данной странице распологается веб-интерфейс для управления процессом
подачи заявок на повышенную стипендию. Данный интерфейс позволяет
управлять сроками регистрации заявок, а так же позволяет просматривать
заявку и достижения прикрепленные к ней, а так же подтверждать или от58
Рис. 27: Добавление заявки.
клонять её.
Рис. 28: Список заявок студентов.
59
Заключение
Как итог, проделанная работа отвечает поставленной цели, а именно:
моделирование и разработка ядра приложения для подачи заявок на повышенную стипендию, а так же актуальности и особенностям заданной предметной области. Можно сделать вывод о том, что были решены следующие
задачи:
∙
Спроектирована БД, в которой будут храниться данные о индивидуальных достижениях студентов Орловского Государственного Университета им. И.С. Тургенева;
∙
Результат
проектирования
представлен
в
виде
набора
объектно-
реляционных моделей в контексте фреймворка Django;
∙
Разработан модуль регистрации и авторизации студентов в системе;
∙
Был
разработан
веб-интерфейс
для
взаимодействия
с
набором
объектно-реляционных моделей в контексте фреймворка Django так,
что он может предоставлять CRUD-доступ (создание, чтение, изменение, удаление) к представленным моделям.
Были полученные научные и научно технические результаты:
∙
разработано ядро веб приложения для подачи документов на повышенную стипендию с учетом особенностейвузовской организации документооборота;
∙
выполнена программная реализация приложения на современном языке программирования;
∙
проведена апробация приложения и выполнено тестирование.
60
Спроектированная база данных позволяет хранить достаточно большой объем информации о студентах, необходимых данные для подачи заявок
на повышенную стипендию, а так же разработать приложение для автоматизации подачи документов на повышенную государственную стипендию и
оптимизировать процесс получения и обработки соответствующей информации.
В процессе выполнения данной работы был получен веб-интерфейс,
позволяющий создавать, просматривать, изменять и удалить данные, относящиеся к индивидуальным достижениям студентов ФГБОУ ВО «Орловский государственный университет им. И.С. Тургенева», отвечая современным тенденциям применения веб-технологий в приложениях.
Все полученные результаты являются новыми и могут применяться
в рамках высших учебных заведений. Разработанное приложение не имеет
аналогов, полностью отвечая требованиям заданной предметной области.
61
Список литературы
1.
Системы
электронной
отчетности
о
научно-исследовательской
те сотрудников вуза [Электронный ресурс]. Режим доступа:
univ-orel.ru
— Дата доступа: 24.06.2018.
2.
система
Истина
-
управления
информацией
о
рабо-
http://nir.
результатах
научно-
исследовательской и педагогической деятельности [Электронный ресурс].
-
Режим
9143061/
http://istina.msu.ru/conferences/presentations/
доступа:
— Дата доступа: 27.06.2018.
3. 1С:Университет - система управления информацией о результатах научноисследовательской деятельности [Электронный ресурс]. - Режим доступа:
http://solutions.1c.ru/catalog/university/features
— Дата доступа:
27.06.2018.
4.
Academic
Line
-
cистема
управления
ятельностью
вуза
[Электронный
ресурс].
научно-исследовательской
Режим
доступа:
де-
http://www.
verticalportals.ru/Default.aspx?tabid=436 — Дата доступа: 27.06.2018.
5. Питер Роб. Системы баз данных: проектирование, реализация, управление – 5-е изд. – СПб.: «БХВ-Петербург», 2014. – 1040 с.
6. MySQL Workbench documentation [Электронный ресурс]. Режим доступа:
https://dev.mysql.com/doc/index-gui.html
— Дата доступа: 20.06.2018.
7. Python documentation [Электронный ресурс]. Режим доступа:
www.python.org/doc/
— Дата доступа: 29.05.2018.
8. Django documentation [Электронный ресурс]. Режим доступа:
docs.djangoproject.com/en/1.6/
9.
Git
documentation
https://
— Дата доступа: 14.06.2018.
[Электронный
git-scm.com/documentation
https://
ресурс].
Режим
доступа:
https://
— Дата доступа: 05.06.2018.
10. Лутц М. Программирование на Python, том 1 - 2 , 4-е издание/ М. Лутц
– СПб.: Символ-Плюс, 2011. – 922с.
11.
Регламент
подачи
документов
и
62
конкурсного
отбора
на
получе-
ние
повышенной
государственной
ный ресурс]. Режим доступа:
академической
стипендии
[Электрон-
http://oreluniver.ru/public/file/sveden/
grants/stipend/reglam_pov_stip_2017.pdf
— Дата доступа: 25.06.2018.
12. Дронов В.А. Django: практика создания Web-сайтов на Python. – СПб.:
БХВ-Петербург, 2016. – 528с.
13. Головатый А.Н. Django. Подробное руководство: Пер. с анг. [Текст] / А.
Головатый, Дж. Каплан-Мос. – 2-е изд. – СПб.: Символ-Плюс, 2010. – 560 с.
14. Django на русском [Электронный ресурс]. – [Б. м.: б. и.], 2018. Режим
доступа:
http://djbook.ru
— Дата доступа: 05.06.2018.
15. Форсье, Дж. Django. Разработка веб-приложений на Python / Дж. Форсье. - М.: Символ-плюс, 2014. - 343 c.
63
Приложение
1
from django . c o n f . u r l s import p a t t e r n s , u r l
2
3
from s t u d e n t . v i e w s import *
4
5
urlpatterns = patterns ( ’ ’ ,
6
u r l ( r ’ ^$ ’ , StudentIndexView . as_view ( ) , name= ’ student_index_view ’ ) ,
7
u r l ( r ’ ^ p r o f i l e / $ ’ , S t u d e n t P r o f i l e V i e w . as_view ( ) , name= ’ s t u d e n t _ p r o f i l e _ v i e w
’) ,
8
u r l ( r ’ ^ p r o f i l e / s t u d e n t $ ’ , StudentView . as_view ( ) , name= ’ p r o f i l e _ s t u d e n t _ v i e w
’) ,
9
u r l ( r ’ ^ p r o f i l e / s t u d e n t / e d i t / $ ’ , StudentUpdate . as_view ( ) ) ,
10
u r l ( r ’ ^ p r o f i l e / s t u d e n t / password_change / $ ’ , StudentPasswordChange . as_view ( ) ,
name= ’ student_password_change_view ’ ) ,
11
u r l ( r ’ ^ p r o f i l e / o p t i o n s $ ’ , OptionsView . as_view ( ) , name= ’
student_profile_options_view ’ ) ,
12
13
u r l ( r ’ ^ p r o f i l e / o p t i o n s / e d i t / $ ’ , OptionsUpdate . as_view ( ) ) ,
)
Листинг student/urls.py
1
# −*− coding : utf −8 −*−
2
3
from django . c o n t r i b . auth . models import User
4
from django . db import models
5
import d a t e t i m e
6
7
8
9
def y e a r _ c h o i c e s ( ) :
return [ ( r , r ) for r in range ( d a t e t i m e . d a t e . today ( ) . year − 4, d a t e t i m e . d a t e .
today ( ) . y e a r +2) ]
10
11
12
13
def c u r r e n t _ y e a r ( ) :
return d a t e t i m e . d a t e . today ( ) . y e a r
14
15
16
c l a s s Student ( models . Model ) :
17
owner = models . OneToOneField ( User , o n _ d e l e t e=models .CASCADE)
18
f i r s t _ n a m e = models . C h a r F i e l d ( " s t u d e n t ␣ f i r s t ␣name" , max_length =100 ,
64
19
20
n u l l=F a l s e , blank=F a l s e )
last_name = models . C h a r F i e l d ( " s t u d e n t ␣ l a s t ␣name" , max_length =100 ,
21
n u l l=F a l s e , blank=F a l s e )
22
23
24
def __unicode__ ( s e l f ) :
return u ’%s ␣%s ’ % ( s e l f . last_name , s e l f . f i r s t _ n a m e )
Листинг student/models.py
1
from django . c o n t r i b . auth . models import User
2
from b r a c e s . v i e w s import LoginRequiredMixin
3
from django . v i e w s . g e n e r i c import TemplateView
4
from django . v i e w s . g e n e r i c . e d i t import FormView , UpdateView
5
from django . c o r e . u r l r e s o l v e r s import r e v e r s e _ l a z y
6
from s t u d e n t s h i p . m i x i n s import EventStatusMixin , S t u d e n t A c c e s s M i x i n
7
from django . c o n t r i b . auth . forms import PasswordChangeForm
8
from s t u d e n t . models import Student
9
10
11
c l a s s StudentIndexView ( LoginRequiredMixin , EventStatusMixin , StudentAccessMixin
, TemplateView ) :
12
template_name = ’ s t u d e n t / i n d e x . html ’
13
14
15
def get_context_data ( s e l f , * a r g s , ** kwargs ) :
c o n t e x t = super ( StudentIndexView , s e l f ) . get_context_data ( * a r g s , **
kwargs )
16
u s e r _ i d = s e l f . r e q u e s t . u s e r . pk
17
c o n t e x t [ ’ u s e r ’ ] = User . o b j e c t s . g e t ( id=u s e r _ i d )
18
c o n t e x t [ ’ template_main ’ ] = ’ a c t i v e ’
19
return c o n t e x t
20
21
22
23
c l a s s S t u d e n t P r o f i l e V i e w ( LoginRequiredMixin , StudentAccessMixin , TemplateView ) :
template_name = ’ s t u d e n t / p r o f i l e . html ’
24
25
26
def get_context_data ( s e l f , * a r g s , ** kwargs ) :
c o n t e x t = super ( S t u d e n t P r o f i l e V i e w , s e l f ) . get_context_data ( * a r g s , **
kwargs )
27
u s e r _ i d = s e l f . r e q u e s t . u s e r . pk
28
c o n t e x t [ ’ u s e r ’ ] = User . o b j e c t s . g e t ( id=u s e r _ i d )
29
context [ ’ template_profile ’ ] = ’ active ’
65
30
return c o n t e x t
31
32
33
34
c l a s s StudentView ( LoginRequiredMixin , StudentAccessMixin , TemplateView ) :
template_name = ’ s t u d e n t / s t u d e n t . html ’
35
36
def get_context_data ( s e l f , * a r g s , ** kwargs ) :
37
c o n t e x t = super ( StudentView , s e l f ) . get_context_data ( * a r g s , ** kwargs )
38
u s e r _ i d = s e l f . r e q u e s t . u s e r . pk
39
c o n t e x t [ ’ u s e r ’ ] = User . o b j e c t s . g e t ( id=u s e r _ i d )
40
context [ ’ template_profile ’ ] = ’ active ’
41
c o n t e x t [ ’ user_item ’ ] = ’ a c t i v e ’
42
return c o n t e x t
43
44
45
c l a s s StudentUpdate ( LoginRequiredMixin , StudentAccessMixin , UpdateView ) :
46
template_name = ’ s t u d e n t / form_student . html ’
47
success_url = reverse_lazy ( ’ profile_student_view ’ )
48
model = User
49
f i e l d s = [ ’ e m a i l ’ , ’ username ’ ]
50
51
52
53
def g e t _ o b j e c t ( s e l f , q u e r y s e t=None ) :
i f s e l f . request . user . is_authenticated () :
return s e l f . r e q u e s t . u s e r
54
55
56
c l a s s StudentPasswordChange ( LoginRequiredMixin , StudentAccessMixin , FormView ) :
57
template_name = ’ s t u d e n t / form_student_password . html ’
58
f o r m _ c l a s s = PasswordChangeForm
59
success_url = reverse_lazy ( ’ profile_student_view ’ )
60
61
def get_form_kwargs ( s e l f ) :
62
kwargs = super ( StudentPasswordChange , s e l f ) . get_form_kwargs ( )
63
kwargs . update ( { ’ u s e r ’ : s e l f . r e q u e s t . u s e r } )
64
return kwargs
65
66
def form_valid ( s e l f , form ) :
67
form . s a v e ( )
68
return super ( StudentPasswordChange , s e l f ) . form_valid ( form )
69
66
70
71
72
c l a s s OptionsView ( LoginRequiredMixin , StudentAccessMixin , TemplateView ) :
template_name = ’ s t u d e n t / o p t i o n s . html ’
73
74
def get_context_data ( s e l f , * a r g s , ** kwargs ) :
75
c o n t e x t = super ( OptionsView , s e l f ) . get_context_data ( * a r g s , ** kwargs )
76
u s e r _ i d = s e l f . r e q u e s t . u s e r . pk
77
c o n t e x t [ ’ o p t i o n s ’ ] = Student . o b j e c t s . g e t ( owner_id=u s e r _ i d )
78
context [ ’ template_profile ’ ] = ’ active ’
79
context [ ’ options_item ’ ] = ’ a c t i v e ’
80
return c o n t e x t
81
82
83
c l a s s OptionsUpdate ( LoginRequiredMixin , StudentAccessMixin , UpdateView ) :
84
template_name = ’ s t u d e n t / form_options . html ’
85
model = Student
86
fields = [
87
’ last_name ’ ,
88
’ first_name ’ ,
89
]
90
success_url = reverse_lazy ( ’ student_profile_options_view ’ )
91
92
def g e t _ o b j e c t ( s e l f , q u e r y s e t=None ) :
return Student . o b j e c t s . g e t ( owner_id= s e l f . r e q u e s t . u s e r . pk )
93
Листинг student/views.py
1
from django . c o n f . u r l s import p a t t e r n s , u r l
2
from django . v i e w s . g e n e r i c . b a s e import TemplateView
3
from django . c o n t r i b . auth import v i e w s a s auth_views
4
5
from student_auth . v i e w s import S t u d e n t R e g i s t r a t i o n V i e w , S t u d e n t A c t i v a t i o n V i e w ,
login
6
from student_auth . forms import S t u d e n t R e g i s t r a t i o n F o r m
7
8
9
urlpatterns = patterns ( ’ ’ ,
u r l ( r ’ ^ r e g i s t e r / $ ’ , S t u d e n t R e g i s t r a t i o n V i e w . as_view ( f o r m _ c l a s s=
S t u d e n t R e g i s t r a t i o n F o r m , template_name= ’ student_auth / r e g i s t r a t i o n _ f o r m .
html ’ ) , name= ’ s t u d e n t _ r e g i s t r a t i o n _ r e g i s t e r ’ ) ,
10
u r l ( r ’ ^ a c t i v a t e / c o m p l e t e / $ ’ , TemplateView . as_view ( template_name= ’
student_auth / a c t i v a t i o n _ c o m p l e t e . html ’ ) , name= ’
67
student_registration_activation_complete ’ ) ,
11
u r l ( r ’ ^ a c t i v a t e / ( ?P<a c t i v a t i o n _ k e y >\w+)/ $ ’ , S t u d e n t A c t i v a t i o n V i e w . as_view ( )
, name= ’ s t u d e n t _ r e g i s t r a t i o n _ a c t i v a t e ’ ) ,
12
u r l ( r ’ ^ r e g i s t e r / c o m p l e t e / $ ’ , TemplateView . as_view ( template_name= ’
student_auth / r e g i s t r a t i o n _ c o m p l e t e . html ’ ) , name= ’
student_registration_complete ’ ) ,
13
u r l ( r ’ ^ r e g i s t e r / c l o s e d / $ ’ , TemplateView . as_view ( template_name= ’ student_auth
/ r e g i s t r a t i o n _ c l o s e d . html ’ ) , name= ’ s t u d e n t _ r e g i s t r a t i o n _ d i s a l l o w e d ’ ) ,
14
u r l ( r ’ ^ l o g i n / $ ’ , l o g i n , { ’ template_name ’ : ’ student_auth / l o g i n . html ’ } , name=
’ student_auth_login ’ ) ,
15
u r l ( r ’ ^ l o g o u t / $ ’ , auth_views . l o g o u t , { ’ template_name ’ : ’ student_auth / l o g o u t
. html ’ } , name= ’ student_auth_logout ’ ) ,
16
u r l ( r ’ ^password / change / $ ’ , auth_views . password_change , name= ’
student_auth_password_change ’ ) ,
17
u r l ( r ’ ^password / change / done / $ ’ , auth_views . password_change_done , name= ’
student_auth_password_change_done ’ ) ,
18
u r l ( r ’ ^password / r e s e t / $ ’ , auth_views . password_reset , name= ’
student_auth_password_reset ’ ) ,
19
u r l ( r ’ ^password / r e s e t / c o n f i r m / ( ?P<uidb36 >[0 −9A−Za−z ]+) − (?P<token >.+)/ $ ’ ,
auth_views . password_reset_confirm , name= ’
student_auth_password_reset_confirm ’ ) ,
20
u r l ( r ’ ^password / r e s e t / c o m p l e t e / $ ’ , auth_views . password_reset_complete , name
= ’ student_auth_password_reset_complete ’ ) ,
21
u r l ( r ’ ^password / r e s e t / done / $ ’ , auth_views . password_reset_done , name= ’
student_auth_password_reset_done ’ )
22
)
Листинг student_auth/urls.py
1
# −*− coding : utf −8 −*−
2
3
import d a t e t i m e
4
from django . c o n f import s e t t i n g s
5
from django . c o n t r i b . auth . models import User
6
from django . db import models
7
from django . t e m p l a t e . l o a d e r import r e n d e r _ t o _ s t r i n g
8
from r e g i s t r a t i o n . models import R e g i s t r a t i o n M a n a g e r
9
from django . u t i l s . t r a n s l a t i o n import u g e t t e x t _ l a z y a s _
10
11
12
try :
from django . u t i l s . t i m e z o n e import now a s datetime_now
68
13
14
except I m p o r t E r r o r :
datetime_now = d a t e t i m e . d a t e t i m e . now
15
16
17
18
c l a s s S t u d e n t R e g i s t r a t i o n P r o f i l e ( models . Model ) :
ACTIVATED = u"ALREADY_ACTIVATED"
19
20
u s e r = models . ForeignKey ( User , unique=True , verbose_name=_( ’ u s e r ’ ) )
21
a c t i v a t i o n _ k e y = models . C h a r F i e l d (_( ’ a c t i v a t i o n ␣ key ’ ) , max_length =40)
22
23
o b j e c t s = RegistrationManager ()
24
25
26
def s e n d _ a c t i v a t i o n _ e m a i l ( s e l f , s i t e ) :
ctx_dict = { ’ activation_key ’ : s e l f . activation_key ,
27
’ e x p i r a t i o n _ d a y s ’ : s e t t i n g s .ACCOUNT_ACTIVATION_DAYS,
28
’ site ’ : site}
29
s u b j e c t = r e n d e r _ t o _ s t r i n g ( ’ student_auth / a c t i v a t i o n _ e m a i l _ s u b j e c t . t x t ’ ,
30
31
ctx_dict )
subject = ’ ’ . join ( subject . s p l i t l i n e s () )
32
33
message = r e n d e r _ t o _ s t r i n g ( ’ student_auth / a c t i v a t i o n _ e m a i l . t x t ’ ,
34
ctx_dict )
35
36
s e l f . u s e r . e m a i l _ u s e r ( s u b j e c t , message , s e t t i n g s .DEFAULT_FROM_EMAIL)
37
38
c l a s s Meta :
39
verbose_name = _( ’ r e g i s t r a t i o n ␣ p r o f i l e ’ )
40
verbose_name_plural = _( ’ r e g i s t r a t i o n ␣ p r o f i l e s ’ )
41
db_table = ’ r e g i s t r a t i o n _ r e g i s t r a t i o n p r o f i l e ’
42
43
44
def __unicode__ ( s e l f ) :
return u" R e g i s t r a t i o n ␣ i n f o r m a t i o n ␣ f o r ␣%s " % s e l f . u s e r
45
46
47
def a c t i v a t i o n _ k e y _ e x p i r e d ( s e l f ) :
e x p i r a t i o n _ d a t e = d a t e t i m e . t i m e d e l t a ( days=s e t t i n g s .
ACCOUNT_ACTIVATION_DAYS)
48
49
50
return s e l f . a c t i v a t i o n _ k e y == s e l f .ACTIVATED or \
( s e l f . u s e r . d a t e _ j o i n e d + e x p i r a t i o n _ d a t e <= datetime_now ( ) )
a c t i v a t i o n _ k e y _ e x p i r e d . b o o l e a n = True
69
Листинг student_auth/models.py
1
from django . c o n t r i b . auth import REDIRECT_FIELD_NAME, l o g i n a s a u t h _ l o g i n
2
from django . c o n t r i b . s i t e s . models import R e q u e s t S i t e
3
from django . c o n t r i b . s i t e s . models import S i t e
4
from django . c o n t r i b . s i t e s . models import g e t _ c u r r e n t _ s i t e
5
from django . h t t p import H t t p R e s p o n s e R e d i r e c t
6
from django . s h o r t c u t s import r e s o l v e _ u r l
7
from django . t e m p l a t e . r e s p o n s e import TemplateResponse
8
from django . u t i l s . h t t p import i s _ s a f e _ u r l
9
from django . v i e w s . d e c o r a t o r s . c a c h e import never_cache
10
from django . v i e w s . d e c o r a t o r s . c s r f import c s r f _ p r o t e c t
11
from django . v i e w s . d e c o r a t o r s . debug import s e n s i t i v e _ p o s t _ p a r a m e t e r s
12
from r e g i s t r a t i o n . backends . d e f a u l t . v i e w s import R e g i s t r a t i o n V i e w ,
ActivationView
13
14
from student_auth import s i g n a l s
15
from student_auth . models import S t u d e n t R e g i s t r a t i o n P r o f i l e
16
from student_auth . forms import S t ud e n tA u t h en t i ca t i on F o rm
17
18 LOGIN_REDIRECT_URL = ’ / s t u d e n t ’
19
20
21
class StudentRegistrationView ( RegistrationView ) :
22
def r e g i s t e r ( s e l f , r e q u e s t , ** cleaned_data ) :
23
username , email , password = cleaned_data [ ’ username ’ ] , cleaned_data [ ’
e m a i l ’ ] , cleaned_data [ ’ password1 ’ ]
24
25
26
27
28
29
30
i f S i t e . _meta . i n s t a l l e d :
s i t e = S i t e . o b j e c t s . get_current ()
else :
s i t e = RequestSite ( request )
new_user = S t u d e n t R e g i s t r a t i o n P r o f i l e . o b j e c t s . c r e a t e _ i n a c t i v e _ u s e r (
username , email , password , s i t e )
s i g n a l s . s t u d e n t _ r e g i s t e r e d . send_robust ( s e n d e r= s e l f . __class__ ,
31
u s e r=new_user ,
32
r e q u e s t=r e q u e s t )
33
return new_user
34
35
def g e t _ s u c c e s s _ u r l ( s e l f , r e q u e s t , u s e r ) :
70
return ( ’ s t u d e n t _ r e g i s t r a t i o n _ c o m p l e t e ’ , ( ) , { } )
36
37
38
39
40
class StudentActivationView ( ActivationView ) :
def g e t _ s u c c e s s _ u r l ( s e l f , r e q u e s t , u s e r ) :
return ( ’ s t u d e n t _ r e g i s t r a t i o n _ a c t i v a t i o n _ c o m p l e t e ’ , ( ) , { } )
41
42
43
44
@sensitive_post_parameters ( )
45
@csrf_protect
46
@never_cache
47
def l o g i n ( r e q u e s t , template_name= ’ student_auth / l o g i n . html ’ ,
48
r e d i r e c t _ f i e l d _ n a m e=REDIRECT_FIELD_NAME,
49
a u t h e n t i c a t i o n _ f o r m=StudentAuthenticationForm ,
50
current_app=None , e x t r a _ c o n t e x t=None ) :
51
r e d i r e c t _ t o = r e q u e s t .REQUEST. g e t ( r e d i r e c t _ f i e l d _ n a m e , ’ ’ )
52
53
i f r e q u e s t . method == "POST" :
54
form = a u t h e n t i c a t i o n _ f o r m ( r e q u e s t , data=r e q u e s t .POST)
55
i f form . i s _ v a l i d ( ) :
56
i f not i s _ s a f e _ u r l ( u r l=r e d i r e c t _ t o , h o s t=r e q u e s t . get_host ( ) ) :
57
58
r e d i r e c t _ t o = r e s o l v e _ u r l (LOGIN_REDIRECT_URL)
59
60
a u t h _ l o g i n ( r e q u e s t , form . g e t _ u s e r ( ) )
61
return H t t p R e s p o n s e R e d i r e c t ( r e d i r e c t _ t o )
62
63
else :
64
form = a u t h e n t i c a t i o n _ f o r m ( r e q u e s t )
65
66
current_site = get_current_site ( request )
67
68
context = {
69
’ form ’ : form ,
70
redirect_field_name : redirect_to ,
71
’ s i t e ’ : current_site ,
72
’ site_name ’ : c u r r e n t _ s i t e . name ,
73
}
74
i f e x t r a _ c o n t e x t i s not None :
75
c o n t e x t . update ( e x t r a _ c o n t e x t )
71
76
return TemplateResponse ( r e q u e s t , template_name , c o n t e x t ,
77
current_app=current_app )
Листинг student_auth/views.py
1
from django . d i s p a t c h import S i g n a l
2
3
4
# A new student has registered .
5
s t u d e n t _ r e g i s t e r e d = S i g n a l ( p r o v i d i n g _ a r g s =[" u s e r " , " r e q u e s t " ] )
Листинг student_auth/signals.py
1
from django . d i s p a t c h import r e c e i v e r
2
from student_auth . s i g n a l s import s t u d e n t _ r e g i s t e r e d
3
from s t u d e n t . models import Student
4
5
6
@receiver ( student_registered )
7
def s t u d e n t _ r e g i s t e r e d _ h a n d l e r ( s e n d e r , u s e r , r e q u e s t , ** kwargs ) :
8
p r o f i l e = Student ( owner=u s e r )
9
p r o f i l e . middle_name = r e q u e s t .POST[ ’ middle_name ’ ]
10
p r o f i l e . f i r s t _ n a m e = r e q u e s t .POST[ ’ f i r s t _ n a m e ’ ]
11
p r o f i l e . last_name = r e q u e s t .POST[ ’ last_name ’ ]
12
p r o f i l e . save ( )
Листинг student_auth/handlers.py
1
from django . c o n f . u r l s import p a t t e r n s , u r l , RegexURLResolver
2
from s t u d e n t s h i p import v i e w s
3
4
5
6
def group ( regex , * a r g s ) :
return RegexURLResolver ( regex , a r g s )
7
8
9
10
urlpatterns = patterns (
’’,
11
# TODO: make group
12
u r l ( r ’ ^ a c h i e v e m e n t s / $ ’ , v i e w s . A c h i e v e m e n t L i s t . as_view ( ) , name= ’
achievement_list ’ ) ,
72
13
u r l ( r ’ ^ a c h i e v e m e n t s /new/ $ ’ , v i e w s . AchievementCreate . as_view ( ) , name= ’
achievement_new ’ ) ,
14
u r l ( r ’ ^ a c h i e v e m e n t s /show / ( ?P<pk>\d+)$ ’ , v i e w s . AchievementShow . as_view ( ) ,
name= ’ achievement_show ’ ) ,
15
u r l ( r ’ ^ a c h i e v e m e n t s / update / ( ?P<pk>\d+)$ ’ , v i e w s . AchievementUpdate . as_view ( )
, name= ’ a c h i e v e m e n t _ e d i t ’ ) ,
16
u r l ( r ’ ^ a c h i e v e m e n t s / d e l e t e / ( ?P<pk>\d+)$ ’ , v i e w s . AchievementDelete . as_view ( )
, name= ’ a c h i e v e m e n t _ d e l e t e ’ ) ,
17
# TODO: make group
18
u r l ( r ’ ^ a p p l i c a t i o n s / $ ’ , v i e w s . A p p l i c a t i o n L i s t . as_view ( ) , name= ’
application_list ’ ) ,
19
u r l ( r ’ ^ a p p l i c a t i o n s /new/ $ ’ , v i e w s . A p p l i c a t i o n C r e a t e . as_view ( ) , name= ’
application_new ’ ) ,
20
u r l ( r ’ ^ a p p l i c a t i o n s / send / $ ’ , v i e w s . A p p l i c a t i o n S e n d . as_view ( ) , name= ’
application_send ’ ) ,
21
u r l ( r ’ ^ a p p l i c a t i o n s /show / ( ?P<pk>\d+)$ ’ , v i e w s . ApplicationShow . as_view ( ) ,
name= ’ a p p l i c a t i o n _ s h o w ’ ) ,
22
u r l ( r ’ ^ a p p l i c a t i o n s / update / ( ?P<pk>\d+)$ ’ , v i e w s . A p p l i c a t i o n U p d a t e . as_view ( )
, name= ’ a p p l i c a t i o n _ e d i t ’ ) ,
23
u r l ( r ’ ^ a p p l i c a t i o n s / d e l e t e / ( ?P<pk>\d+)$ ’ , v i e w s . A p p l i c a t i o n D e l e t e . as_view ( )
, name= ’ a p p l i c a t i o n _ d e l e t e ’ ) ,
24
group ( r ’ ^employee / ’ ,
25
u r l ( r ’ ^$ ’ ,
v i e w s . EmployeeIndex . as_view ( ) , name= ’ a p p l i c a t i o n s _ l i s t ’ ) ,
26
u r l ( r ’^events$ ’ ,
27
u r l ( r ’^events / c r e a t e $ ’ ,
28
u r l ( r ’ ^ e v e n t s / ( ?P<event_id >\d+)/ update$ ’ ,
v i e w s . EventIndex . as_view ( ) , name= ’ e v e n t s _ l i s t ’ ) ,
v i e w s . EventCreate . as_view ( ) ) ,
v i e w s . EventEdit . as_view ( ) )
,
29
u r l ( r ’ ^ e v e n t s / d e l e t e / ( ?P<pk>\d+)$ ’ , v i e w s . E v e n t D e l e t e . as_view ( ) , name
=’ event_delete ’ ) ,
30
u r l ( r ’ ^ a p p l i c a t i o n s / ( ?P<a p p l i c a t i o n _ i d >\d+)$ ’ ,
views .
EmployeeApplicationShow . as_view ( ) , name= ’ a p p l i c a t i o n s _ s h o w ’ ) ,
31
u r l ( r ’^activity_types$ ’ ,
v i e w s . A c t i v i t y T y p e I n d e x . as_view ( ) , name= ’
activity_types_list ’ ) ,
32
u r l ( r ’^a ct i v i ty _ t y p e s / c r e a t e $ ’ ,
v i e w s . A c t i v i t y T y p e C r e a t e . as_view ( ) ) ,
33
u r l ( r ’ ^ a c t i v i t y _ t y p e s / ( ?P<a c t i v i t y _ t y p e _ i d >\d+)/ update$ ’ ,
views .
A c t i v i t y T y p e E d i t . as_view ( ) ) ,
34
u r l ( r ’ ^ a c t i v i t y _ t y p e s / d e l e t e / ( ?P<pk>\d+)$ ’ , v i e w s . A c t i v i t y T y p e D e l e t e .
as_view ( ) , name= ’ a c t i v i t y _ t y p e _ d e l e t e ’ ) ,
35
u r l ( r ’ ^achievement_types$ ’ ,
v i e w s . AchievementTypeIndex . as_view ( ) ,
name= ’ a c h i e v e m e n t _ t y p e s _ l i s t ’ ) ,
73
36
u r l ( r ’ ^achievement_types / c r e a t e $ ’ ,
v i e w s . AchievementTypeCreate .
as_view ( ) ) ,
37
u r l ( r ’ ^achievement_types / update / ( ?P<pk>\d+)$ ’ ,
views .
AchievementTypeEdit . as_view ( ) ) ,
38
u r l ( r ’ ^achievement_types / d e l e t e / ( ?P<pk>\d+)$ ’ , v i e w s .
AchievementTypeDelete . as_view ( ) , name= ’ achievement_type_delete ’ ) ,
39
u r l ( r ’ ^ s t u d e n t _ p r o f i l e $ ’ , v i e w s . S t u d e n t P r o f i l e . as_view ( ) , name= ’
student_profile ’ ) ,
40
41
)
)
Листинг studentship/urls.py
1
# −*− coding : utf −8 −*−
2
3
from django . db import models
4
5
from s t u d e n t . models import Student
6
7
8
9
c l a s s Event ( models . Model ) :
y e a r = models . I n t e g e r F i e l d ( )
10
begin_date = models . D a t e F i e l d ( )
11
end_date = models . D a t e F i e l d ( )
12
s t a t u s = models . C h a r F i e l d ( " e v e n t ␣ s t a t u s " , max_length =50 , n u l l=F a l s e ,
13
blank=F a l s e )
14
15
16
17
c l a s s A c t i v i t y T y p e ( models . Model ) :
name = models . C h a r F i e l d ( "name␣ o f ␣ a c t i v i t y ␣ type " , max_length =50 ,
18
n u l l=F a l s e , blank=F a l s e )
19
20
21
def __unicode__ ( s e l f ) :
return s e l f . name
22
23
24
25
26
27
c l a s s AchievementType ( models . Model ) :
name = models . C h a r F i e l d ( "name␣ o f ␣ achievement ␣ type " , max_length =50 ,
n u l l=F a l s e , blank=F a l s e )
a c t i v i t y _ t y p e = models . ForeignKey ( A c t i v i t y T y p e )
28
74
29
30
def __unicode__ ( s e l f ) :
return s e l f . name
31
32
33
c l a s s Achievement ( models . Model ) :
34
a c t i v i t y _ t y p e = models . ForeignKey ( A c t i v i t y T y p e )
35
achievement_type = models . ForeignKey ( AchievementType )
36
s t u d e n t = models . ForeignKey ( Student )
37
obtain_date = models . D a t e F i e l d ( )
38
39
40
def __unicode__ ( s e l f ) :
return s e l f . achievement_type . name
41
42
43
c l a s s A p p l i c a t i o n ( models . Model ) :
44
a c t i v i t y _ t y p e = models . ForeignKey ( A c t i v i t y T y p e )
45
e v e n t = models . ForeignKey ( Event , n u l l=True , blank=True )
46
a c h i e v e m e n t s = models . ManyToManyField ( Achievement )
47
s t u d e n t = models . ForeignKey ( Student , n u l l=True , blank=True )
48
s t a t u s = models . C h a r F i e l d ( " a p p l i c a t i o n ␣ s t a t u s " , max_length =50 , n u l l=True ,
49
blank=True )
50
f e e d b a c k = models . T e x t F i e l d ( " a p p l i c a t i o n ␣ f e e d b a c k " , n u l l=True , blank=True )
51
s e n d _ s t a t u s = models . I n t e g e r F i e l d ( d e f a u l t =0)
52
53
54
c l a s s Scan ( models . Model ) :
55
achievement = models . ForeignKey ( Achievement )
56
f i l e n a m e = models . F i l e F i e l d ( upload_to= ’ . / s c a n / s t u d e n t ’ , blank=True )
Листинг studentship/models.py
1
# −*− coding : utf −8 −*−
2
3
from django . h t t p import H t t p R e s p o n s e R e d i r e c t
4
from django . v i e w s . g e n e r i c import TemplateView , ListView , D e t a i l V i e w
5
from django . v i e w s . g e n e r i c . e d i t import CreateView , UpdateView , DeleteView
6
from django . c o r e . u r l r e s o l v e r s import r e v e r s e _ l a z y
7
from django . v i e w s import g e n e r i c
8
from b r a c e s . v i e w s import LoginRequiredMixin
9
from django . c o r e . u r l r e s o l v e r s import r e v e r s e
10
from django . s h o r t c u t s import get_object_or_404
75
11
from s t u d e n t s h i p . models import *
12
from s t u d e n t s h i p . forms import *
13
from s t u d e n t s h i p . m i x i n s import *
14
from s t u d e n t . models import *
15
16
17
c l a s s A c h i e v e m e n t L i s t ( LoginRequiredMixin , StudentAccessMixin , L i s t V i e w ) :
18
paginate_by = 5
19
model = Achievement
20
21
22
def get_context_data ( s e l f , * a r g s , ** kwargs ) :
c o n t e x t = super ( AchievementList , s e l f ) . get_context_data ( * a r g s , ** kwargs
)
23
c o n t e x t [ ’ template_achievements ’ ] = ’ a c t i v e ’
24
return c o n t e x t
25
26
27
c l a s s AchievementCreate ( LoginRequiredMixin , StudentAccessMixin , CreateView ) :
28
f o r m _ c l a s s = AchievementCreateForm
29
template_name = ’ s t u d e n t s h i p / achievement_form . html ’
30
31
32
def get_context_data ( s e l f , * a r g s , ** kwargs ) :
c o n t e x t = super ( AchievementCreate , s e l f ) . get_context_data ( * a r g s , **
kwargs )
33
c o n t e x t [ ’ template_achievements ’ ] = ’ a c t i v e ’
34
return c o n t e x t
35
36
def form_valid ( s e l f , form ) :
37
form . i n s t a n c e . s t u d e n t = s e l f . r e q u e s t . u s e r . s t u d e n t
38
super ( AchievementCreate , s e l f ) . form_valid ( form )
39
form . i n s t a n c e . s c a n _ s e t . c r e a t e ( f i l e n a m e=form . cleaned_data [ ’ s c a n ’ ] )
40
return super ( AchievementCreate , s e l f ) . form_valid ( form )
41
42
43
def g e t _ s u c c e s s _ u r l ( s e l f ) :
return r e v e r s e _ l a z y ( ’ a c h i e v e m e n t _ l i s t ’ )
44
45
46
47
c l a s s AchievementShow ( LoginRequiredMixin , StudentAccessMixin , D e t a i l V i e w ) :
model = Achievement
48
76
49
50
def get_context_data ( s e l f , * a r g s , ** kwargs ) :
c o n t e x t = super ( AchievementShow , s e l f ) . get_context_data ( * a r g s , ** kwargs
)
51
c o n t e x t [ ’ template_achievements ’ ] = ’ a c t i v e ’
52
return c o n t e x t
53
54
55
c l a s s AchievementUpdate ( LoginRequiredMixin , StudentAccessMixin , UpdateView ) :
56
model = Achievement
57
f o r m _ c l a s s = AchievementUpdateForm
58
template_name = ’ s t u d e n t s h i p / achievement_form . html ’
59
60
def get_context_data ( s e l f , ** kwargs ) :
61
c o n t e x t = super ( AchievementUpdate , s e l f ) . get_context_data ( * * kwargs )
62
c o n t e x t [ ’ uploaded_scan ’ ] = Scan . o b j e c t s . f i l t e r ( achievement= s e l f . kwargs [
’ pk ’ ] ) . l a s t ( )
63
c o n t e x t [ ’ template_achievements ’ ] = ’ a c t i v e ’
64
return c o n t e x t
65
66
def form_valid ( s e l f , form ) :
67
form . i n s t a n c e . s t u d e n t = s e l f . r e q u e s t . u s e r . s t u d e n t
68
super ( AchievementUpdate , s e l f ) . form_valid ( form )
69
i f form . cleaned_data [ ’ s c a n ’ ] :
70
71
form . i n s t a n c e . s c a n _ s e t . update ( f i l e n a m e=form . cleaned_data [ ’ s c a n ’ ] )
return super ( AchievementUpdate , s e l f ) . form_valid ( form )
72
73
74
def g e t _ s u c c e s s _ u r l ( s e l f ) :
return r e v e r s e _ l a z y ( ’ a c h i e v e m e n t _ l i s t ’ )
75
76
77
c l a s s AchievementDelete ( LoginRequiredMixin , StudentAccessMixin , DeleteView ) :
78
model = Achievement
79
success_url = reverse_lazy ( ’ achievement_list ’ )
80
81
82
def get_context_data ( s e l f , * a r g s , ** kwargs ) :
c o n t e x t = super ( AchievementDelete , s e l f ) . get_context_data ( * a r g s , **
kwargs )
83
c o n t e x t [ ’ template_achievements ’ ] = ’ a c t i v e ’
84
return c o n t e x t
85
77
86
87
c l a s s A p p l i c a t i o n L i s t ( LoginRequiredMixin , EventStatusMixin , StudentAccessMixin ,
ListView ) :
88
paginate_by = 8
89
model = A p p l i c a t i o n
90
91
92
def get_context_data ( s e l f , * a r g s , ** kwargs ) :
c o n t e x t = super ( A p p l i c a t i o n L i s t , s e l f ) . get_context_data ( * a r g s , ** kwargs
)
93
context [ ’ template_studentship ’ ] = ’ a c t i v e ’
94
return c o n t e x t
95
96
97
c l a s s A p p l i c a t i o n C r e a t e ( LoginRequiredMixin , StudentAccessMixin , CreateView ) :
98
form_class = ApplicationCreateForm
99
template_name = ’ s t u d e n t s h i p / a p p l i c a t i o n _ f o r m . html ’
100
101
102
def get_context_data ( s e l f , * a r g s , ** kwargs ) :
c o n t e x t = super ( A p p l i c a t i o n C r e a t e , s e l f ) . get_context_data ( * a r g s , **
kwargs )
103
context [ ’ template_studentship ’ ] = ’ a c t i v e ’
104
return c o n t e x t
105
106
def get_form_kwargs ( s e l f ) :
107
kwargs = super ( A p p l i c a t i o n C r e a t e , s e l f ) . get_form_kwargs ( )
108
kwargs [ ’ u s e r ’ ] = s e l f . r e q u e s t . u s e r
109
return kwargs
110
111
def form_valid ( s e l f , form ) :
112
form . i n s t a n c e . s t u d e n t = s e l f . r e q u e s t . u s e r . s t u d e n t
113
form . i n s t a n c e . s t a t u s = ’ none_status ’
114
return super ( A p p l i c a t i o n C r e a t e , s e l f ) . form_valid ( form )
115
116
117
def g e t _ s u c c e s s _ u r l ( s e l f ) :
return r e v e r s e _ l a z y ( ’ a p p l i c a t i o n _ l i s t ’ )
118
119
120
121
c l a s s ApplicationShow ( LoginRequiredMixin , StudentAccessMixin , D e t a i l V i e w ) :
model = A p p l i c a t i o n
122
78
123
124
def get_context_data ( s e l f , * a r g s , ** kwargs ) :
c o n t e x t = super ( ApplicationShow , s e l f ) . get_context_data ( * a r g s , ** kwargs
)
125
context [ ’ template_studentship ’ ] = ’ a c t i v e ’
126
return c o n t e x t
127
128
129
c l a s s A p p l i c a t i o n U p d a t e ( LoginRequiredMixin , StudentAccessMixin , UpdateView ) :
130
f o r m _ c l a s s = ApplicationUpdateForm
131
model = A p p l i c a t i o n
132
template_name = ’ s t u d e n t s h i p / a p p l i c a t i o n _ f o r m . html ’
133
134
135
def get_context_data ( s e l f , * a r g s , ** kwargs ) :
c o n t e x t = super ( A p p l i c a t i o n U p d a t e , s e l f ) . get_context_data ( * a r g s , **
kwargs )
136
context [ ’ template_studentship ’ ] = ’ a c t i v e ’
137
return c o n t e x t
138
139
def get_form_kwargs ( s e l f ) :
140
kwargs = super ( A p p l i c a t i o n U p d a t e , s e l f ) . get_form_kwargs ( )
141
kwargs [ ’ u s e r ’ ] = s e l f . r e q u e s t . u s e r
142
return kwargs
143
144
def form_valid ( s e l f , form ) :
145
form . i n s t a n c e . s t u d e n t = s e l f . r e q u e s t . u s e r . s t u d e n t
146
form . i n s t a n c e . s t a t u s = ’ none_status ’
147
return super ( A p p l i c a t i o n U p d a t e , s e l f ) . form_valid ( form )
148
149
150
def g e t _ s u c c e s s _ u r l ( s e l f ) :
return r e v e r s e _ l a z y ( ’ a p p l i c a t i o n _ l i s t ’ )
151
152
153
154
155
c l a s s A p p l i c a t i o n S e n d ( LoginRequiredMixin , StudentAccessMixin , TemplateView ) :
def p o s t ( s e l f , * a r g s , ** kwargs ) :
i f s e l f . r e q u e s t . method == "POST" :
156
a p p l i c a t i o n _ i d = s e l f . r e q u e s t .POST[ ’ a p p l i c a t i o n _ i d ’ ]
157
a p p l i c a t i o n = get_object_or_404 ( A p p l i c a t i o n , pk=a p p l i c a t i o n _ i d )
158
application . status = ’ waiting ’
159
a p p l i c a t i o n . event_id = s e l f . r e q u e s t .POST[ ’ event_id ’ ]
160
a p p l i c a t i o n . send_status = 1
79
161
162
a p p l i c a t i o n . save ( )
return H t t p R e s p o n s e R e d i r e c t ( r e v e r s e ( ’ a p p l i c a t i o n _ l i s t ’ ) )
163
164
165
c l a s s A p p l i c a t i o n D e l e t e ( LoginRequiredMixin , StudentAccessMixin , DeleteView ) :
166
model = A p p l i c a t i o n
167
success_url = reverse_lazy ( ’ application_list ’ )
168
169
170
def get_context_data ( s e l f , * a r g s , ** kwargs ) :
c o n t e x t = super ( A p p l i c a t i o n D e l e t e , s e l f ) . get_context_data ( * a r g s , **
kwargs )
171
context [ ’ template_studentship ’ ] = ’ a c t i v e ’
172
return c o n t e x t
173
174
175
# Employee part
176
c l a s s EmployeeIndex ( LoginRequiredMixin , EmployeeAccessMixin , TemplateView ) :
177
template_name = ’ s t u d e n t s h i p / employee / i n d e x . html ’
178
179
def get_context_data ( s e l f , * a r g s , ** kwargs ) :
180
c o n t e x t = super ( EmployeeIndex , s e l f ) . get_context_data ( * a r g s , ** kwargs )
181
c o n t e x t [ ’ a p p l i c a t i o n ’ ] = A p p l i c a t i o n . o b j e c t s . e x t r a ( where =[" s e n d _ s t a t u s
= ’1 ’ " ] )
182
return c o n t e x t
183
184
185
c l a s s EmployeeApplicationShow ( LoginRequiredMixin , EmployeeAccessMixin ,
TemplateView ) :
186
template_name = ’ s t u d e n t s h i p / employee / a p p l i c a t i o n /show . html ’
187
188
189
def get_context_data ( s e l f , * a r g s , ** kwargs ) :
c o n t e x t = super ( EmployeeApplicationShow , s e l f ) . get_context_data ( * a r g s ,
** kwargs )
190
a p p l i c a t i o n = A p p l i c a t i o n . o b j e c t s . g e t ( id=kwargs [ " a p p l i c a t i o n _ i d " ] )
191
context [ ’ application ’ ] = application
192
context [ ’ achievements ’ ] = a p p l i c a t i o n . achievements . a l l ( ) .
p r e f e t c h _ r e l a t e d ( ’ scan_set ’ )
193
c o n t e x t [ ’ form ’ ] = ApplicationShowForm ( { ’ s t a t u s ’ : a p p l i c a t i o n . s t a t u s , ’
feedback ’ : a p p l i c a t i o n . feedback })
194
return c o n t e x t
80
195
196
197
def p o s t ( s e l f , * a r g s , ** kwargs ) :
i f s e l f . r e q u e s t . method == "POST" :
198
a p p l i c a t i o n _ i d = kwargs [ " a p p l i c a t i o n _ i d " ]
199
a p p l i c a t i o n = get_object_or_404 ( A p p l i c a t i o n , pk=a p p l i c a t i o n _ i d )
200
a p p l i c a t i o n . s t a t u s = s e l f . r e q u e s t .POST[ ’ s t a t u s ’ ]
201
a p p l i c a t i o n . f e e d b a c k = s e l f . r e q u e s t .POST[ ’ f e e d b a c k ’ ]
202
a p p l i c a t i o n . save ( )
203
return H t t p R e s p o n s e R e d i r e c t ( r e v e r s e ( ’ a p p l i c a t i o n s _ l i s t ’ ) )
204
205
206
c l a s s EventIndex ( LoginRequiredMixin , EmployeeAccessMixin , L i s t V i e w ) :
207
paginate_by = 8
208
model = Event
209
template_name = ’ s t u d e n t s h i p / employee / e v e n t / i n d e x . html ’
210
211
212
c l a s s EventCreate ( LoginRequiredMixin , EmployeeAccessMixin , CreateView ) :
213
f o r m _ c l a s s = EventCreateForm
214
template_name = ’ s t u d e n t s h i p / employee / e v e n t / c r e a t e . html ’
215
success_url = reverse_lazy ( ’ events_list ’ )
216
217
218
219
c l a s s EventEdit ( LoginRequiredMixin , EmployeeAccessMixin , TemplateView ) :
template_name = ’ s t u d e n t s h i p / employee / e v e n t / e d i t . html ’
220
221
def get_context_data ( s e l f , * a r g s , ** kwargs ) :
222
c o n t e x t = super ( EventEdit , s e l f ) . get_context_data ( * a r g s , ** kwargs )
223
c o n t e x t [ ’ e v e n t ’ ] = Event . o b j e c t s . g e t ( id=kwargs [ " event_id " ] )
224
return c o n t e x t
225
226
def p o s t ( s e l f , * a r g s , ** kwargs ) :
227
i f s e l f . r e q u e s t . method == "POST" :
228
event_id = kwargs [ " event_id " ]
229
e v e n t = get_object_or_404 ( Event , pk=event_id )
230
e v e n t . y e a r = s e l f . r e q u e s t .POST[ ’ y e a r ’ ]
231
e v e n t . begin_date = s e l f . r e q u e s t .POST[ ’ begin_date ’ ]
232
e v e n t . end_date = s e l f . r e q u e s t .POST[ ’ end_date ’ ]
233
e v e n t . s t a t u s = s e l f . r e q u e s t .POST[ ’ s t a t u s ’ ]
234
event . save ( )
81
return H t t p R e s p o n s e R e d i r e c t ( r e v e r s e ( ’ e v e n t s _ l i s t ’ ) )
235
236
237
238
c l a s s E v e n t D e l e t e ( LoginRequiredMixin , EmployeeAccessMixin , DeleteView ) :
239
model = Event
240
success_url = reverse_lazy ( ’ events_list ’ )
241
242
243
c l a s s A c t i v i t y T y p e I n d e x ( LoginRequiredMixin , EmployeeAccessMixin , L i s t V i e w ) :
244
paginate_by = 8
245
model = A c t i v i t y T y p e
246
template_name = ’ s t u d e n t s h i p / employee / a c t i v i t y _ t y p e / i n d e x . html ’
247
248
249
c l a s s A c t i v i t y T y p e C r e a t e ( LoginRequiredMixin , EmployeeAccessMixin , TemplateView )
:
250
template_name = ’ s t u d e n t s h i p / employee / a c t i v i t y _ t y p e / c r e a t e . html ’
251
252
253
def get_context_data ( s e l f , * a r g s , ** kwargs ) :
c o n t e x t = super ( A c t i v i t y T y p e C r e a t e , s e l f ) . get_context_data ( * a r g s , **
kwargs )
254
c o n t e x t [ ’ form ’ ] = ActivityTypeForm ( )
255
return c o n t e x t
256
257
def p o s t ( s e l f , * a r g s , ** kwargs ) :
258
c o n t e x t = s e l f . get_context_data ( * * kwargs )
259
i f s e l f . r e q u e s t . method == "POST" :
260
form = ActivityTypeForm ( s e l f . r e q u e s t .POST)
261
i f form . i s _ v a l i d ( ) :
262
A c t i v i t y T y p e ( name= s e l f . r e q u e s t .POST[ ’ name ’ ] , ) . s a v e ( )
263
return H t t p R e s p o n s e R e d i r e c t ( r e v e r s e ( ’ a c t i v i t y _ t y p e s _ l i s t ’ ) )
264
265
266
267
else :
form = ActivityTypeForm ( )
c o n t e x t [ ’ form ’ ] = form
return super ( TemplateView , s e l f ) . r en de r_ t o_ re sp on s e ( c o n t e x t , ** kwargs )
268
269
270
271
c l a s s A c t i v i t y T y p e E d i t ( LoginRequiredMixin , EmployeeAccessMixin , TemplateView ) :
template_name = ’ s t u d e n t s h i p / employee / a c t i v i t y _ t y p e / e d i t . html ’
272
82
273
def get_context_data ( s e l f , * a r g s , ** kwargs ) :
c o n t e x t = super ( A c t i v i t y T y p e E d i t , s e l f ) . get_context_data ( * a r g s , **
274
kwargs )
c o n t e x t [ ’ a c t i v i t y _ t y p e ’ ] = A c t i v i t y T y p e . o b j e c t s . g e t ( id=kwargs [ "
275
activity_type_id " ] )
return c o n t e x t
276
277
278
def p o s t ( s e l f , * a r g s , ** kwargs ) :
i f s e l f . r e q u e s t . method == "POST" :
279
280
a c t i v i t y _ t y p e _ i d = kwargs [ " a c t i v i t y _ t y p e _ i d " ]
281
a c t i v i t y _ t y p e = get_object_or_404 ( ActivityType , pk=a c t i v i t y _ t y p e _ i d
)
282
a c t i v i t y _ t y p e . name = s e l f . r e q u e s t .POST[ ’ name ’ ]
283
activity_type . save ( )
return H t t p R e s p o n s e R e d i r e c t ( r e v e r s e ( ’ a c t i v i t y _ t y p e s _ l i s t ’ ) )
284
285
286
287
c l a s s A c t i v i t y T y p e D e l e t e ( LoginRequiredMixin , EmployeeAccessMixin , DeleteView ) :
288
model = A c t i v i t y T y p e
289
success_url = reverse_lazy ( ’ activity_types_list ’ )
290
291
292
c l a s s AchievementTypeIndex ( LoginRequiredMixin , EmployeeAccessMixin , L i s t V i e w ) :
293
paginate_by = 8
294
model = AchievementType
295
template_name = ’ s t u d e n t s h i p / employee / achievement_type / i n d e x . html ’
296
297
298
c l a s s AchievementTypeCreate ( LoginRequiredMixin , EmployeeAccessMixin , CreateView
):
299
model = AchievementType
300
fields = [
301
’ name ’ ,
302
’ activity_type ’
303
]
304
template_name = ’ s t u d e n t s h i p / employee / achievement_type / c r e a t e . html ’
305
success_url = reverse_lazy ( ’ achievement_types_list ’ )
306
307
308
c l a s s AchievementTypeEdit ( LoginRequiredMixin , EmployeeAccessMixin , UpdateView ) :
83
309
model = AchievementType
310
fields = [
311
’ name ’ ,
312
’ activity_type ’
313
]
314
template_name = ’ s t u d e n t s h i p / employee / achievement_type / e d i t . html ’
315
success_url = reverse_lazy ( ’ achievement_types_list ’ )
316
317
318
c l a s s AchievementTypeDelete ( LoginRequiredMixin , EmployeeAccessMixin , DeleteView
):
319
model = AchievementType
320
success_url = reverse_lazy ( ’ achievement_types_list ’ )
321
322
323
324
c l a s s S t u d e n t P r o f i l e ( LoginRequiredMixin , EmployeeAccessMixin , TemplateView ) :
template_name = ’ s t u d e n t s h i p / s t u d e n t _ p r o f i l e . html ’
325
326
def get_context_data ( s e l f , * a r g s , ** kwargs ) :
327
c o n t e x t = super ( S t u d e n t P r o f i l e , s e l f ) . get_context_data ( * a r g s , ** kwargs )
328
return c o n t e x t
Листинг studentship/views.py
1
# −*− coding : utf −8 −*−
2
3
import j s o n
4
from django import forms
5
from s t u d e n t s h i p . models import Achievement , ActivityType , A p p l i c a t i o n , Event
6
7
8
9
c l a s s EventCreateForm ( forms . ModelForm ) :
CHOICES = ( ( ’ open ’ , ’Открыт о ’ , ) , ( ’ c l o s e ’ , ’ Закрыт о ’ , ) )
10
y e a r = forms . I n t e g e r F i e l d ( w i d g e t=forms . TextInput ( ) )
11
begin_date = forms . D a t e F i e l d ( )
12
end_date = forms . D a t e F i e l d ( )
13
s t a t u s = forms . C h o i c e F i e l d ( w i d g e t=forms . S e l e c t , c h o i c e s=CHOICES)
14
15
c l a s s Meta :
16
model = Event
17
fields = [
84
18
’ year ’ ,
19
’ begin_date ’ ,
20
’ end_date ’ ,
21
’ status ’
22
]
23
24
25
26
27
c l a s s A p p l i c a t i o n C r e a t e F o r m ( forms . ModelForm ) :
def __init__ ( s e l f , * a r g s , ** kwargs ) :
a c t i v i t y _ t y p e s = s e l f . g e t _ a c t i v i t y _ t y p e s ( kwargs . pop ( ’ u s e r ’ , None ) .
student )
28
s e l f . a c t i v i t y _ t y p e s = j s o n . dumps ( a c t i v i t y _ t y p e s )
29
super ( ApplicationCreateForm , s e l f ) . __init__ ( * a r g s , ** kwargs )
30
31
def g e t _ a c t i v i t y _ t y p e s ( s e l f , s t u d e n t ) :
32
activity_types = [ ]
33
t y p e s = A c t i v i t y T y p e . o b j e c t s . f i l t e r ( achievement__student=s t u d e n t . id ) .
distinct ()
34
35
for type in t y p e s :
a c t i v i t y _ t y p e s . append (
36
{
37
’ i d ’ : type . id ,
38
’ name ’ : type . name ,
39
’ achievements ’ : [
40
{ ’ i d ’ : achievement . id , ’ name ’ : unicode ( achievement ) }
41
for achievement in type . achievement_set . f i l t e r ( s t u d e n t=
s t u d e n t . id )
42
]
43
44
45
}
)
return a c t i v i t y _ t y p e s
46
47
c l a s s Meta :
48
model = A p p l i c a t i o n
49
fields = [
50
’ activity_type ’ ,
51
’ event ’ ,
52
’ student ’ ,
53
’ status ’ ,
54
’ feedback ’ ,
85
55
56
’ achievements ’
]
57
58
59
60
61
c l a s s ApplicationUpdateForm ( forms . ModelForm ) :
def __init__ ( s e l f , * a r g s , ** kwargs ) :
a c t i v i t y _ t y p e s = s e l f . g e t _ a c t i v i t y _ t y p e s ( kwargs . pop ( ’ u s e r ’ , None ) .
student )
62
s e l f . a c t i v i t y _ t y p e s = j s o n . dumps ( a c t i v i t y _ t y p e s )
63
super ( ApplicationUpdateForm , s e l f ) . __init__ ( * a r g s , ** kwargs )
64
65
def g e t _ a c t i v i t y _ t y p e s ( s e l f , s t u d e n t ) :
66
activity_types = [ ]
67
t y p e s = A c t i v i t y T y p e . o b j e c t s . f i l t e r ( achievement__student=s t u d e n t . id ) .
distinct ()
68
for type in t y p e s :
69
a c t i v i t y _ t y p e s . append (
70
{
71
’ i d ’ : type . id ,
72
’ name ’ : type . name ,
73
’ achievements ’ : [
74
{ ’ i d ’ : achievement . id , ’ name ’ : unicode ( achievement ) }
75
for achievement in type . achievement_set . f i l t e r ( s t u d e n t=
s t u d e n t . id )
76
]
77
}
78
79
)
return a c t i v i t y _ t y p e s
80
81
c l a s s Meta :
82
model = A p p l i c a t i o n
83
fields = [
84
’ activity_type ’ ,
85
’ event ’ ,
86
’ student ’ ,
87
’ status ’ ,
88
’ feedback ’ ,
89
’ achievements ’
90
]
91
86
92
93
94
c l a s s ApplicationShowForm ( forms . Form ) :
CHOICES = (
95
( ’ approve ’ , ’Принят о ’ , ) ,
96
( ’ r e j e c t e d ’ , ’Отклон е но ’ , ) ,
97
( ’ w a i t i n g ’ , ’Ожидани е ’ , )
98
)
99
100
f e e d b a c k = forms . C h a r F i e l d ( )
s t a t u s = forms . C h o i c e F i e l d ( w i d g e t=forms . S e l e c t , c h o i c e s=CHOICES)
101
102
103
104
c l a s s ActivityTypeForm ( forms . Form ) :
name = forms . C h a r F i e l d ( max_length =50)
105
106
107
108
c l a s s AchievementCreateForm ( forms . ModelForm ) :
s c a n = forms . F i l e F i e l d ( w i d g e t=forms . F i l e I n p u t ( a t t r s ={ ’ a c c e p t ’ : ’ a p p l i c a t i o n
/ pdf ’ } ) )
109
activity_types = [ ]
110
for a c t i v i t y _ t y p e in A c t i v i t y T y p e . o b j e c t s . a l l ( ) . p r e f e t c h _ r e l a t e d ( ’
achievementtype_set ’ ) :
111
a c t i v i t y _ t y p e s . append (
112
{
113
’ i d ’ : a c t i v i t y _ t y p e . id ,
114
’ name ’ : a c t i v i t y _ t y p e . name ,
115
’ achievement_types ’ : [
116
{ ’ i d ’ : achievement_type . id , ’ name ’ : achievement_type . name}
117
for achievement_type in a c t i v i t y _ t y p e . a c h i e v e m e n t t y p e _ s e t .
all ()
118
]
119
120
121
}
)
a c t i v i t y _ t y p e s = j s o n . dumps ( a c t i v i t y _ t y p e s )
122
123
c l a s s Meta :
124
model = Achievement
125
fields = [
126
’ activity_type ’ ,
127
’ achievement_type ’ ,
128
’ obtain_date ’ ,
87
129
130
’ scan ’
]
131
132
133
c l a s s AchievementUpdateForm ( forms . ModelForm ) :
134
s c a n = forms . F i l e F i e l d ( r e q u i r e d=F a l s e )
135
activity_types = [ ]
136
for a c t i v i t y _ t y p e in A c t i v i t y T y p e . o b j e c t s . a l l ( ) . p r e f e t c h _ r e l a t e d ( ’
achievementtype_set ’ ) :
137
a c t i v i t y _ t y p e s . append (
138
{
139
’ i d ’ : a c t i v i t y _ t y p e . id ,
140
’ name ’ : a c t i v i t y _ t y p e . name ,
141
’ achievement_types ’ : [
142
{ ’ i d ’ : achievement_type . id , ’ name ’ : achievement_type . name}
143
for achievement_type in a c t i v i t y _ t y p e . a c h i e v e m e n t t y p e _ s e t .
all ()
144
]
145
146
147
}
)
a c t i v i t y _ t y p e s = j s o n . dumps ( a c t i v i t y _ t y p e s )
148
149
c l a s s Meta :
150
model = Achievement
151
fields = [
152
’ activity_type ’ ,
153
’ achievement_type ’ ,
154
’ obtain_date ’ ,
155
’ scan ’
156
]
Листинг studentship/forms.py
1
# −*− coding : utf −8 −*−
2
3
from s c i . models import U s e r P r o f i l e
4
from s t u d e n t s h i p . models import Event
5
from s t u d e n t . models import Student
6
from django . c o r e . e x c e p t i o n s import P e r m i s s i o n D e n i e d
7
from d a t e t i m e import d a t e
8
88
9
10
11
12
13
14
c l a s s EmployeeAccessMixin ( object ) :
def d i s p a t c h ( s e l f , * a r g s , ** kwargs ) :
i f not U s e r P r o f i l e . o b j e c t s . f i l t e r ( owner= s e l f . r e q u e s t . u s e r . pk ) . e x i s t s ( ) :
rais e P e r m i s s i o n D e n i e d
return super ( EmployeeAccessMixin , s e l f ) . d i s p a t c h ( * a r g s , ** kwargs )
15
16
17
18
19
20
21
c l a s s S t u d e n t A c c e s s M i x i n ( object ) :
def d i s p a t c h ( s e l f , * a r g s , ** kwargs ) :
i f not Student . o b j e c t s . f i l t e r ( owner= s e l f . r e q u e s t . u s e r . pk ) . e x i s t s ( ) :
rais e P e r m i s s i o n D e n i e d
return super ( StudentAccessMixin , s e l f ) . d i s p a t c h ( * a r g s , ** kwargs )
22
23
24
25
26
c l a s s EventStatusMixin ( object ) :
def get_context_data ( s e l f , * a r g s , ** kwargs ) :
c o n t e x t = super ( EventStatusMixin , s e l f ) . get_context_data ( * a r g s , **
kwargs )
27
e v e n t s = Event . o b j e c t s . e x t r a ( where =[" begin_date >=’"+d a t e . today ( ) .
s t r f t i m e ( "%Y−%m−%d" )+" ’ ␣OR␣ end_date ␣>=’"+d a t e . today ( ) . s t r f t i m e ( "%Y−%
m−%d" )+" ’ ␣AND␣ s t a t u s =’ open ’ " ] )
28
event_flag = 0
29
event_object = [ ]
30
for n in e v e n t s :
31
i f n . begin_date <= d a t e . today ( ) <= n . end_date :
32
event_flag = 1
33
event_object = n
34
e l i f ( n . begin_date − d a t e . today ( ) ) . days <= 7 :
35
event_flag = 2
36
e v e n t _ o b j e c t = ( n . begin_date − d a t e . today ( ) ) . days
37
context [ ’ event_flag ’ ] = event_flag
38
context [ ’ event_object ’ ] = event_object
39
return c o n t e x t
Листинг studentship/mixins.py
89
1/--страниц
Пожаловаться на содержимое документа