Архивы: python

UnicodeDecodeError: ‘ascii’ codec can’t decode byte 0xc2 in position 0: ordinal not in range(128)

Капец, это вынос мозга, всегда разрабатывал под ubuntu, а тут приходится в Win это делать, и вылазят такие невероятные ошибки и грабли… вот сегодняшяя….

ctype = ctype.encode(default_encoding) # omit in 3.x!

UnicodeDecodeError: 'ascii' codec can't decode byte 0xc2 in position 0: ordinal not in range(128)

сразу же всё предельно и ясно, он нам прямым текстом говорит что надо топать в реестр
вот сюда

HKEY_CLASSES_ROOT\MIME\Database\Content Type

и тут находим в самом низу ветки с русскими символами, и переименовывает в транслит\латиницу.

аминь…

оказывается это давний баг, есть решение вот тут
http://softwaremaniacs.org/forum/django/31707/

А как вы боретесь с такими глюками?
чем заменяете cmd чтоб было удобно работать как в привычном terminal ?

Django показывать в админке пользователю только его объекты

Ещё довольно частая задача, надо чтоб пользователю в админке показывались только его объекты.
и второй момент, есть у нас в модели поле автор

    author = models.ForeignKey(User, null = True, blank = True , verbose_name=u'Имя')

и хочу чтоб пользователю в админке это поле не показывалось, но автоматически при сохранении подставлялся request.user

Реализуется это как всё по Джанговски в пару движений

в admin.py
наследуемся от модели admin
и немногожечrо допиливаем её

class ListAdmin(admin.ModelAdmin):
    # Добавим всякие фильтра
    list_filter = ('rooms','region','street', 'pub_date')
    #Говорим, чтоб не показывать это поле
    exclude = ('author',)
    # Тут начинается магия, СуперАдмину показываем всё, а пользователю, показываем только его объекты
    def queryset(self, request):
        if request.user.is_superuser:
            return super(ListAdmin, self).queryset(request)
        else:
            return super(ListAdmin, self).queryset(request).filter(author = request.user)
    # Так решим вторую задачу, в поле author подставляем request.user
    def save_model(self, request, obj, form, change):
        if getattr(obj, 'author', None) is None:
            obj.author = request.user
        obj.save()
       
admin.site.register(Estate,ListAdmin)

Вот и всё, не забываем создать отдельную группу для пользователей, в которой указать ту часть приложений куда они могут обращаться.

Django загрузка картинки и создания кропнутой превьюшки ( thumbnail )

И так господа, продолжаю ковыряться в Django, продолжу тему создания расширенного профиля и создания аватарки разных размеров.

Напомню, что у нас есть модель профиль и там поле аватарки

 avatar = models.ImageField(verbose_name=u'Путь до аватарки', upload_to = 'users/', null = True, blank = True)

Теперь предположим, что у нас 2 странички, одна страничка целиком и полностью посвящена Пользователю, например так

И например вот такая страница где выводится полный список всех пользователей

разные размеры, разные соотношения сторон, привет верстальщику 😉
Ну да ладно, блуждая по тырнету наткнулся на сниппет

На его основе делаю, делаю при сохранении модели создания 2х картинок
одну звать полностью, у второй есть дописка _thumb.jpg например

def save(self,size=(276,317), *args, **kwargs):
        super(UserProfile, self).save(*args, **kwargs)
        try:
            # Создаём первое изображение
            filename= self.avatar.path
            image = Image.open(filename)
            image.thumbnail(size, Image.ANTIALIAS)
            image.save(filename)
            #Создаём мелкую картинку, если оно не верных размером кропаем под вёрстку
            size=(104,127)
            pw = self.avatar.width
            ph = self.avatar.height
            nw = size[0]
            nh = size[1]

            # only do this if the image needs resizing
            if (pw, ph) != (nw, nh):
                filename = str(self.avatar.path)
                image = Image.open(filename)
                pr = float(pw) / float(ph)
                nr = float(nw) / float(nh)

                if pr > nr:
                    # photo aspect is wider than destination ratio
                    tw = int(round(nh * pr))
                    image = image.resize((tw, nh), Image.ANTIALIAS)
                    l = int(round(( tw - nw ) / 2.0))
                    image = image.crop((l, 0, l + nw, nh))
                elif pr < nr:
                    # photo aspect is taller than destination ratio
                    th = int(round(nw / pr))
                    image = image.resize((nw, th), Image.ANTIALIAS)
                    t = int(round(( th - nh ) / 2.0))
                    print((0, t, nw, t + nh))
                    image = image.crop((0, t, nw, t + nh))
                else:
                    # photo aspect matches the destination ratio
                    image = image.resize(size, Image.ANTIALIAS)
                file, ext = os.path.splitext(filename)
                image.save(file + "_thumb.jpg", "JPEG")
        except :
            filename=''

