пятница, 29 апреля 2011 г.

Вывод изображений на страницу


    Сейчас я расскажу как выводить изображения на страницу, для их просмотра. Для начала нужно создать модель, с необходимыми полями. В данном случае используется модель, представленная  здесь.

views.py:

#берем все изображения, закаченные текущим пользователем
puser = User.objects.get(name=request.user)
images = Image.objects.filter(namer=puser.id)

#необходимо для корректного отображения, чтобы не возникало csrf-ошибки
context = {'images': images}
context.update(csrf(request))
#возвращаем значение со страницей и картинками
return render_to_response('reg_inf/base_index.html', context)


   Далее, в html -коде, пишем:

<form method="post">

{% csrf_token %}

<body>

<table class="t_img">
   {% for img in images %}
      {% if forloop.counter0|divisibleby:"3" %}
      <tr width=151>
      {% endif %}
            <td align="char">
                      <img id="img-{{ img.nomer }}" src='{{ img.mini.url }}' />         
</td>
      {% if forloop.counter|divisibleby:"3" %}
      </tr>
      {% endif %}
{% endfor %}
</table>

</body>
</form>

    {% if forloop.counter0|divisibleby:"3" %} - используется для вывода по три картинки(миниатюры) в строку

вторник, 26 апреля 2011 г.

Отображение файла журнала в джанговской Админке


   В предыдущей статье было описано как реализовать журнал действий пользователь. Здесь будет рассмотрено как просмотреть журнал в админке.

   Для начала, сама процедура отображения содержимого файла.
views.py:

def log(request, userid):
    #по идентификатору выбираем строку из БД с данными о текущем пользователе
    user = LogUser.objects.get(id=userid)
    username = user.name
    #указываем путь к фалу лога пользователя
    url = settings.LOG_FILE_PATH.format(user=username) #MEDIA_ROOT+log.log'
    #считываем информацию из файла
    f = open(url, 'r')
    log = f.readlines()
    #создаем переменную лога для передачи на html страницу
    context = {'log_lines': log}
    return render_to_response('reg_inf/user_log.html', context)

После подключения админки (расскобить две строки в урлах:)), в файле models.py, пишем:

from django.contrib import admin
#импортируем Стандартную джанговскую модель User
#как с ней работать написано здесь 
from django.contrib.auth.models import User
#модель, для отображения имени юзера и поля лога
from reg_inf.models import LogUser

from django.contrib.auth.admin import UserAdmin

#импортируем процедуру из views.py
from reg_inf.views import log

admin.autodiscover()

#процедура, для отображения ссылки в админке на файл лога
def user_view_log_link(user):
    #id юзека, для определения имени в БД
    p = user.id
    #возвращаем ссылку, при нажатии на которую, вызывается процедура log
    #ей передается id юзера, на против которого была нажата ссылка
    return '<a href="%s">:Журнал</a>' % reverse(log, args=[p])

#создаем дополнительное поле для ссылки
user_view_log_link.allow_tags = True

#создаем класс, для отображения в админке
class MyUser(admin.ModelAdmin):
  list_display = ('name', user_view_log_link,)
#регистрируем модель LogUser как потомка MyUser
admin.site.register(LogUser, MyUser)

Для корректной передачи id юзера, необходимо записать в url.py:

