Information Security
Website development
Django
Comments 11
+2
Не все Django-проекты это требуют. Но да, согласен — ссылка точно уместна.
+1
Кстати, метод get_cookies можно упростить:

def get_cookies(self, request):
    if request is None:
        return {}
            
    return {key: 'secret' for key in request.COOKIES}

Спасибо Dreadatour!

Принцип с else общий — если в конце блока if есть return, то всё то, что должно выполняться в случае, если условие if не расценивается как истинное, можно помещать не в блок else, а просто размещать сразу после блока if, без каких-либо блоков — потому что если условие if было расценено как истинное, то всё, что ниже, всё равно уже никогда не выполнится (даже если было вызвано исключение).
0
Мне, кажется, это только наоборот усложняет восприятие программы. Конструкция if-else-then визуально воспринимается проще и логика более простая, чем в «упрощённом» варианте.
0
Просто представьте, что у вас не одно условие для return, а хотя бы три, что бывает довольно часто.
0
Представить можно много чего, мы ведь говорим про конкретное упрощение кода, представленного выше, а не про все на свете варианты. Я высказал мысль о том, как бы я записал конкретный код, рассмотренный выше, а не абстрактный.
0
Я вообще не спорю, просто захотелось мыслями поделиться. Для меня KISS — тот вариант, про который я пишу, с явным else
+1
За пост спасибо!

Но при авторизации скрытие email грозит, тем что можно долго искать проблему с дублированием email в другом регистре, что по де-фолту для джанги актуально. Во-первых, в стандартной модели пользователя email не уникальный. Во-вторых в стандратном поле EmailField нормализируется только домен. Таким образом, если вы все использовали из коробки и при регистрации сами не валидилировали email на уникальность с учетом возможного использования разного регистра символов то в зависимости от вашего бэкэнда утентификации при авторизации могут быть ошибки из-за того что в базе есть разные пользователи с адресами aruseni.magiku@gmail.com и Aruseni.Magiku@gmail.com. На рабочем сайте с большой базой пользователей вы можете долго искать эту проблему. Знание же для какого именно пользователя проблема актуальна в данном случае позволяет установить ее причину гораздо быстрее.
0
Спасибо, что подняли данную тему. Такая проблема действительно существует, если специально не позаботиться об обработке адресов электронной почты, набранных с использованием букв в разном регистре.

Реально регистрация может быть, например, такой (обработка IntegrityError тут для маловероятной ситуации race condition в случае одновременной регистрации двух пользователей):

Скрытый текст
if request.method == "POST":
    form = RegistrationForm(request.POST, request.FILES)
    if form.is_valid():
        email = form.cleaned_data["email"].lower()
        password = form.cleaned_data["password"]
        try:
            user = User.objects.create_user(hashlib.sha1(email).hexdigest()[:30],
                                       email,
                                       password)
            user.username = "".join(["user", str(user.id)])
            user.save()
        except IntegrityError:
            messages.error(request, u"При регистрации возникла ошибка. Пожалуйста, попробуйте ещё раз.")
            try:
                # Rollback the transaction (otherwise a DatabaseError would be raised when trying to delete the user)
                connection._rollback()
                # In case the IntegrityError was raised when renaming the user
                user.delete()
            # UnboundLocalError can be raised if the user variable is not defined
            except UnboundLocalError:
                pass
            return HttpResponseRedirect(reverse('dating.views.index'))
        UserProfile.objects.create(user=user,
                                   name=form.cleaned_data["name"],
                                   photo=form.cleaned_data["photo"])

        user = authenticate(username=user.username, password=password)
        login(request, user)

        email_body = render_to_string('registration_email.txt', {
            "username": form.cleaned_data["name"], "user_id": user.id
        })
        send_mail('Background Dating',
                  email_body,
                  None,
                  [email],
                  fail_silently=True)

        return HttpResponseRedirect(reverse('dating.views.index'))
else:
    form = RegistrationForm()

return render_to_response('index.html',
                          {"registration_form": form},
                          context_instance=RequestContext(request))

Форма регистрации с её родительским классом:

class UserProfileForm(forms.ModelForm):
    def clean_photo(self):
        image = self.cleaned_data.get('photo')
        if image:
            if not "." in image.name:
                raise ValidationError(u"Пожалуйста, убедитесь, что файл имеет расширение.")

            extension = image.name.rsplit('.',1)[1].lower()

            if extension not in ["jpg", "jpeg", "gif", "png"]:
                raise ValidationError(u"Пожалуйста, убедитесь, что изображение имеет одно из следующих расширений: jpg, jpeg, png, gif.")

            if image._size > 1*1024*1024:
                raise ValidationError(u"Пожалуйста, убедитесь, что размер изображения не больше 1 MiB.")

            im = Image.open(StringIO.StringIO(image.read()))

            # A dictionary of expected file extensions for each format (as returned by PIL)
            expected_file_extensions = {"JPEG": ["jpg", "jpeg"], "PNG": ["png"], "GIF": ["gif"]}

            if im.format not in expected_file_extensions:
                raise ValidationError(u"Пожалуйста, убедитесь, что изображение имеет один из следующих форматов: JPEG, PNG, GIF.")

            if extension not in expected_file_extensions[im.format]:
                raise ValidationError(u"Пожалуйста, убедитесь, что формат изображения соответствует его расширению.")

            if (im.size[0] < 300 or im.size[1] < 200):
                raise ValidationError(u"Пожалуйста, убедитесь, что разрешение фотографии не меньше 300×200.")

            if (max(im.size) > 10000):
                raise ValidationError(u"Пожалуйста, убедитесь, что разрешение фотографии не больше 10000×10000.")

            return image
        else:
            raise ValidationError(u"При получении изображения возникла ошибка")

    class Meta:
        model = UserProfile

class RegistrationForm(UserProfileForm):
    email = forms.EmailField(max_length=75)
    password = forms.CharField(max_length=128)

    def clean_email(self):
        email = self.cleaned_data['email'].lower()
        if User.objects.filter(email=email).exists():
            raise forms.ValidationError(u"Пользователь с таким адресом электронной почты уже есть на сайте.")

        return email

    class Meta:
        model = UserProfile
        exclude = ('user',)

Соответственно, в бэкэнде авторизации просто позволяем пользователю вводить email с использованием букв любого регистра:

class EmailAuthBackend(ModelBackend):
    def authenticate(self, email=None, password=None, **kwargs):
        if not email:
            return None

        try:
            user = User.objects.get(email__iexact=email)
        except User.DoesNotExist:
            return None
        except User.MultipleObjectsReturned:
            user = User.objects.filter(email__iexact=email)[0]

        if user.check_password(password):
            return user


К счастью, в Django 1.5 обязательность танцев с бубном заметно уменьшится в связи с появлением определяемых разработчиком моделей User.
Only those users with full accounts are able to leave comments.  , please.