По итогу создаются 2 картинки, для вывода полного изображения ничего не придумываю просто в шаблоне

<img src="/media/{{ profile.avatar }}"/>

А для вывода второго изображения описываю свойство дополнительное, примерно вот так

    def avatarTumb(self):
        try:
            filename= self.avatar.path
            file = os.path.basename(filename)
            files, ext = os.path.splitext(file)
            return u'%s_thumb.jpg' % (files)
        except :
            filename=''

ну и собственно обращаемся вот так

<img src="/media/users/{{ item.get_profile.avatarTumb }}" />

Свои варианты предлагайте ниже, как показало время это полезно очень, что-то можно сделать более удобно, может где-то я допустил ошибку 😉

Расширение профиля пользователя django

в Django я по прежнему новичок, но что-то стараюсь понять и запомнить.

стояла задача расширить профиль пользователя дополнительными полями, статей на эту тему пресс и малелькая тележка, но не получалось, то у кого-то на сайте парсер html сильно злой и код надо было переписывать, у кого-то были ошибки в примерах и т.п.

но как-то оно получилось, попробую собрать все мысли в кучу в эту статью.

Многие знают о django-registration и вот от автора этого замечательного приложения существует django-profiles котором я и воспользовался.

устанавливаем django-profiles

easy_install django-profiles

в models.py создадим модель профиля, которая наследуется от штатной User и добавим в ней нужное нам поле

from django.contrib.auth.models import User
...
...
class UserProfile(models.Model):
    # поле для связки со встроенной моделью пользователя Django
    user = models.ForeignKey(User, unique=True)
    # наше новое поле
    about = models.TextField(blank=True)

Далее в settings.py надо указать кто будет новым AUTH_PROFILE_MODULE

AUTH_PROFILE_MODULE = 'list.UserProfile'

где list это ваше приложение в котором расположена модель расширяющая пользователя

в принципе на этом можно закончить, ибо обращаться теперь можно к

{{ user.get_profile.about }}

только нужно обратить внимание что надо пользоваться не context а RequestContext
и указать это в
TEMPLATE_CONTEXT_PROCESSORS файла settings.py

TEMPLATE_CONTEXT_PROCESSORS = (
     ...
     'django.contrib.auth.context_processors.auth',
     ...
     )

но мы идём дальше

Теперь нам надо подключить django-profiles для просмотра\редактирования профиля

в файле urls.py
подключаем

    ...
    (r'^profiles/', include('profiles.urls')),
    ...

в settings.py также подключим приложение

INSTALLED_APPS = (
     ...
     'profiles',
     )

теперь создадим таблицы в базе

python manage.py syncdb

приложение profiles использует вот такие шаблоны

    profiles/create_profile.html
    profiles/edit_profile.html
    profiles/profile_detail.html
    profiles/profile_list.html

по названию понятно что к чему

для начала отредактируем edit_profile.html

{% extends "base.html" %}
{% block title %}Edit Profile{% endblock %}
 
{% block content %}
<h1>Edit contact info for {{ user }} </h1>
 
<form method="POST" action="">
    {{ form }}
    <input type="submit" name="submit" value="Update" id="submit">
</form>
 
{% endblock content %}

сохраняем, теперь можно обратиться к /profiles/edit/ то должно открыться форма редактирования профиля.

бывают ситуации, что в профиле есть какие-то поля, что запрещено редактировать пользователю, реализуется это довольно просто

создаём класс формы, наследуемой от общей формы, в котором перечисляем, то что нам исключить от вывода пользователю
forms.py