urlpatterns = patterns('reg_inf.views',
    (r'^log/(?P<userid>\d+)$', 'log'),


   Конешно можно было отобразить ссылку на файл прямо в стандартной модели User. Для этого её необходимо выгрузить из джанго и щзарегать снова. Но как показывает опыт, при таком отображении локально все работает отлично, при закгрузке на сервер под Апачем, а именно, ссылка то проподает, то появляется снова, то админка не грузиться.

среда, 20 апреля 2011 г.

Журналирование/логирование


Ниже представлена слегка переделанная функция, взятая вот отсюда:  http://pysi.org/articles/django_and_tornado/
views.py:
 

def userlogpath(user, message):
  #создание директории для записи лога и файла лога
  LOG_DIR = MEDIA_ROOT+'/log'
  LOG_FILE =  LOG_DIR+username+'.log'

  #проверка существования директории (впервые вошел в систему)
  if not os.path.isdir(LOG_DIR):
    os.makedirs(LOG_DIR)


  #задаем свойсива файла логирования
  #вданнои случе его размкщение
  file_handler = logging.handlers.RotatingFileHandler(
    filename = LOG_FILE)#, mode='a+', # имя файла
   #maxBytes = 1000000, # максимально байт в файле
   #backupCount = 1) # максимум файлов

  # задаем режим логирования ('INFO')
  file_handler.setLevel(getattr(logging, 'INFO'))
  #задаем формат логирования (число-месяц-год время) 
  file_handler.setFormatter(
  logging.Formatter('%(asctime)s\t%(levelname)-8s %(message)s',
                               datefmt = '%d-%m-%Y %H:%M:%S'))
  logging.getLogger('').setLevel(logging.INFO)
  #устанавливаем режим добавления в файл
  logging.getLogger('').addHandler(file_handler)

  #записываем информацию
  logging.info(message)

  #закрываем файл
  logging.getLogger('').removeHandler(file_handler)
  file_handler.close()


Это был простой способ. Но можно повыпендриваться и записать основные директории в settings.py, например вот так:

LOG_DIRNAME = 'log'
LOG_DIR = os.path.join( '{user}', LOG_DIRNAME)
LOG_FILENAME = '{user}.log'
LOG_FILE_PATH = os.path.join(MEDIA_ROOT, LOG_DIR, LOG_FILENAME)

#в views.py вызвать вот так:

LOG_FILE = settings.LOG_FILE_PATH.format(user=user.username)
LOG_DIR = os.path.dirname(LOG_FILE)

воскресенье, 17 апреля 2011 г.

Авторизация средствами Django


  В Django есть две таблицы. Это User и Group. Они располагаются в django.contrib.auth. На самом деле там есть еще таблицы, но для создания проверки прав доступа, необходимы эти две.
  В таблице Group, будут содержаться группы пользователей, которые имеют различные правадоступа. В данном случае это:

1. Оператор
2. Пользователь (Юзер)

  Таблица User используется для записи пользователей прошедших аутоинтификацию. Там содержится логин пользователя, который уникален и не повторяется.

  Для работы с этими таблицами необходимо их импортировать:

from django.contrib.auth.models import User, Group

  Далее, при первичной аутоидентификации, данные вносятся в таблици:
# выполняется в блоке try - except, если таблица была пустой и туда ещё не
# вносились записи

try:
    group = Group.objects.get(name='user')
except Group.DoesNotExist:
# вексение групп пользователей
    group = Group(name='operators')
    group.save()
    group = Group(name='users')
    group.save()
try:
    user = User.objects.get(username=username)
except User.DoesNotExist:
# создание записи пользователя
    user = User.objects.create_user(username, '', '')
# внесение в группу номер 2, т.е. 'user'
    user.groups.add(2)


  Таблица User, содержит в себе ссылку на таблицу Group, через встроенную 'подтаблицу'
groups.
  Главное корректно заполнить таблицу Group, а далее, добавление прав доступа осуществляется коммандой add('нмер поля записи в таблице Group, соответсвующий определенной группе пользователей')

  Процедура авторизации имеет следующий вид:

def avtorr(user):
# осуществляется проверка принадлежности копределенной группе пользователей
    return True if user.groups.filter(name='user') else False


  Далее, в тексте программы, вставляется проверка, Она вставляется в начале процедуры, которая обрабатывает html страницы, в которых разграничены права доступа.

if autor(request.user)==False:
    return HttpResponseRedirect(reverse("имя процедуры, обрабатывающей случай когда нет прав доступа к данной странице"))


четверг, 14 апреля 2011 г.

Выбор даты в Django




Здесь я покажу как можно создать форму, в которой можно выбрать день, месяц, год, нажатием мыши.
Для этоко использовался виджет SelectDateWidget, взятый здесь

year = datetime.date.today().year

class MyForms(forms.Form):
    dataget = forms.DateField(label='Дата:', initial=datetime.date.today,
                                           input_formats=('%d-%m-%Y',),
                                           widget=SelectDateWidget(input_format='%d-%B-%Y',
                                           years=range(year, year-101, -1)))


initial=datetime.date.today - инициализируем форму с текущей датой

input_formats=('%d-%m-%Y',) - отображения даты в виде день, месяц, год

input_format='%d-%B-%Y' - тображение и обработка даты в виджете

%B - месяц словами, в данном случае английские названия

years=range(year, year-101, -1) - задание диапазона лет, чтобы нельзя бало выбрать дату рождения 1104 от Р. Х.)


Во всех полях данной формы, можно отображать произвольную информацию, с помощью модуля: django.utils.dates. Отдуда импортируются словари MONTHS и MONTHS_3.

Их можно переделать следующим образом:

MONTHS = {
1: 'Январь', 2: 'Февраль', 3: 'Март', 4: 'Апрель', 5: 'Май', 6: 'Июнь',
7: 'Июль', 8: 'Август', 9: 'Сентябрь', 10: 'Октябрь', 11: 'Ноябрь',
12: 'Декабрь'
}


Но лучше использовать для этого конвертацию в другие языки названий месяцев).
Для это го надо в settings.py изменить язик:

LANGUAGE_CODE = 'ru-RU'
Время тоже лучше поменять на свой часовой пояс:

TIME_ZONE = 'Europe/Moscow'

Далее использовать стандартный джанговский модуль в forms.py:

