Django 5 для начинающих

Прогресс по курсу:  9/1004

7.6 Улучшаем дизайн блога с использованием Bootstrap 5
7 из 7 шагов пройдено

А сейчас мы доработаем наш дизайн приложения accounts с использованием Bootstrap 5. И начнем мы со страницы авторизации, для этого откроем шаблон login.html и добавим в него следующий код:

{% extends "blog/base.html" %}
{% block title %} Login {% endblock %}
{% block content %}
    <h2> Login </h2>
    <a href="{% url 'signup' %}"  class="btn btn-link btn-lg active btn-block">SignUp</a>
    <a href="{% url 'social:begin' 'github' %}"  class="btn btn-link btn-lg active btn-block">Log In with GitHub</a>
    <a href="{% url 'social:begin' 'google-oauth2' %}" class="btn btn-link btn-lg active btn-block">Log In with Google</a>
    <form method="post" class="form">
        {{ form.username }}
        {{ form.password }}
        <div class="mb-1">Remember me: {{ form.remember_me }}</div>
        {% csrf_token %}
        <input type="submit" class="btn btn-primary btn-lg" value="Login">
    </form>
   <a href="{% url 'password_reset' %}">Reset Password</a>
{% endblock %}

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


Далее откроем наш forms.py приложения accounts и внесем изменения в наш класс LoginForm, а именно добавим новые стили к нашим полям:

class LoginForm(AuthenticationForm):
    username = forms.CharField(max_length=100,
                               required=True,
                               widget=forms.TextInput(attrs={"class": "form-control mb-1", 'placeholder': 'Username'}))
    password = forms.CharField(max_length=50,
                               required=True,
                               widget=forms.PasswordInput(
                                   attrs={"class": "form-control mb-1", 'placeholder': 'Password'}))
    remember_me = forms.BooleanField(required=False)

    class Meta:
        model = User
        fields = ['username', 'password', 'remember_me']


Проверим, что у нас получилось:


Далее давайте переработаем страницу регистрации, для этого откроем signup.html и заменим в нем код, на следующий:

{% extends "blog/base.html" %}
{% block title %} Sign Up {% endblock %}
{% block content %}
    <h2> Sign Up </h2>
    {% if form.errors %}
        <div class="container d-flex align-items-center justify-content-center">
            <div class="alert alert-warning alert-dismissible fade show w-50  d-block" role="alert">
                {% for key, value in form.errors.items %}
                    <strong>{{ value }}</strong>
                {% endfor %}
                <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
            </div>
        </div>
    {% endif %}
    <form method="post">
        {% csrf_token %}
        Username: {{ form.username }}
        E-Mail:{{ form.email }}
        First Name:{{ form.first_name }}
        Last Name: {{ form.last_name }}
        Password: {{ form.password1 }}
        {{ form.errors.password }}
        Confirm Password: {{ form.password2 }}
        <button type="submit" class="btn btn-primary btn-lg">Sign Up</button>
    </form>
    <a href="/accounts/login/">Have an account? Go to Log In</a>
{% endblock %}

Мы немного изменили обработку ошибок, добавив их отображение в модальном окне.


Давайте теперь изменим класс SignUpForm в forms.py:

class SignUpForm(UserCreationForm):
    first_name = forms.CharField(max_length=100, widget=forms.TextInput(
        attrs={"class": "form-control mb-1", 'placeholder': 'Enter First Name'}))
    last_name = forms.CharField(max_length=100, widget=forms.TextInput(
        attrs={"class": "form-control mb-1", 'placeholder': 'Enter Last Name'}))
    username = forms.CharField(max_length=100, widget=forms.TextInput(
        attrs={"class": "form-control mb-1", 'placeholder': 'Enter Username'}))
    email = forms.EmailField(
        widget=forms.TextInput(attrs={"class": "form-control mb-1", 'placeholder': 'Enter your E-Mail'}))
    password1 = forms.CharField(max_length=50, widget=forms.PasswordInput(
        attrs={"class": "form-control mb-1", 'placeholder': 'Enter password'}))
    password2 = forms.CharField(max_length=50, widget=forms.PasswordInput(
        attrs={"class": "form-control mb-1", 'placeholder': 'Confirm Password'}))

    class Meta:
        model = User
        fields = ['username', 'first_name', 'last_name', 'email', 'password1', 'password2']


Мы также добавили стили к нашим полям и добавили текстовые подсказки. Проверим работу:


Проверим работу модального окна, попробовав зарегистрировать нового пользователя, намеренно совершая ошибки в заполнении полей:


Модальное окно прекрасно работает, можно прочитать данные ошибки и убрать его.


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

Плавающие метки + проверка уникальности введенного Email

signup.html - только форма

    <form method="post">
        {% csrf_token %}
        {% for field in form %}
            <div class="form-floating mb-1">
            {{ field }}
            <label for="{{ field.id_for_label }}">{{ field.label }}</label>
            </div>
        {% endfor %}

        <button type="submit" class="btn btn-primary btn-lg">Sign Up</button>
    </form>

И форма целиком из forms.py:

class SignUpForm(UserCreationForm):
    username = forms.CharField(widget=forms.TextInput(attrs={"class": "form-control mb-1", 'placeholder': ''}),
                               label='Логин')
    first_name = forms.CharField(widget=forms.TextInput(attrs={"class": "form-control mb-1", 'placeholder': ''}),
                                 label='Имя')
    last_name = forms.CharField(widget=forms.TextInput(attrs={"class": "form-control mb-1", 'placeholder': ''}),
                                label='Фамилия')
    email = forms.EmailField(widget=forms.TextInput(attrs={"class": "form-control mb-1", 'placeholder': ''}),
                             label='Email')
    password1 = forms.CharField(widget=forms.PasswordInput(attrs={"class": "form-control mb-1", 'placeholder': ''}),
                                label='Введите пароль')
    password2 = forms.CharField(widget=forms.PasswordInput(attrs={"class": "form-control mb-1", 'placeholder': ''}),
                                label='Подтвердите пароль')

    class Meta:
        model = get_user_model()
        fields = ['username', 'first_name', 'last_name', 'email', 'password1', 'password2']

    def clean_email(self):
        email = self.cleaned_data['email']
        users = get_user_model()
        if users.objects.filter(email=email).exists():
            raise ValidationError(f'Entered email {email} already used in the database, please use another one')
        return email

Попробовал как-то автоматизировать присвоение widget'а полям - через __init__(), примерно как описано в документации, но так не получилось, ругается на атрибуты BoundField

Изменен ilya kutaev