from django.db import models
from django.forms import ModelForm
from PROJ.apps.APP.models import UserProfile

.........
class ProfileForm(forms.ModelForm):
  class Meta:
      model = UserProfile
      exclude = ('user','last_name',)

from PROJ.apps.APP.models import UserProfile
проект и приложение где расположена расширенная модель

теперь в urls.py надо указать, что страницу редактирования профиля надо открывать с нужной нам формой

from PROJ.APP.forms import ProfileForm
........
    ('^profiles/edit', 'profiles.views.edit_profile', {'form_class': ProfileForm,}),
    (r'^profiles/', include('profiles.urls')),
.......

Должно получиться примерно так.. проверяем на странице редактирования профиля (/profiles/edit/).

Теперь сделаем страницу отображения профиля profile/profile_detail.html

вывести можно что угодно из профиля вот так

<p><strong>Address 2:</strong><br>{{ profile.address2 }}</p>

где address2 это дополнительное поле
список пользователей с профилями можно вывести вот так

profiles/profile_list.html

{% extends "base.html" %}
{% block content %}
<h1>Список пользователей</h1>
<br/><br/>
    {% for p in object_list  %}
<a href="{% url profiles_profile_detail p.user %}">{{ p.user }}</a>
{% endfor %}
{% endblock %}

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

в models.py добавим

from django.db.models import signals
from bucket.signals import create_profile
 
# When model instance is saved, trigger creation of corresponding profile
signals.post_save.connect(create_profile, sender=User)

создадим файл, если он не создан signals.py:

def create_profile(sender, instance, signal, created, **kwargs):
    """When user is created also create a matching profile."""

    from PROJ.apps.APP.models import UserProfile

    if created:
        UserProfile(user = instance).save()
        # Do additional stuff here if needed, e.g.
        # create other required related records

вот и всё, при регистрации нового пользователя автоматически будет создаваться к нему профиль, если у вас уже сейчас много пользователей, то создать для каждого профиль можно вот так

$ python manage.py shell
 
from django.contrib.auth.models import User
from bucket.models import Profile
 
users = User.objects.all()
for u in users:
     try:
          p = u.get_profile()
     except p.DoesNotExist:
          Profile(user = u).save()

ещё коснусь вопроса редактирования своего email в профиль, пока ещё не совсем разобрался с этим.

пока есть только пример, делается это анналогично через forms.py

class ProfileForm(ModelForm):
 
    def __init__(self, *args, **kwargs):
        super(ProfileForm, self).__init__(*args, **kwargs)
        try:
            self.fields['email'].initial = self.instance.user.email
            # self.fields['first_name'].initial = self.instance.user.first_name
            # self.fields['last_name'].initial = self.instance.user.last_name
        except User.DoesNotExist:
            pass
 
    email = forms.EmailField(label="Primary email",help_text='')
 
    class Meta:
      model = Profile
      exclude = ('user',)        
 
    def save(self, *args, **kwargs):
        """
        Update the primary email address on the related User object as well.
        """

        u = self.instance.user
        u.email = self.cleaned_data['email']
        u.save()
        profile = super(ProfileForm, self).save(*args,**kwargs)
        return profile

надеюсь вернусь к этому вопросу

django + twitter

«Мопед не мой, я лишь объяву разместил»
У меня пока не хватает кармы, чтоб высылать за такие статьи инвайты на хабр, поэтому видимо кроме меня этого не жалает делать никто, то буду опубликовать тут. ибо информацию считаю полезной, не только для себя.

Доброго времени суток!
Появилась необходимость следующего характера: в движке на django, при публикации новости, чтоб создавался кросс-пост на twitter. Т.е. пишем новость, жмём сохранить и на твиттере появляется пост аля «Название статьи, bit.ly/s/ссылка_на_нашу_новость».

Для реализации потребовались следующие пакеты:

1. python-oauth2 | https://github.com/simplegeo/python-oauth2
2. oauth-python-twitter2 | http://code.google.com/p/oauth-python-twitter2/
3. simplejson | http://pypi.python.org/pypi/simplejson/
4. oauth2 | http://pypi.python.org/pypi/oauth2/
5. bitlyapi | http://pypi.python.org/pypi/bitlyapi/