from django.forms.extras.widgets import SelectDateWidget

year = datetime.date.today().year

class MyForms(forms.Form):
    dataget = forms.DateField(label='Дата выдачи:',       widget=SelectDateWidget(years=range(year, year-101, -1)), required=False)

required=False - испоьзуется для необязательных для заполнения полей.

Поле ContentTypeRestrictedFileField


Очень полезным полем для загрузки изображений является ContentTypeRestrictedFileField. Удобство его в том, что оно позволяет задать размер загружаемого изображения и, тем самым, обезопасить свой сайт от намеренной загрузки огромных изображений)).

Так же, это поле может использоваться для загрузки файлов.
Ниже приведена форма (forms.py):

class VvForm(forms.Form):
    imgname = forms.CharField(max_length=40, label='Название изображения',
    error_messages={'required': 'Заполните поле'})
    img = ContentTypeRestrictedFileField(label='Изображение',
             content_types='image/x-ms-bmp;image/png;image/bmp;image/jpg;image/jpeg;image/gif',
             max_upload_size=1073741824,
             error_messages={'required': 'Заполните поле'})

content_types='image/x-ms-bmp;image/png;image/bmp;image/jpg;image/jpeg;image/gif' - определяет диапазон возможных загружаемых типов изображений.

max_upload_size=1073741824  - непосредственно, поля для задания размера загружаемого файла.

error_messages={'required': 'Заполните поле') - если поле не заполнено и попытаться осуществить загрузку, то выдаст сообщение:  'Заполните поле'.)

Так же, ознакомиться с функционированием пол, можно здесь: http://djangosnippets.org/snippets/2206/

Каталог блогов

понедельник, 11 апреля 2011 г.

Загрузка текстового файла с помошью динамического upload_to



Итак приступим).

Здесь я опушу как создавал модели и как просто (на мой взгляд) задавать динамический путь для upload_to (использовалась БД PostgreSQL).
Для начала, опишем какие модели использовались

 models.py:

class User(models.Model):
publication_date = models.DateField(auto_now_add=True)
.......
nick = models.CharField(max_length=50)
#auto_now_add=True - автоматически сохраняет текущую дату в поле publication_date, при записи в #БД.

#Следующая модель:

class Ident(models.Model):
user = models.ForeignKey('User')
img = models.ForeignKey('Image')

..........
request_file = models.FileField(upload_to=txt_ident_get_upload_to)


models.ForeignKey('User') - используется для создания ключа (один ко многим) к таблице User. Аналогично Image PrimaryKey не используется. Так как, втоматически создается поле id (User.id, Ident.id) по #которому легко можжно однозначно идентифицировать запись.


Функция, создающая динамический путь кфайлу.

def txt_ident_get_upload_to(instance, filename):
nick= instance.user.nick #так определяется текущий юзер, в поле nick таблицы User
tmpnomer = Img.objects.aggregate(models.Max('nomer'))['nomer__max']# http://docs.djangoproject.com/en/1.3/topics/db/aggregation/
return os.path.join('user', nick, 'idn', str( tmpnomer )+".txt") #Возвращаем функции значени пути к файлу и название текстового файла str( tmpnomer )+".txt"


tmpnomer = tmpnomer + 1 if tmpnomer else 1 - можно использовать, еси до этого в таблицу не вносились данные и там ничего еще не записано. У меня в данном случае это не использовалесь

return os.path.join('user', nick, 'idn', str( tmpnomer )+".txt") #Возвращаем функции значени пути к файлу и название текстового файла str( tmpnomer )+".txt"
Также необходимо импортировать библиотеку для работы с директориями и файлами: import os

Теперь модуль views.py.

Cоздадим специальный файл и сохраним его с помощью upload_to

metadata = u"""{0} {1} {2} #Вместо цифр используются значения полей формы, в таком же порядке, Питоновский способ записи данных
Дата подачи заявки: {4}
""".format(tmpdata.sername, tmpdata.name, tmpdata.ssername, pimg.publication_date) #Значения этих поле подставяться вместо цифр. Значение берется из БД



Импортируем библиотеку для создания временных файлов
from django.core.files.uploadedfile import SimpleUploadedFile

upload_file = SimpleUploadedFile(str(tmpnomer), smart_str(metadata), content_type='text/plain')# Cоздаем специфльный файл


Первое значение - название файла
Второе - умная строка, содержимое файла:http://docs.djangoproject.com/en/1.3/ref/models/instances/
Третья -тип содержимого


Подставляем файл в модель при записи:

ident = Ident(user_id=pdata.user_id, request_file=upload_file)
ident.save()


Все), Файл сохранен по динамическому пути.
В функцию def txt_ident_get_upload_to(instance, filename) можно вставлять любые условя для определения пути, по которому файл сохраниться