Пособие по языку Python 3
Данная книга является кратким и информативным пособием с большим количеством примеров по языку Python версии 3, по структуре разбита на три главы, разделенные по разделам.
Главы этой книги я показывал людям как имевшим опыт в программировании, так и совершенно с ним не знакомых. Материал был приведен к очень простому пониманию, и может быть легко усвоен человеком без знаний программирования вообще.
Первая глава посвящена общим возможностям и синтаксису конструкций языка Python.
Вторая глава посвящена графическим приложениям.
Третья глава посвящена django.
Данную книгу я посвящаю своей семье. Благодаря их терпению я смог выделить время для написания и составления примеров.
В данной книге я по минимуму буду «разводить воду», больше будет упор на практические примеры, чтобы донести возможности языка. Все примеры выполнялись под операционной системой Windows 7, но и без проблем применяемы мной в работе и на ОС FreeBSD и Linux.
Взять дистрибутив можно с официального сайта: https://www.python.org/
Данное пособие написано автором проекта http://snakeproject.ru/ Козловым Михаилом, Вы можете посредством обратной связи на сайте оставить отзыв или предложение.
Оглавление
1. Вводная часть
1.0 Введение
1.1 Первая программа
1.2 Примеры с выводом на экран
1.3 Переменные и типы данных
1.4 Арифметические операторы
1.5 Интерактивный ввод
1.6 Работа со строками
1.7 Списки и кортежи
1.8 Циклы и условия
1.9 Функции
2.0 Базовые навыки работы с модулями.
2.1 Работа с файлами
2.2 Работа с ftp
2.3 Регулярные выражения
2.4 Прехват ошибки(try-except)
2.5 Встроенные функции
2.6 Основы ООП
2.7 Сокеты(пример простого сетевого приложения)
2.8 Основы работы с базами данных(sqlite)
2. Графические приложения
2.0 PyQt: Знакомство
2.1 PyQt : Знакомство в ООП стиле
2.2 PyQt : Отцентровка, messagebox, контекстная подсказка
2.3 Визуальные эффекты, включение виджетов, выход из программы
2.4 PyQt : Позиционирование, буфер обмена
2.5 PyQt: меню, панель задач, строка состояния
2.6 PyQt : простой текстовой редактор, диалоговые окна
3. Основы django
3.0 Установка django на примере windows 7
3.1 Простое приложение, простая модель
3.2 Изменения в базе данных
3.3 Админка
3.4 Сессии
3.5 Запросы и чистый SQL
3.6 Простые формы
1. Вводная часть
1.0 Введение
Итак, поехали! Язык Python в изучении невероятно прост, после установки дистрибутива я буду работать либо посредством интерактивной среды разработки IDLE (Вы можете например найти ее в «пуске»), либо писать в скриптах с расширением .py или .pyw (варианты для отладки и без).
1.1 Первая программа
Первая «классическая программа» с выводом строки на экран:
>>> print("Hello World!")
Hello World!
1.2 Примеры с выводом на экран
>>> 1+34
35
>>> print("123 "+" 456")
123 456
Примеры с форматированием вывода(%s,%d,%f для работы со строками, целыми и числами с плавающей точкой):
>>> print("%s and %s" % ("str1", "str2"))
str1 and str2
>>> print("%12d and %0.2f" % (2014, 23.1234))
2014 and 23.12
1.3 Переменные и типы данных
В Python переменные слаботипизированы, т.е. переменные имеют динамическую типизацию. В ходе программы переменная может принимать различные типы данных.
Частоиспользуемые типы данных в Python:
Категория |
Тип |
Описание |
Числа |
int |
целые |
|
float |
с плавающей точкой |
|
bool |
логические(true\false) |
|
complex |
комплексные |
Последовательности |
str |
строки |
|
list |
списки |
|
typle |
кортежи |
None |
Type(None) |
пустой объект |
Рассмотрим примеры объявления переменных и работы с ними.
>>> per = "AnyString"
>>> perNew = "NewString"
>>> perMix = per+" "+perNew
>>> perMix
'AnyString NewString'
>>> per*3
'AnyStringAnyStringAnyString'
>>> per[3]
'S'
>>> per[3:5]
'St'
1.4 Арифметические операторы
Рассмотрим примеры с арифметическими выражениями.
>>> 2+2 #Сложение
4
>>> 5-3 #Вычитание
2
>>> 8/2 #Деление
4.0
>>> 45*3 #Умножение
135
>>> (5+5)*5 #Скобки
50
>>> 13%2 #Деление по модулю
1
>>> 9//2 #Деление с усечением
4
1.5 Интерактивный ввод
>>> a = input()
AnyString
>>> a
'AnyString'
1.6 Работа со строками
Поиск и замена в строке
>>> 'первый и второй'.replace('второй', 'первый')
'первый и первый'
Длина строки
>>> len(per)
9
Вывод на нескольких строках
>>> print("""
String 1 1 1
String 2 2 2
String 3 3 3
""")
String 1 1 1
String 2 2 2
String 3 3 3
#Объединение строк используя «разделитель»
>>> s = ","
>>> s1 = "1"; s2 = "2"; s3 = "3";
>>> st = [s1,s2,s3]
>>> s.join(st)
'1,2,3'
#Перевод в большой и малые регистры
>>> s = "aBcD"
>>> s.upper()
'ABCD'
>>> s.lower()
'abcd'
#Проверка на:
>>> s = "123123"
#Все ли цифровые символы в строке
>>> s.isdigit()
True
#Все ли буквенные символы в строке
>>> s.isalpha()
False
#Все ли буквенно-цифровые символы в строке
>>> s.isalnum()
True
1.7 Списки и кортежи
Списки это фактически массивы, но типы значений могут различаться.
Кортежи по сути являются неизменяемыми конструкциями типа «ключ-значение».
Примеры объявления и распространенных действий со списками.
#Объявление
>>> a = ['1', '2', 1, 2]
>>> a
['1', '2', 1, 2]
#Обращение
>>> a[0]
'1'
>>> a[1:3]
['2', 1]
>>> a[2] = 123
>>> a[1:3]
['2', 123]
#Изменить значение
>>> a[:0] = [1212, '222']
>>> a
[1212, '222', '1', '2', 123, 2]
#Очистить
>>> a[:] = []
>>> a
[]
#Длина
>>> len(a)
0
#Добавление элемента
>>> a.append('555')
>>> a
['555']
#Варианты удаления элементов
>>> a.remove('555')
>>> del a[0]
#Посчитаем количество вхождений в список
>>> a = ['1', '2', 1, 2]
>>> a.count(2)
1
>>> a = ['1', '2', 1, 2, 2, 2, 3, 3]
>>> a.count(2)
3
#Применение некоторой функции ко всем элементам списка - map()
>>> a1 = [1, 2, 3, 4, 5, 6]
>>> a2 = [6, 5, 4, 3, 2, 1]
>>> print map(lambda x, y: x*y, a1, a2)
[6, 10, 12, 12, 10, 6]
#Удалим элемент по позиции
>>> a.pop(2)
1
>>> a
['1', '2', 2, 2, 2, 3, 3]
Примеры объявления и работы с кортежами.
#Объявление
>>> per = {'name': 'ira', 'lastname': 'lomova'}
#Добавить ключ и значение
>>> per['age'] = 25
#Обращение к значению ключа
>>> per['name']
'ira'
#Проверка на присутствие в кортеже ключа
>>> 'name' in per
True
#Перебор значений и ключей
>>> for key, value in per.items():
print(key, value)
name ira
age 25
lastname lomova
1.8 Циклы и условия
Рассмотрим конструкции циклов while, for и оператора проверки условия(оператора ветвления)
While(«выполняй пока условие верно»)
>>> a=1
>>> while a!=3:
print(a)
a = a+1
1
2
>>> a=1
>>> while a!=3:
print(a, end=' ')
a=a+1
1 2
For(перебирает значения)
>>> a = ['1', '2', '3']
>>> for x in a:
print(x)
1
2
3
#Вариант с генератором чисел range
>>> for i in range(3):
print(i)
0
1
2
#Вариант с генератором чисел range с определенным диапазоном чисел
>>> for i in range(3, 7):
print(i)
3
4
5
6
IF(проверка условия)
Имеет необязательные блоки elif и else. Количество дополнительных проверок elif может быть несколько или одно, блок else отработает в ситуации, когда ни одно условие не выполнилось.
>>> per = int(input('Введи число: '))
Введи число: 123
>>> if per > 100:
print('per больше 100')
elif per < 100:
print('per меньше 100')
else:
print('per равно 0')
per больше 100
1.9 Функции
Функции могут содержать инструкцию return, которая возвращает значение(его можно например занести в переменную).
В другом случае функция может использоваться без ключевого слова return и отрабатывать как «кусок кода» или как «хранимая процедура».
Помимо этого функция может принимать аргументы, иметь обязательные и аргументы с уже заданными значениями.
Примеры функций.
#Объявление функции с одним обязательным аргументом
#return не используется
>>> def func(x):
if x>0:
print('x > 0')
else:
print('x <= 0')
#Вызов с передачей аргумента
>>> func(3)
x > 0
#return возвратит значение, которое можно записать в переменную
>>> def func(x):
if x>0:
z = x + 1
return z
else:
z = x - 1
return z
>>>per = func(3)
>>>per
4
Примеры с обязательными и необязательными аргументами.
>>> def func(a, b, c=4): # c - необязательный аргумент
return a + b + c
>>> func(1, 2) # a = 1, b = 2, c = 4 (по умолчанию)
7
>>> func(1, 2, 3) # a = 1, b = 2, c = 3
6
>>> func(a=1, b=1) # a = 1, b = 1, c = 4
6
Произвольное количество аргументов.
>>> def func(*args):
return args
>>> func(1,2,3,4,5)
(1,2,3,4,5)
Произвольное количество именованных аргументов.
>>> def func(**kwargs):
return kwargs
>>> func(a=1, b=2, c=3)
{'a': 1, 'b': 2, 'c': 3}
2.0 Базовые навыки работы с модулями.
В питоне изначально присутствует большое количество модулей для работы например с регулярными выражениями или операционной системой.
Модули представлены объектами-модулями, атрибутами которох являются имена, определенные в модулях
Модули по тематике из стандартной библиотеки Python:
Сервисы периода выполнения: sys, atexit, copy, traceback, math, cmath, random, time, calendar, datetime, sets, array, struct, itertools, locale, gettext.
Поддержка цикла разработки: pdb, hotshot, profile, unittest, pydoc. Пакеты docutils, distutils.
Взаимодействие с ОС (файлы, процессы): os, os.path, getopt, glob, popen2, shutil, select, signal, stat, tempfile.
Обработка текстов: string, re, StringIO, codecs, difflib, mmap, sgmllib, htmllib, htmlentitydefs. Пакет xml.
Многопоточные вычисления: threading, thread, Queue.
Хранение данных. Архивация: pickle, shelve, anydbm, gdbm, gzip, zlib, zipfile, bz2, csv, tarfile.
Платформо-зависимые модули. Для UNIX: commands, pwd, grp, fcntl, resource, termios, readline, rlcompleter. Для Windows: msvcrt, _winreg, winsound.
Поддержка сети. Протоколы Интернет: cgi, Cookie, urllib, urlparse, httplib, smtplib, poplib, telnetlib, socket, asyncore. Примеры серверов: SocketServer, BaseHTTPServer, xmlrpclib, asynchat.
Поддержка Internet. Форматы данных: quopri, uu, base64, binhex, binascii, rfc822, mimetools, MimeWriter, multifile, mailbox. Пакет email.
Для Python: parser, symbol, token, keyword, inspect, tokenize, pyclbr, py_compile, compileall, dis, compiler.
Графический интерфейс: Tkinter.
В данном разделе будет показано, как импортировать и получать справку по модулям.
#Импортировать модуль(в нашем примере модуль sys)
>>> import sys
#Посмотрим пути, где питон смотрит наличие модулей
#Тут мы уже обращаемся к функционалу модуля
>>> sys.path
['', 'C:\Python33\Lib\idlelib', 'c:\Python27\egg\Lib\site-packages', 'c:\Python27\Lib\site-packages', 'C:\Windows\system32\python33.zip', 'C:\Python33\DLLs', 'C:\Python33\lib', 'C:\Python33', 'C:\Python33\lib\site-packages']
#Посмотрим, что есть в модуле sys
>>> dir(sys)
['__displayhook__', '__doc__', '__excepthook__', '__loader__', '__name__', '__package__', '__stderr__', '__stdin__', '__stdout__', '_clear_type_cache', '_current_frames', '_debugmallocstats', '_getframe', '_home', '_mercurial', '_xoptions', 'api_version', 'argv', 'base_exec_prefix', 'base_prefix', 'builtin_module_names', 'byteorder', 'call_tracing', 'callstats', 'copyright', 'displayhook', 'dllhandle', 'dont_write_bytecode', 'exc_info', 'excepthook', 'exec_prefix', 'executable', 'exit', 'flags', 'float_info', 'float_repr_style', 'getcheckinterval', 'getdefaultencoding', 'getfilesystemencoding', 'getprofile', 'getrecursionlimit', 'getrefcount', 'getsizeof', 'getswitchinterval', 'gettrace', 'getwindowsversion', 'hash_info', 'hexversion', 'implementation', 'int_info', 'intern', 'last_traceback', 'last_type', 'last_value', 'maxsize', 'maxunicode', 'meta_path', 'modules', 'path', 'path_hooks', 'path_importer_cache', 'platform', 'prefix', 'setcheckinterval', 'setprofile', 'setrecursionlimit', 'setswitchinterval', 'settrace', 'stderr', 'stdin', 'stdout', 'thread_info', 'version', 'version_info', 'warnoptions', 'winver']
#Пример импортирования фукционала из модуля
>>> from sys import *
#После импортирования можно обращаться напрямую, а не через точку
>>> version
'3.3.2 (v3.3.2:d047928ae3f6, May 16 2013, 00:03:43) [MSC v.1600 32 bit (Intel)]'
#Посмотреть справку по модулю или отдельному функционалу:
>>> help(os)
>>> help(os.system)
2.1 Работа с файлами
#Копировать файл
>>> import shutil
>>> shutil.copyfile('C:/test/test.txt', 'C:/test/newtest.txt')
'C:/test/newtest.txt'
#Откроем файл на запись.
>>> f = open('C:/test/test.txt', 'w')
#Запишем в него несколько строк с переносом на другую строку "\r\n".
>>> f.write('string1 \r\n')
10
>>> f.write('string2')
7
#Закроем файл
>>> f.close()
#Пример с чтением файла по количеству байт, и "прочитать все"
>>> f = open('C:/test/test.txt', 'r')
>>> f.read(7)
'string1'
>>> f.read()
' \n\nstring2'
>>> f.close()
#Пример с редактированием файла по позиции байт
>>> f = open('C:/test/test.txt', 'w')
>>> f.write('abcdef')
6
>>> f.seek(3)
3
>>> f.write('CD')
2
>>> f.close()
>>> f = open('C:/test/test.txt', 'r')
>>> f.read()
'abcCDf'
#Еще пример чтения из файла
>>> f = open('C:/test/test.txt', 'w')
>>> f.write('string \r\n')
9
>>> f.write('string \r\n')
9
>>> f.write('string \r\n')
9
>>> f.close()
>>> f = open('C:/test/test.txt', 'r')
>>> f.readline()
'string \n'
>>> f.readlines()
['\n', 'string \n', '\n', 'string \n', '\n']
>>> f.close()
#Замена определенной строки на значение
>>> f = open('C:/test/test.txt', 'r')
>>> strings = f.readlines()
>>> f.close()
>>> strings[0] = 'STRING'
>>> f = open('C:/test/test.txt', 'w')
>>> f.writelines(strings)
>>> f.close()
2.2 Работа с ftp
#Импортируем библиотеки
>>> import os
>>> from ftplib import FTP
#Данные для подключения
>>> ftpresource = '192.168.10.102'
>>> ftplogin = 'anonymous'
>>> ftppassword = 'yourpass'
>>> todir = 'C:/2'
#Параметры подключения
>>> ftp = FTP(ftpresource)
>>> ftp.login(ftplogin, ftppassword)
'230 Anonymous user logged in.'
>>> ftp.cwd('/')
'250 CWD command successful.'
#Скачиваем все файлы с расширением .cfg
>>> for files in ftp.nlst('*.cfg'):
ftp.retrbinary('RETR '+files, open(os.path.join(todir, files), 'wb').write, 1024)
'226 Transfer complete.'
'226 Transfer complete.'
'226 Transfer complete.'
#Закрываем соединение
>>> ftp.close()
2.3 Регулярные выражения
Регулярные выражения модуль - re
Символы для шаблонов:
"." Любой символ
"^" Начало строки
"$" Конец строки
"*" Повторение фрагмента нуль или более раз
"+" Повторение фрагмента один или более раз
"?" Предыдущий фрагмент либо присутствует, либо отсутствует
"{m,n}" Повторение предыдущего фрагмента от m до n раз включительно
"[...]" Любой символ из набора в скобках.
"[^...]" Любой символ не из набора в скобках
"" Обратная косая черта отменяет специальное значение следующего за ней символа
"|" Фрагмент справа или фрагмент слева
"*?" Повторение фрагмента нуль или более раз
"+?" Повторение фрагмента один или более раз
"{m,n}?" Повторение предыдущего фрагмента от m до n раз включительно
#Импортируем модуль
>>> import re
#Поиск всех совпадений в строке
>>> re.findall(r"[0-9]+", "123 abc 456AAA 789 def")
['123', '456', '789']
#Разбивает строку на подстроки, разделенные подстроками, заданными шаблоном
>>> re.split(r"[-_|/]", "123-abc_456AAA/789|def")
['123', 'abc', '456AAA', '789', 'def']
2.4 Прехват ошибки(try-except)
#Контроль ошибок
>>> try:
zxc /cxz
except:
print "Error"
Error
2.5 Встроенные функции
В этом разделе приведем список встроенных функций и дадим ресурс, где можно разобрать функциональную часть каждой из функций.
Встроенные функции
Тут можно посмотреть описание: http://ru.wikiversity.org/wiki/Программирование_и_научные_вычисления_на_языке_Python/§4/Приложение
Встроенные функции по тематике:
Функции преобразования типов и классы: coerce, str, repr, int, list, tuple, long, float, complex, dict, super, file, bool, object
Числовые и строковые функции: abs, divmod, ord, pow, len, chr, unichr, hex, oct, cmp, round, unicode
Функции обработки данных: apply, map, filter, reduce, zip, range, xrange, max, min, iter, enumerate, sum
Функции определения свойств: hash, id, callable, issubclass, isinstance, type
Функции для доступа к внутренним структурам: locals, globals, vars, intern, dir
Функции компиляции и исполнения: eval, execfile, reload, __import__, compile
Функции ввода-вывода: input, raw_input, open
Функции для работы с атрибутами: getattr, setattr, delattr, hasattr
Функции-"украшатели" методов классов: staticmethod, classmethod, property
Прочие функции: buffer, slice
2.6 Основы ООП
ООП
Все данные представляются объектами.
Программу можно составить как набор взаимодействующих объектов, посылающих друг другу сообщения.
Каждый объект имеет собственную часть памяти и может состоять из других объектов.
Каждый объект имеет тип.
Все объекты одного типа могут принимать одни и те же сообщения (и выполнять одни и те же действия).
#Минимально возможное определение класса
>>> class A:
pass
В Python члены класса называются атрибутами, функции класса — методами, поля класса — свойствами.
Определения методов аналогичны определениям функций, методы всегда имеют первый аргумент, называемый по широко принятому соглашению self:
>>> class A:
def m1(self, x):
print (x)
Создание экземпляра класса, изменение атрибутов и вызов метода
>>> class A:
attr1 = 0
attr2 = 0
def m(self, x):
print (self.attr1 * self.attr2 * x)
>>> A = A()
>>> A.attr1 = 2
>>> A.attr2 = 3
>>> A.m(10)
60
Конструктор класса - специальный метод, который не требует вызова, запускается при вызове класса автоматически, носит имя __init__
>>> class B:
def __init__(self,a,b):
self.fname = a
self.lname = b
self.job = "Director: "+self.fname+" "+self.lname
def m(self,d):
self.department = self.job+" work in " + d + " dept"
print (self.department)
>>> B = B("Mike", "Jagger")
>>> B.m("IT")
Director: Mike Jagger work in IT dept
2.7 Сокеты(пример простого сетевого приложения)
Для начала немного теории о сетевой модели
Уровни модели OSI:
Физический
Поток битов, передаваемых по физической линии. Определяет параметры физической линии.
Канальный (Ethernet, PPP, ATM и т.п.)
Кодирует и декодирует данные в виде потока битов, справляясь с ошибками, возникающими на физическом уровне в пределах физически единой сети.
Сетевой (IP)
Маршрутизирует информационные пакеты от узла к узлу.
Транспортный (TCP, UDP и т.п.)
Обеспечивает прозрачную передачу данных между двумя точками соединения.
Сеансовый
Управляет сеансом соединения между участниками сети. Начинает, координирует и завершает соединения.
Представления
Обеспечивает независимость данных от формы их представления путем преобразования форматов. На этом уровне может выполняться прозрачное (с точки зрения вышележащего уровня) шифрование и дешифрование данных.
Приложений (HTTP, FTP, SMTP, NNTP, POP3, IMAP и т.д.)
Поддерживает конкретные сетевые приложения. Протокол зависит от типа сервиса.
Итак, пример простой передачи и возврата строки по сети.(приложение типа обмен данными между клиентом и сервером)
#Модуль socket
import socket
#Создание сокета
sock = socket.socket()
#Свяжем сокет с хостом и портом с помощью метода bind
sock.bind(('', 9999))
#С помощью метода listen запустим для сокета режим прослушивания.
sock.listen(1)
#Принимаем подключение с помощью метода accept, который возвращает кортеж с двумя элементами: новый сокет и адрес клиента.
conn, addr = sock.accept()
#Для получения данных воспользуемся методом recv, в качестве аргумента принимает количество байт. Будем читать 1024 байт.
#Получаем данные от клиента, и возвращаем приветствие
data = conn.recv(1024)
conn.send("Server:Hello, client!")
#Закрываем соединение
conn.close()
Файл server.py:
import socket
sock = socket.socket()
sock.bind(('', 9999))
sock.listen(1)
conn, addr = sock.accept()
print ('Client address:', addr)
data = conn.recv(1024)
print (data)
s = "Server:Hello, client!"
conn.send(bytes(s, 'UTF-8'))
conn.close()
Файл client.py
import socket
sock = socket.socket()
sock.connect(('localhost', 9999))
s = 'Client:Hello, server!'
sock.send(bytes(s, 'UTF-8'))
data = sock.recv(1024)
sock.close()
print (data)
Запустить можно например так:
Вызываем два окошка «cmd»
Пишем путь до питона и через пробел путь до скрипта
Сначала запускаем server.py
Затем client.py
2.8 Основы работы с базами данных(sqlite)
#sqlite3 простейший пример работы с базой данных из файла
>>> import sqlite3
#Соединение с базой методом connect
>>> conn = sqlite3.connect('C:\test\base.db')
#Соединение в результате успешного вызова функции connect(), имеет следующие методы:
#close() Закрывает соединение с базой данных.
#commit() Завершает транзакцию.
#rollback() Откатывает начатую транзакцию.
#cursor() Возвращает объект-курсор, использующий данное соединение.
>>> c = conn.cursor()
#execute - исполняет запрос к базе данных. Примеры:
#Создание таблицы
c.execute('''create table stocks (date text, trans text, symbol text, qty real, price real)''')
#Вставка значений
c.execute("""insert into stocks values ('2006-01-05','BUY','RHAT',100,35.14)""")
#Подтверждаем изменения
conn.commit()
#Сделаем выборку
>>> conn = sqlite3.connect('C:\test\base.db')
>>> c = conn.cursor()
>>> c.execute('select * from stocks order by price')
<sqlite3.Cursor object at 0x028517E0>
>>> for row in c:
print(row)
(u'2006-01-05', u'BUY', u'RHAT', 100.0, 35.14)
#Закрываем соединение
c.close()
2. Графические приложения
2.0 PyQt: Знакомство
Использована версия 4.
Официальный сайт: http://www.riverbankcomputing.com/software/pyqt/download5
PyQt4 является инструментом создания GUI приложений, представляет симбиоз языка Python и библиотеки Qt.
Модули в PyQt4:
QtCore предназначен для работы со файлами, каталогами, временем, URL, типами данных, потоками, процессами.
QtGui хранит внутри себя графические компоненты и взаимодействующие с ними классы. (кнопки, цвета, шрифты, окна, панели, изображения)
QtNetwork хранит классы сетевого программирования. Позволяет создать TCP/IP, UDP клиентские и серверные приложения.
QtSql хранит классы для работы с базами данных.
QtXml хранит классы для работы с xml.
QtSvg хранит компоненты для работы с масштабируемой векторной графикой (SVG),(двумерная графикаи графическими приложениями XML).
QtOpenGL предназначен для бесшовной интеграции QtGui и библиотеки OpenGL.
Первая «классическая программа» Hello World!
#Подключаем библиотеки, необходимые для создания программы
import sys
from PyQt4 import QtCore, QtGui
#Обязательное создание экземпляра основного приложения и передача параметров командной строки
app = QtGui.QApplication(sys.argv)
#Создаем объект окна, который наследует nрактически все классы, реализующие комnоненты графического интерфейса.
widget = QtGui.QWidget()
#Изменяем размеры окна с помощью метода resize()
widget.resize(300, 150)
#Зададим заголовок программы
widget.setWindowTitle('MyProgramm')
#Создадим надпись(можно использовать теги HTML)
label = QtGui.QLabel("<center>Hello!</center>")
#Создадим кнопку и присвоем ей надпись
btn = QtGui.QPushButton("CloseWindow")
#Создадим контейнер, в который помести надпись и кнопку
box = QtGui.QVBoxLayout()
box.addWidget(label)
box.addWidget(btn)
#Добавим контейнер в основное окно
widget.setLayout(box)
#Обработчик сигнала, генерируемый nри нажатии кноnки.
#Аргументы:
#btn - объект, генерируещий сигнал
#QtCore.SIGNAL("clicked()") - название сигнала
#QtGui.qApp - объект, nринимающий сигнал
#QtCore.SLOT("quit()") - метод объекта, который будет вызван nри вызове события
QtCore.QObject.connect(btn, QtCore.SIGNAL("clicked()"), QtGui.qApp, QtCore.SLOT("quit()"))
#Отобразим окно прогаммы с помощью метода show()
widget.show()
#Основной цикл обработки событий программы, получает и обрабатывает события окна системы, передает их виджетам.
#По окончании работы основного цикла, программа закончит работу. sys.exit() передает информацию ОС об оканчании работы приложения.
sys.exit(app.exec_())
#Для того, чтоб не появлялась отладочная консоль при запуске программы, расширение скрипта переименуйте в .pyw
2.1 PyQt : Знакомство в ООП стиле
Напишем вариант первой программы с помощью ООП стиля:
import sys
from PyQt4 import QtCore, QtGui
#ООП-стиль создания окна
#Создаем класс Prog
#Объявляем класс Prog производным от класса QtGui.QWidget
#Вызываем конструктор класса-родителя, передаем указатель на класс Prog, и указатель на родительский класс
class Prog(QtGui.QWidget):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
#Зададим расположение окна и размеры
self.setGeometry(650, 450, 150, 150)
#Эти конструкции мы разбирали на прошлом уроке
self.label = QtGui.QLabel("<center>Hello!</center>")
self.btn = QtGui.QPushButton("CloseWindow")
self.box = QtGui.QVBoxLayout()
self.box.addWidget(self.label)
self.box.addWidget(self.btn)
self.setLayout(self.box)
self.connect(self.btn, QtCore.SIGNAL("clicked()"), QtGui.qApp.quit)
app = QtGui.QApplication(sys.argv)
#Создаем экземпляр класса
prog = Prog()
#Устанавливаем свойства в т.ч. добавим иконку в окошко
prog.setWindowTitle("MyProgramm")
prog.setWindowIcon(QtGui.QIcon('lesson2.png'))
prog.show()
sys.exit(app.exec_())
2.2 PyQt : Отцентровка, messagebox, контекстная подсказка
import sys
from PyQt4 import QtCore, QtGui
class Prog(QtGui.QWidget):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
#Задаем размеры окна и вызываем функцию отцентровки по дисплею
self.setWindowTitle('center')
self.resize(350, 250)
self.center()
#Эти конструкции мы разбирали на прошлом уроке
self.label = QtGui.QLabel("<center>Hello!</center>")
self.btn = QtGui.QPushButton("Edit setToolTip")
self.box = QtGui.QVBoxLayout()
self.box.addWidget(self.label)
self.box.addWidget(self.btn)
self.setLayout(self.box)
#По клику вызовем связь с функцией(изменим подсказку)
self.connect(self.btn, QtCore.SIGNAL("clicked()"), Prog.func)
#Устанавливаем шрифт и размер подсказки
QtGui.QToolTip.setFont(QtGui.QFont('verdana', 14))
#При закрытии программы выведем окно с сообщением
def closeEvent(self, event):
reply = QtGui.QMessageBox.question(self, 'Message', "Are you sure to quit?", QtGui.QMessageBox.Yes, QtGui.QMessageBox.No)
if reply == QtGui.QMessageBox.Yes:
event.accept()
else:
event.ignore()
#Функция изменяющая подсказку
def func():
prog.label.setToolTip('Push button new!')
#Функция, распологающая окно по центру дисплея, вычисляя его длинуширину
def center(self):
screen = QtGui.QDesktopWidget().screenGeometry()
size = self.geometry()
self.move((screen.width()-size.width())/2, (screen.height()-size.height())/2)
app = QtGui.QApplication(sys.argv)
#Создаем экземпляр класса
prog = Prog()
#Устанавливаем контекстную подсказку
prog.label.setToolTip('Push button!')
prog.show()
sys.exit(app.exec_())
2.3 Визуальные эффекты, включение виджетов, выход из программы
Рассмотрим:
1. Включение\Выключение виджета
2. Имитацию процесса со строкой прогресса(не забудьте создать произвольный(например 150 на 50 пикселей серый фон) png файл для фона со строкой прогресса)
3. Скрыть\показать окно программы
4. Прозрачность
5. Смену цветов
6. Закрытие программы
from PyQt4 import QtCore, QtGui
from PyQt4.QtCore import Qt, SIGNAL
import sys, time
class Prog(QtGui.QWidget):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.resize(350, 250)
self.label = QtGui.QLabel("<center>Hello!</center>")
self.btn = QtGui.QPushButton("On\Off label")
self.btnProgress = QtGui.QPushButton("Progress")
self.btnVis = QtGui.QPushButton("Visible")
self.btnOpac = QtGui.QPushButton("Opacity")
self.btnColor = QtGui.QPushButton("Color")
self.btnClose = QtGui.QPushButton("Close")
self.box = QtGui.QVBoxLayout()
self.box.addWidget(self.label)
self.box.addWidget(self.btn)
self.box.addWidget(self.btnProgress)
self.box.addWidget(self.btnVis)
self.box.addWidget(self.btnOpac)
self.box.addWidget(self.btnColor)
self.box.addWidget(self.btnClose)
self.setLayout(self.box)
self.connect(self.btn, QtCore.SIGNAL("clicked()"), self.des)
self.connect(self.btnProgress, QtCore.SIGNAL("clicked()"), self.desProg)
self.connect(self.btnVis, QtCore.SIGNAL("clicked()"), self.desVis)
self.connect(self.btnOpac, QtCore.SIGNAL("clicked()"), self.opac)
self.connect(self.btnColor, QtCore.SIGNAL("clicked()"), self.color)
self.connect(self.btnClose, QtCore.SIGNAL("clicked()"), self, QtCore.SLOT("close()"))
#closeEvent()
ev = 0
def closeEvent(self, event):
if self.ev == 3:
event.accept()
elif self.ev < 3:
event.ignore()
self.ev += 1
#Color
def color(self):
pal = self.palette()
pal.setColor(QtGui.QPalette.Normal, QtGui.QPalette.Window, QtGui.QColor("DarkGreen"))
self.setPalette(pal)
self.label.setStyleSheet("background-color: #ffffff;")
#Opacity widget
ix = 0.0
def opac(self):
while self.ix <= 1.0:
time.sleep(1)
self.setWindowOpacity(self.ix)
self.ix += 0.25
#visible widget
def desVis(self):
if self.label.isVisible() == True:
self.label.setVisible(False)
elif self.label.isVisible() == False:
self.label.setVisible(True)
#ON\OFF widget
a = 1
def des(self):
if self.a == 1:
self.label.setDisabled(True)
self.a = 2
elif self.a == 2:
self.label.setDisabled(False)
self.a = 1
#inscription over the raster image (simulation progress)
def desProg(self):
splash = QtGui.QSplashScreen(QtGui.QPixmap("img.png"))
splash. showMessage ("Load data... 0%", Qt.AlignHCenter | Qt.AlignBottom, Qt.black)
splash.show()
for i in range(1, 6):
time.sleep(1)
splash.showMessage("Load data...{0}%".format(i*20), Qt.AlignHCenter | Qt.AlignBottom, Qt.black)
QtGui.qApp.processEvents()
splash.show()
splash.finish(splash)
app = QtGui.QApplication(sys.argv)
prog = Prog()
prog.show()
sys.exit(app.exec_())
2.4 PyQt : Позиционирование, буфер обмена
1 В первой части раскоментируйте блок # #Absolute position для рассмотрения абсолютного(жесткого) позиционирования.
В данном случае элементы будут располагаться жестко по координатам.
2 Во второй части раскоментируйте блок # #clipboard для рассмотрения работы с буфером обмена(изначально скопируйти в буфер любую строку или слово).
3 В третьей части посмотрите «резиновое позиционирование»(не жесткое) элементов.
В данном случае можно менять размер окна, и Вы увидите «прижимание» элементов или их расползание относительно рамок программы.
from PyQt4 import QtCore, QtGui
from PyQt4.QtCore import Qt, SIGNAL
import sys, time
class Prog(QtGui.QWidget):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
# #----------------------
# #Absolute position
# self.resize(350, 250)
# self.label = QtGui.QLabel("<center>Hello!</center>", self)
# self.btn = QtGui.QPushButton("clipboard", self)
# self.label.setGeometry(30, 30, 300, 50) #width, height, x, y
# self.btn.resize(70, 30) #width, height
# self.btn.move(20, 150) #x, y
# #----------------------
# #clipboard
# self.connect(self.btn, QtCore.SIGNAL("clicked()"), self.des)
#----------------------
#rubber position
self.label1 = QtGui.QLabel("<center>l1</center>")
self.label2 = QtGui.QLabel("<center>l2</center>")
self.label3 = QtGui.QLabel("<center>l3</center>")
self.btn1 = QtGui.QPushButton("b1")
self.btn2= QtGui.QPushButton("b2")
self.btn3= QtGui.QPushButton("b3")
#Vertical
#self.box = QtGui.QVBoxLayout()
#Horisontal
self.box = QtGui.QHBoxLayout()
self.innerBox1 = QtGui.QHBoxLayout()
self.innerBox2 = QtGui.QHBoxLayout()
#alignment=QtCore.Qt. - align:
#AlignLeft, AlignRight, AlignHcenter, AlignJustify, AlignTop, AlignBottom, AlignVcenter, AlignCenter
self.box.addWidget(self.label1, alignment=QtCore.Qt.AlignTop)
self.box.addWidget(self.label2, alignment=QtCore.Qt.AlignBottom)
self.box.addWidget(self.btn1)
self.box.addWidget(self.btn2)
self.setLayout(self.box)
#add widget on last position
self.box.addWidget(self.label3)
#add widget on defined position
self.box.insertWidget(0, self.btn3)
#Add container in container
self.innerLabel1 = QtGui.QLabel("<center>innerLabel1</center>")
self.innerLabel2 = QtGui.QLabel("<center>innerLabel2</center>")
self.innerBox1.addWidget(self.innerLabel1)
self.innerBox2.addWidget(self.innerLabel2)
self.box.addLayout(self.innerBox1)
self.box.insertLayout(0, self.innerBox2)
#Add empty space (static)
self.box.addSpacing(100)
self.box.insertSpacing(0, 100)
def des(self):
clipboard = QtGui.QApplication.clipboard()
self.label.setText(clipboard.text())
app = QtGui.QApplication(sys.argv)
prog = Prog()
prog.show()
sys.exit(app.exec_())
2.5 PyQt: меню, панель задач, строка состояния
Для иконки в меню создайте маленький файл 'exit.png'
import sys, time
from PyQt4.QtGui import *
from PyQt4 import QtGui, QtCore
class Prog(QtGui.QMainWindow):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.resize(350, 250)
self.setWindowTitle('MyProg')
self.label = QtGui.QLabel("label", self)
self.label.setGeometry(70, 70, 23, 23)
#menu
#menu icon and text
exit = QtGui.QAction(QtGui.QIcon('exit.png'), 'Exit', self)
#hot keys
exit.setShortcut('Ctrl+Q')
#signal onclick
self.connect(exit, QtCore.SIGNAL('triggered()'), QtCore.SLOT('close()'))
AnyNews1 = QtGui.QAction('AnyNews1', self)
AnyNews2 = QtGui.QAction('AnyNews2', self)
self.connect(AnyNews1, QtCore.SIGNAL('triggered()'), self.des1)
self.connect(AnyNews2, QtCore.SIGNAL('triggered()'), self.des2)
#create menu and actions
menubar = self.menuBar()
file = menubar.addMenu('&File')
news = menubar.addMenu('&News')
file.addAction(exit)
news.addAction(AnyNews1)
news.addAction(AnyNews2)
#toolbars
self.toolbar = self.addToolBar('Exit')
self.toolbar.addAction(exit)
self.toolbar.addAction(AnyNews1)
self.toolbar.addAction(AnyNews2)
def des1(self):
self.label.setStyleSheet("background-color: #ffffff;")
def des2(self):
self.label.setStyleSheet("background-color: DarkGreen;")
#statusbar
i = 1
def enterEvent(self, event):
self.statusBar().setVisible(True)
self.statusBar().showMessage('Statusbar count: {0}'.format(self.i))
self.i += 1
def leaveEvent(self, event):
self.statusBar().setVisible(False)
app = QtGui.QApplication(sys.argv)
prog = Prog()
prog.show()
sys.exit(app.exec_())
2.6 PyQt : простой текстовой редактор, диалоговые окна
import sys, time
from PyQt4.QtGui import *
from PyQt4 import QtGui, QtCore
class Prog(QtGui.QWidget):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.setWindowTitle('grid layout')
#Craete line and text area
self.Line = QtGui.QLabel('Line')
self.Text = QtGui.QLabel('Text')
self.LineEdit = QtGui.QLineEdit()
self.TextEdit = QtGui.QTextEdit()
#checkered layout, 5 - cell spacing
grid = QtGui.QGridLayout()
grid.setSpacing(5)
grid.addWidget(self.Line, 1, 0) #1 and 0 - coordinates
grid.addWidget(self.LineEdit, 1, 1)
grid.addWidget(self.Text, 3, 0)
grid.addWidget(self.TextEdit, 3, 1, 5, 1) # 5,1 - number of columns and cells
self.setLayout(grid)
#dialog window
self.button = QtGui.QPushButton('editLine', self)
grid.addWidget(self.button, 12, 1)
self.connect(self.button, QtCore.SIGNAL('clicked()'), self.editLine)
self.resize(350, 300)
def editLine(self):
text, ok = QtGui.QInputDialog.getText(self, 'Input in line', 'Enter string:')
if ok:
self.LineEdit.setText(text)
app = QtGui.QApplication(sys.argv)
prog = Prog()
prog.show()
sys.exit(app.exec_())
3 Основы Django
3.0 Установка django на примере windows 7
Примеры были написаны на Python 3.3 и Setup Tools (второе можно взять отсюда: https://pypi.python.org/pypi/setuptools установка после разархивации C:\Python33\python.exe C:\setup_tools\setup.py install)
Приступим, первым делом - установка!
Идем на сайт: https://www.djangoproject.com/download/
В данном примере я просто скачал архивную версию, распаковал ее в папку C:\test\
Далее запускаем командную строку, или проще говоря «cmd».
У меня на компьютере был установлен Python 3, в cmd (запускаем с правами администратора) действия следующие:
1. cd C:\test\
2. C:\Python33\python.exe C:\test\setup.py install
После этого проверим (уже в Python):
>>> import django
>>> print(django.get_version())
1.7.1
3.1 Hello, world! Передача аргументов. Шаблоны.
После установки django, создаем проект:
cd C:\django_code\
Создаем проект командой «startproject»
C:\Python33\python.exe C:\Python33\Lib\site-packages\Django-1.7.1-py3.3.egg\django\bin\django-admin.py startproject first
Далее для теста нам хватит минимального предустановленного функционала с базой данных sqlite, для работы создадим все нужные файлы (настройки, для которых создаются файлы базы данных и учетные данные хранятся в созданном файле проекта "settings.py"):
C:\Python33\python.exe C:\django_code\first\manage.py migrate
Запускаем сервер(По умолчанию работает на адресе http://127.0.0.1:8000/)
C:\Python33\python.exe C:\django_code\first\manage.py runserver
Что мы создадим в этой главе:
1. Первую классическую программу "Hello World!"
2. Научимся передавать аргументы в URL запроса
3. Выведем страницу с помощью шаблона
Итак, давайте создадим обработчики запросов для нашего сервера:
C:\django_code\first\first\urls.py
from django.conf.urls import patterns, include, url
from . import views
urlpatterns = patterns('',
#^ - "начинается с", $ - "окончание строки"
url(r'^hello/$', views.hello),
#\d - числовой символ, представление(функция) принимает аргумент из "()"
url(r'^dtime/(\d)/$', views.dtime),
#\w+ - Буквенный или цифровой символ или знак подчёркивания ноль или более раз
url(r'^templ/(\w+)/$', views.templ),
)
Надо сказать следущее, первый url обрабатывает запрос к "Hello World!" - http://127.0.0.1:8000/hello/ ,
второй к http://127.0.0.1:8000/dtime/1/ , тут "1" - передаваемый аргумент,
третий к http://127.0.0.1:8000/templ/3/ , тут передаваемый аргумент - "3"
Для составления более сложных шаблонов запросов почитайте о регулярных выражениях например на википедии.
строка "from . import views" - импортирует файл представлений:
C:\django_code\first\first\views.py
#Представление(view) — это функция, которая получает аргумент HttpReqeust и возвращает объект HttpResponse
from django.http import HttpResponse
###Первая программа
def hello( request ) :
return HttpResponse( u'Hello World!' )
###Принимаем аргумент и вывод 404 ошибки
from django.http import Http404
from datetime import *
#offset - принимаемый аргумент из "()"
def dtime( request, offset ) :
try :
offset = int(offset)
dt = datetime.now() + timedelta( hours = offset )
result = HttpResponse( u"<html><body>%s</body></html>" % dt )
return result
except ValueError :
raise Http404
###Шаблон и контекст
from django.shortcuts import render
def templ( request, arg ) :
localarg = '' # вызовет блок else в шаблоне
localarg = 'in templ'
#render() - выполняет указанный шаблон с переданным словарем контекста, возвращает HttpResponse с полученным содержимым.
context = {'context_arg': arg, 'templ_arg': localarg, 'incontext': [ '1 arg', '2 arg' ] }
return render( request, 'templ.html', context )
В нем мы описали логику обработки аргументов, другие переменные и передачу итоговых данных для шаблонов.
Но для работы шаблона нам нужно в файле настроек C:\django_code\first\first\settings.py внести блок:
#Укажем папку для шаблонов
TEMPLATE_DIRS = (
'C:\\django_code\\first\\templates\\' ,
)
После чего функция "render" найдет шаблон по этому пути 'templ.html',
Сам шаблон выводит две переменные, и переменны из списка с помощью перебора:
<html><body>
<!-- Если пришел словарь с таким именем -->
{% if context_arg and templ_arg %}
<!-- Обратимся к именам переменных -->
context_arg is: {{ context_arg }}
<br />
templ_arg is: {{ templ_arg }}
<hr />
<!-- Переберем элементы списка {{ forloop.counter }} - счетчик(псевдопеременная) -->
{% for inarg in incontext %}
incontext_arg {{ forloop.counter }} is: {{ inarg }}<br />
{% endfor %}
{% else %}
<!-- Если нет - ошибка -->
Error!
{% endif %}
</body></html>
В переборе участвует псевдопеременная forloop.counter, переданные переменные для django обрабляются в двойные кавычки.
Заметьте, если Вы закоментируете localarg = 'in templ', то отработает блок "else" нашего шаблона.
3.1 Простое приложение, простая модель
Приложение создается с помощью команды "startapp ", которой передается имя будущего приложения:
c:\django_code\first>C:\Python33\python.exe C:\django_code\first\manage.py startapp firstapp
Далее в настройках "C:\django_code\first\first\settings.py" добавим наше приложение:
INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'firstapp',
)
Создадим обработчик запроса для приложения в главном urls нашего проекта:
C:\django_code\first\first\urls.py
from django.conf.urls import patterns, include, url
urlpatterns = patterns('',
#Добавим приложение "firstapp"
#Приложение будет срабатывать по запросу: http://127.0.0.1:8000/firstapp/generic/
#Первая часть запроса обрабатывается в C:\django_code\first\first\urls.py проекта
#Вторая часть запроса обрабатывается в C:\django_code\first\firstapp\urls.py приложения
url(r'^firstapp/', include( 'firstapp.urls' ) ),
)
Создадим обработчик в urls нашего приложения:
C:\django_code\first\firstapp\urls.py
from django.conf.urls import patterns, url
from . import views
urlpatterns = patterns('',
( r'generic/$', views.generic ),
)
Теперь настало время написать элементарное представление для проверки:
C:\django_code\first\firstapp\views.py
from django.http import HttpResponse
def generic( request ) :
return HttpResponse( u'Works!' )
А теперь создадим простую модель.
Модель по сути является схемой базы данных:
C:\django_code\first\firstapp\models.py
from django.db import models
#Модель — это класс, являющийся подклассом django.db.models.Model
#Атрибуты модели - отдельные поля базы данных
class dept ( models.Model ):
#В Django каждая модель имеет поле первичного ключа, даже если его не указали
#Список типов полей в Django: https://docs.djangoproject.com/en/dev/ref/models/fields/
name = models.CharField(max_length=15)
class workers ( models.Model ):
dept = models.ForeignKey(dept)
name = models.TextField()
birthday = models.DateTimeField()
После создания модели приведем в порядок базу данных командой "syncdb":
C:\django_code\first>C:\Python33\python.exe C:\django_code\first\manage.py syncdb
Запускаем сервер и проверяем:
C:\django_code\first>C:\Python33\python.exe C:\django_code\first\manage.py runserver
http://127.0.0.1:8000/firstapp/generic/
3.2 Изменения в базе данных
В этой статье мы научимся вносить изменения в базу данных на примере добавления поля "boss"
Изменяем модель(например добавим поле "boss"):
C:\django_code\first\firstapp\models.py
from django.db import models
class dept ( models.Model ):
name = models.CharField(max_length=15)
class workers ( models.Model ):
dept = models.ForeignKey(dept)
name = models.TextField()
birthday = models.DateTimeField()
boss = models.CharField(max_length=12)
Команда makemigrations - cоздает новые миграции на основе изменений, обнаруженных в вашей модели.
C:\django_code\first>C:\Python33\python.exe C:\django_code\first\manage.py makemigrations
Команда syncdb анализирует значение INSTALLED_APPS и создает все необходимые таблицы в базе данных используя настройки базы данных из файла settings.py.
C:\django_code\first>C:\Python33\python.exe C:\django_code\first\manage.py syncdb
Возникла проблема с dbshell: "sqlite3" не является внутренней или внешней командой, исполняемой программой или пакетным файлом
качаем sqlite-shell-win32-x86-3080701.zip с http://sqlite.org/download.html
распаковываем "экзешник" из архива например в "C\Python33\",
обязательно убедитесь, чтоб этот путь был в переменной PATH в свойствах моего компьютера-доп.параметры системы-переменные среды
Теперь запускаем dbshell
c:\django_code>C:\Python33\python.exe C:\django_code\first\manage.py dbshell
Помощь по командам
sqlite> .help
.backup ?DB? FILE Backup DB (default "main") to FILE
.bail on|off Stop after hitting an error. Default OFF
.clone NEWDB Clone data into NEWDB from the existing database
.databases List names and files of attached databases
.dump ?TABLE? ... Dump the database in an SQL text format
If TABLE specified, only dump tables matching
LIKE pattern TABLE.
.echo on|off Turn command echo on or off
.eqp on|off Enable or disable automatic EXPLAIN QUERY PLAN
.exit Exit this program
.explain ?on|off? Turn output mode suitable for EXPLAIN on or off.
With no args, it turns EXPLAIN on.
.fullschema Show schema and the content of sqlite_stat tables
.headers on|off Turn display of headers on or off
.help Show this message
.import FILE TABLE Import data from FILE into TABLE
.indices ?TABLE? Show names of all indices
If TABLE specified, only show indices for tables
matching LIKE pattern TABLE.
.load FILE ?ENTRY? Load an extension library
.log FILE|off Turn logging on or off. FILE can be stderr/stdout
.mode MODE ?TABLE? Set output mode where MODE is one of:
csv Comma-separated values
column Left-aligned columns. (See .width)
html HTML <table> code
insert SQL insert statements for TABLE
line One value per line
list Values delimited by .separator string
tabs Tab-separated values
tcl TCL list elements
.nullvalue STRING Use STRING in place of NULL values
.once FILENAME Output for the next SQL command only to FILENAME
.open ?FILENAME? Close existing database and reopen FILENAME
.output ?FILENAME? Send output to FILENAME or stdout
.print STRING... Print literal STRING
.prompt MAIN CONTINUE Replace the standard prompts
.quit Exit this program
.read FILENAME Execute SQL in FILENAME
.restore ?DB? FILE Restore content of DB (default "main") from FILE
.save FILE Write in-memory database into FILE
.schema ?TABLE? Show the CREATE statements
If TABLE specified, only show tables matching
LIKE pattern TABLE.
.separator STRING ?NL? Change separator used by output mode and .import
NL is the end-of-line mark for CSV
.shell CMD ARGS... Run CMD ARGS... in a system shell
.show Show the current values for various settings
.stats on|off Turn stats on or off
.system CMD ARGS... Run CMD ARGS... in a system shell
.tables ?TABLE? List names of tables
If TABLE specified, only list tables matching
LIKE pattern TABLE.
.timeout MS Try opening locked tables for MS milliseconds
.timer on|off Turn SQL timer on or off
.trace FILE|off Output each SQL statement as it is run
.vfsname ?AUX? Print the name of the VFS stack
.width NUM1 NUM2 ... Set column widths for "column" mode
Negative values right-justify
посмотрим названия таблиц
sqlite> .tables
auth_group django_admin_log
auth_group_permissions django_content_type
auth_permission django_migrations
auth_user django_session
auth_user_groups firstapp_dept
auth_user_user_permissions firstapp_workers
Проверим нашу таблицу
sqlite> .schema firstapp_workers
CREATE TABLE "firstapp_workers" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "name" text NOT NULL, "birthday" datetime NOT NU
LL, "dept_id" integer NOT NULL REFERENCES "firstapp_dept" ("id"), "boss" varchar(12) NOT NULL);
CREATE INDEX firstapp_workers_b5a9fd30 ON "firstapp_workers" ("dept_id");
Выйдем
sqlite> .exit
3.3 Админка
Минимальные действия для запуска админки
в C:\django_code\first\first\settings.py
в разделе INSTALLED_APPS раскометнтировать 'django.contrib.admin',
Когда Django загружает URLconf от urls.py при запуске сервера, он выполняет admin.autodiscover (),
эта функция перебирает установки INSTALLED_APPS и ищет файл с именем admin.py на каждом из установленных приложений.
Если admin.py существует в данном приложении, он выполняет код в этом файле.
C:\django_code\first\first\urls.py
from django.conf.urls import patterns, include, url
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
url(r'^firstapp/', include( 'firstapp.urls' ) ),
url(r'^admin/', include(admin.site.urls)),
)
теперь зарегистрируем наши модели
C:\django_code\first\firstapp\admin.py
from django.contrib import admin
from firstapp.models import dept, workers
admin.site.register(dept)
admin.site.register(workers)
Теперь добавим удобства
C:\django_code\first\firstapp\admin.py
1. добавим заголовок админки
from django.contrib import admin
from firstapp.models import dept, workers
#Заголовок админки
admin.AdminSite.site_header = 'Заголовок админки'
admin.site.register(dept)
admin.site.register(workers)
2. после добавления записей, мы видим неудобнуое отображение в списке добавленных записей,
Выведем их в "человеческом виде"
C:\django_code\first\firstapp\models.py
from django.db import models
class dept ( models.Model ):
def __str__(self):
return self.name
name = models.CharField(max_length=15)
class workers ( models.Model ):
def __str__(self):
return self.name
dept = models.ForeignKey(dept)
name = models.TextField()
birthday = models.DateTimeField()
boss = models.CharField(max_length=12)
3. изменение порядка полей и скрытие
C:\django_code\first\firstapp\admin.py
from django.contrib import admin
from firstapp.models import dept, workers
#Заголовок админки
admin.AdminSite.site_header = 'Заголовок админки'
class WorkersAdmin(admin.ModelAdmin):
#fieldsets - название группы полей.
#В fields передаем поля из модели.
#Во второй строке класс "collapse", отображает группу полей изначально скрытой.
fieldsets = [
(None, {'fields': ['dept']}),
('Информация о работнике', {'fields': ['name', 'birthday', 'boss'], 'classes': ['collapse']}),
]
admin.site.register(dept)
#WorkersAdmin передается как настройка для класса workers
admin.site.register(workers, WorkersAdmin)
4. Отображение доп.полей в отображении списка работников
C:\django_code\first\firstapp\admin.py
from django.contrib import admin
from firstapp.models import dept, workers
#Заголовок админки
admin.AdminSite.site_header = 'Заголовок админки'
class WorkersAdmin(admin.ModelAdmin):
fieldsets = [
(None, {'fields': ['dept']}),
('Информация о работнике', {'fields': ['name', 'birthday', 'boss'], 'classes': ['collapse']}),
]
#Отображение доп.полей в отображении списка работников
#http://127.0.0.1:8000/admin/firstapp/workers/
list_display = ('name', 'dept', 'birthday')
admin.site.register(dept)
admin.site.register(workers, WorkersAdmin)
5. Добавим поле поиска(поиск по указанному полю):
C:\django_code\first\firstapp\admin.py
from django.contrib import admin
from firstapp.models import dept, workers
#Заголовок админки
admin.AdminSite.site_header = 'Заголовок админки'
class WorkersAdmin(admin.ModelAdmin):
fieldsets = [
(None, {'fields': ['dept']}),
('Информация о работнике', {'fields': ['name', 'birthday', 'boss'], 'classes': ['collapse']}),
]
list_display = ('name', 'dept', 'birthday')
#Добавим поле поиска(будет искать по указанному полю):
search_fields = ['name']
admin.site.register(dept)
admin.site.register(workers, WorkersAdmin)
6. Добавления связанных объектов
Добавим возможность добавлять сотрудников из формы добавления департамента
C:\django_code\first\firstapp\admin.py
from django.contrib import admin
from firstapp.models import dept, workers
admin.AdminSite.site_header = 'Заголовок админки'
#Добавления связанных объектов (отобразим функционал добавления workers в dept)
#Варианты отображения TabularInline и StackedInline
class WorkersInline(admin.TabularInline):
#class ChoiceInline(admin.StackedInline):
model = workers
#Показать 3 формы для добавления работников в департамент.
extra = 3
class DeptAdmin(admin.ModelAdmin):
#функционал добавления workers в dept
inlines = [WorkersInline]
class WorkersAdmin(admin.ModelAdmin):
fieldsets = [
(None, {'fields': ['dept']}),
('Информация о работнике', {'fields': ['name', 'birthday', 'boss'], 'classes': ['collapse']}),
]
list_display = ('name', 'dept', 'birthday')
search_fields = ['name']
admin.site.register(dept, DeptAdmin)
admin.site.register(workers, WorkersAdmin)
3.4 Сессии
Для начала внесем изменения в C:\django_code\first\first\settings.py нашего проекта из прошлых уроков:
1. Измените параметр MIDDLEWARE_CLASSES, добавив в него значение django.contrib.sessions.middleware.SessionMiddleware.
2. Внесите в параметр INSTALLED_APPS значение django.contrib.sessions.
3. После того, как вы завершили настройку, запустите manage.py migrate для создания таблицы базы данных, в которой хранятся данные сессии.
Приведем C:\django_code\first\firstapp\urls.py к такому виду:
from django.conf.urls import patterns, url
from . import views
urlpatterns = patterns('',
( r'ses1/$', views.ses1 ),
( r'ses2/$', views.ses2 ),
( r'delses/$', views.delses ),
( r'getses/$', views.getses ),
( r'giveses/$', views.giveses ),
)
А теперь сами представления:
from django.http import HttpResponse
#Оф.Документация по сессиям Django 1.7 http://djbook.ru/rel1.7/topics/http/sessions.html#module-django.contrib.sessions
def ses1( request ) :
request.session[0] = 'sessionbar'
# Получим значение ключа из сессии
per = "Key '0' is: "+request.session[0]
return HttpResponse( per+' <a href="http://127.0.0.1:8000/firstapp/ses2/">ses2</a>'+
' <a href="http://127.0.0.1:8000/firstapp/delses/">delses</a>'+
' <a href="http://127.0.0.1:8000/firstapp/getses/">getses</a>'+
" <a href='http://127.0.0.1:8000/firstapp/setlogin/'>setlogin</a>")
def ses2( request ) :
#per = request.session[0] Вызовет ошибку
# Проверка наличия ключа в сессии:
if '0' in request.session:
per = "Key '0' is: "+request.session['0']
else :
per = "Key '0' is clean! "
return HttpResponse( per+' <a href="http://127.0.0.1:8000/firstapp/ses1/">ses1</a>'+
' <a href="http://127.0.0.1:8000/firstapp/delses/">delses</a>'+
' <a href="http://127.0.0.1:8000/firstapp/getses/">getses</a>'+
" <a href='http://127.0.0.1:8000/firstapp/setlogin/'>setlogin</a>")
def delses( request ) :
# Чистим значение ключа в сессии:
del request.session['0']
return HttpResponse( "Key '0' is clean! Back to ses2: "+' <a href="http://127.0.0.1:8000/firstapp/ses2/">ses2</a>' )
def getses( request ) :
per = request.session['ses'] = 2
# Проверка значения в сессии методом get
if request.session.get( 'ses' ) == 1 :
return HttpResponse( 'ses = 1' )
else :
return HttpResponse( 'ses != 1' )
def giveses( request ) :
#сессия является моделью Django, определённой в django.contrib.sessions.models
#сессия идентифицировануется 32символьным хэшем, который хранится в cookie
#доступ к сесси можно получить с помощью стандартного API для доступа к базам данных
from django.contrib.sessions.backends.db import SessionStore
#Стартуем сессию
s = SessionStore()
#Устанавливаем переменную сессии и значение
s['bar'] = '123'
#Сохраняем
s.save()
#Получаем доступ к сессии
sk = SessionStore( session_key = s.session_key )
#Выводим переменную из сессии с полученным доступом
return HttpResponse( 'session_key is: '+s.session_key+' sk_bar value is: '+sk['bar'] )
Все примеры снабжены подробными коментариями, но в двух словах:
ses1 - Установка и получение значения сессии
ses2 - Обращение и проверка значения сессии
delses - Очистка значения
getses - Проверка значения в сессии методом get
giveses - доступ к сесси с помощью стандартного API для доступа к базам данных
3.5 Запросы и чистый SQL
Приводим наш C:\django_code\first\firstapp\urls.py к виду:
from django.conf.urls import patterns, url
from . import views
urlpatterns = patterns('',
url(r'^sel/(?P<id>\d+)/$', views.sel),
url(r'^ins/$', views.ins),
url(r'^upd/$', views.upd),
url(r'^delete/$', views.delete),
url(r'^mraw/$', views.mraw),
url(r'^cursor/$', views.cursor),
)
Напоминаю, какая модель была на прошлых уроках(добавьте, если нет тестовые данные C:\django_code\first\firstapp\models.py):
from django.db import models
class dept ( models.Model ):
def __str__(self):
return self.name
name = models.CharField(max_length=15)
class workers ( models.Model ):
def __str__(self):
return self.name
dept = models.ForeignKey(dept)
name = models.TextField()
birthday = models.DateTimeField()
boss = models.CharField(max_length=12)
Теперь сами модели C:\django_code\first\firstapp\views.py:
from django.http import HttpResponse
from firstapp.models import dept
#Примеры SQL-запросов в оф.документации: https://docs.djangoproject.com/en/1.7/topics/db/queries/
#Примеры чистых SQL-запросов в оф.документации:https://docs.djangoproject.com/en/1.7/topics/db/sql/
#SELECT SQL-запрос
def sel( request, id ) :
d_id = dept.objects.get(pk=id) # найти объект по полю id
#Django не выполнит запрос, пока не будет вызван метод save()
d_id.save()
d_name = dept.objects.get(name="sale") # найти запись по полю name
d_name.save()
d_all = dept.objects.all() # все записи
return HttpResponse( "select id: %s select name: %s select count: %s" % (d_id.id, d_name.name, d_all.count()) )
#INSERT SQL-запрос
def ins( request ) :
d = dept(name='New department')
d.save()
d_name = dept.objects.get(name="New department")
d_name.save()
return HttpResponse( "select name: %s" % d_name.name )
#UPDATE SQL-запрос
def upd( request ) :
#UPDATE с условием
d = dept.objects.filter(id=3).update(name='id3_name')
d_id = dept.objects.get(pk=3)
d_id.save()
return HttpResponse( "select id: %s" % d_id.name )
#DELETE SQL-запрос
def delete( request ) :
dept.objects.filter(name="New department").delete()
return HttpResponse( "New department is delete")
#SQL с помощью Manager.raw
def mraw( request ):
#Manager.raw принимает чистый SQL запрос, выполняет, возвращает экземпляр django.db.models.query.RawQuerySet
html = ''
#Raw query must include the primary key \ Raw query должен включать первичный ключ
for dname in dept.objects.raw('SELECT id, name FROM firstapp_dept'):
html = html+dname.name+'<br />'
return HttpResponse(html)
#SQL с помощью объекта Объект django.db.connection
def cursor( request ):
#Подключение к базе данных и получение объекта указателя с помощью вызова connection.cursor()
#cursor.execute(sql, [params]) для выполнения SQL-запросов
#cursor.fetchone() или cursor.fetchall() для получения результата
from django.db import connection
cursor = connection.cursor()
cursor.execute("SELECT id, name FROM firstapp_dept WHERE id = %s", [3])
row = cursor.fetchone()
return HttpResponse(row[1])
Теперь проверяем:
http://127.0.0.1:8000/firstapp/sel/2/
http://127.0.0.1:8000/firstapp/ins/
http://127.0.0.1:8000/firstapp/upd/
http://127.0.0.1:8000/firstapp/delete/
Последние два примера уже с чистыми SQL запросами
http://127.0.0.1:8000/firstapp/mraw/
http://127.0.0.1:8000/firstapp/cursor/
3.6 Простые формы
Задачи:
1. Создать форму
2. Ввести простые проверки корректной заполненности полей формы
3. Получить доступ к отправленным данным
В файле C:\django_code\first\first\settings.py установлен путь для шаблонов
TEMPLATE_DIRS = (
'C:\\django_code\\forms\\' ,
)
Пропишем в C:\django_code\first\firstapp\urls.py обработчик для запроса
from django.conf.urls import patterns, url
from . import views
urlpatterns = patterns('',
url(r'^form/$', views.form),
)
Теперь наше представление C:\django_code\first\firstapp\views.py
from django.shortcuts import render
from django.http import HttpResponse
#django.forms – библиотека django для работы с формами
from django import forms
#Форма с несколькими разнотипными полями
class NameOfForm(forms.Form):
FormField1 = forms.CharField(label='Your name?', max_length=100)
FormField2 = forms.EmailField()
FormField3 = forms.BooleanField(required=False)
def form(request):
# Если отработал метод POST
if request.method == 'POST':
form = NameOfForm(request.POST)
# is_valid - проверка заполнения полей формы
# при успехе возвращает True и добавляет данные формы в атрибут cleaned_data
if form.is_valid():
data = ""
# покажем введенные данные
for x in form.cleaned_data:
data = data + str(form.cleaned_data[x]) + "<br />"
return HttpResponse(data)
else:
form = NameOfForm()
# Вывод формы
return render(request, 'form.html', {'form': form})
И сам шаблончик для вывода формы C:\django_code\forms\form.html:
<form action="/firstapp/form/" method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit" />
</form>
Проверяем: http://127.0.0.1:8000/firstapp/form/