1-4 пакеты нужны нам для связи с twitter’ом, 5-ый для укорачивания ссылок…
Перед тем как начать предполагаю, что у Вас есть аккаунт в twitter.com и bit.ly. Если нет, то это по минуте на регистрацию на каждом из сервисов.

Начнём с twitter’a…

При-python-им twitter

Проставляем все пакеты и выполняем следующие действия (кстати они описаны выше в руководстве python-oauth2):
Логинимся в браузере в twitter.com, и после этого переходим по ссылке http://twitter.com/apps/new. Далее мы воспользуемся инструкциями из замечательной статьи:

1. Заполняем все поля на свое усмотрение, для Application Type выбираем Client
2. Для Default Access type выбираем Read & Write, Use Twitter for login я оставил не выбранным
3. Вводим капчу и сабмитим

После этого twitter сгенерит CONSUMER_KEY, CONSUMER_SECRET.
Следующие два параметра нам вернет такой скрипт

from oauthtwitter import OAuthApi
import pprint

CONSUMER_KEY = "*****"
CONSUMER_SECRET = "*****"

twitter = OAuthApi(consumer_key, consumer_secret)
temp_credentials = twitter.getRequestToken()
print(twitter.getAuthorizationURL(temp_credentials))
oauth_verifier = raw_input('What is the PIN? ')
access_token = twitter.getAccessToken(temp_credentials, oauth_verifier)

print("oauth_token: " + access_token['oauth_token'])
print("oauth_token_secret: " + access_token['oauth_token_secret'])

В CONSUMER_KEY, CONSUMER_SECRET вводим значения полученные на предыдущем этапе, запускаем. Скрипт сгенерит url, переходим по нему и копируем PIN который нам вежливо предлагает twitter. Вставляем PIN в скрипт, он как раз его ждет.

На выходе мы получим значения для двух последних параметров OAUTH_TOKEN и OAUTH_TOKEN_SECRET.
Все, теперь у нас есть все что надо для oauth авторизации, осталось немного подправить скрипты.

Готовимся сокращать ссылки вместе с bit.ly

Предельно простой и удобный модуль bitlyapi. Схема простая:

1. Регистрируемся на bit.ly
2. Логинимся
3. Переходим по ссылке
4. Копируем username и api key

Правим модель в Django

Здесь мы не рассматриваем создание модели, предполагается, что Вы это умеете. В шапку добавляем:

#twitter
import oauth2 as oauth
import bitlyapi
bitly = bitlyapi.BitLy('username bitly', 'api key bitly') #вводим данные с прошлого шага
from oauthtwitter import OAuthApi
CONSUMER_KEY = "*****вводим свои данные*****"
CONSUMER_SECRET = "*****вводим свои данные*****"
OAUTH_TOKEN = "*****вводим свои данные*****"
OAUTH_TOKEN_SECRET = "*****вводим свои данные*****"
twitter = OAuthApi(CONSUMER_KEY, CONSUMER_SECRET, OAUTH_TOKEN, OAUTH_TOKEN_SECRET)

Переходим к моделе. Логика проста, есть boolean поле twitter_export, если галочка ставится, то новость публикуется при сохранении на твиттере. Если не понятно, то сейчас всё увидите и поймёте ))

class News(models.Model):
    title = models.CharField(max_length=300)
    content = models.TextField()
    twitter_export = models.BooleanField(default=False)

def save(self):
    link = bitly.shorten(longUrl='http://example.com/news/' + str(self.id) + '/') #формируем ссылку, которая будет сокращенна
    if self.twitter_export:   #если стоит галочка на twitter_export
        twit = u'%s... | Читать %s' % (self.title[:70], link['url'])  #формируем, что писать в твиттер.. учтите, что длина сообщения в твиттере 160 символов
        twitter.UpdateStatus(twit) #публикуем наш твит
        self.twitter_export = False #убираем галку twitter_export
    super(News, self).save()

Всё готово! Можно тестировать!

Источники

1. Пишем twitter-бота на python
2. Twitter Three-legged OAuth Example

Страница 1 из 212