Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

lesson_1 #1

Open
wants to merge 63 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
3e98b21
add project and app
t-rexamarin Nov 12, 2021
11e6beb
add app in settings
t-rexamarin Nov 12, 2021
73148ca
add templates index and products
t-rexamarin Nov 12, 2021
b879924
add two controllers and urls
t-rexamarin Nov 12, 2021
6fd6487
add static
t-rexamarin Nov 12, 2021
9f55f1f
add pycache to gitignore
t-rexamarin Nov 12, 2021
50a409f
fixed pycache name
t-rexamarin Nov 14, 2021
42291b1
created fixture for products
t-rexamarin Nov 14, 2021
14aa557
dynamic content for index.html
t-rexamarin Nov 14, 2021
68010b6
create model for Products
t-rexamarin Nov 14, 2021
8860a7c
add model Products in admin panel
t-rexamarin Nov 14, 2021
b809e7a
fix Products model
t-rexamarin Nov 14, 2021
509e9a9
add dynamic static
t-rexamarin Nov 15, 2021
c5d8823
add title in index, products controllers
t-rexamarin Nov 15, 2021
10752a4
add dynamic static path to images
t-rexamarin Nov 15, 2021
11d6365
add dynamic urls
t-rexamarin Nov 15, 2021
68782b1
add img_name attribute to model Product and fixture
t-rexamarin Nov 15, 2021
72b8518
1) add dynamic products load in product.html
t-rexamarin Nov 15, 2021
5852ba3
models update
t-rexamarin Nov 18, 2021
31fd528
add media settings
t-rexamarin Nov 18, 2021
31eed1e
fix Product model usage in views
t-rexamarin Nov 18, 2021
35d388d
base, index fix product path
t-rexamarin Nov 19, 2021
bcd9c04
fix include path
t-rexamarin Nov 19, 2021
561afa0
small fixes
t-rexamarin Nov 19, 2021
a179e14
add fixture categories
t-rexamarin Nov 19, 2021
e70d472
models update
t-rexamarin Nov 19, 2021
6f9f7fc
add dynamic categories
t-rexamarin Nov 19, 2021
34426b1
add categories
t-rexamarin Nov 19, 2021
8729a4c
add all products media/product_image
t-rexamarin Nov 20, 2021
a52a739
add fill_db
t-rexamarin Nov 21, 2021
f5eb417
init authapp:
t-rexamarin Nov 21, 2021
78f8754
add authapp templates
t-rexamarin Nov 21, 2021
fadb4c2
add dynamic url for authapp
t-rexamarin Nov 21, 2021
ee01007
working login and registration forms
t-rexamarin Nov 21, 2021
f17a9f5
change timezone to utc+3
t-rexamarin Nov 22, 2021
ff9a115
add date fields
t-rexamarin Nov 22, 2021
c5052a5
add dynamic menu buttons for registered/unregistered user
t-rexamarin Nov 22, 2021
e02e34e
small fixes for logged in user
t-rexamarin Nov 22, 2021
fe15e0b
add logout mechanism
t-rexamarin Nov 22, 2021
a3ed734
add couple custom validators to registration form fields
t-rexamarin Nov 23, 2021
f8b6d02
add custom numeric password validator, it's replace default from django
t-rexamarin Nov 23, 2021
99d3ed5
1) refactored form errors printing
t-rexamarin Nov 26, 2021
1b35ff8
1) add profile template, url, view
t-rexamarin Nov 26, 2021
93bbe4d
add profile dynamic form
t-rexamarin Nov 26, 2021
3664928
add profile edit
t-rexamarin Nov 27, 2021
20023be
init baskets app
t-rexamarin Nov 27, 2021
80cd5ff
1) add basket url
t-rexamarin Nov 27, 2021
940c4fc
add dynamic basket items sum
t-rexamarin Nov 27, 2021
899d1f6
add basket remove
t-rexamarin Nov 27, 2021
fa8a86a
add redirect to login page for unauthorized user
t-rexamarin Nov 27, 2021
46eed5a
change profile form not working validator
t-rexamarin Nov 27, 2021
6440b65
1) change profile first_name validator
t-rexamarin Nov 28, 2021
b0b6a1c
dynamic total_quantity and total_sum in template
t-rexamarin Nov 28, 2021
e978c46
errors printing in template
t-rexamarin Nov 28, 2021
a0a3c5a
add user basket ajax
t-rexamarin Nov 28, 2021
6e9f516
add products ajax
t-rexamarin Nov 29, 2021
eb55247
1) individual item card
t-rexamarin Nov 29, 2021
e7ac921
move carosel element to includes
t-rexamarin Nov 30, 2021
a74e69a
1) now ajax on main page with products
t-rexamarin Nov 30, 2021
465e3e5
add custom alert on add product button
t-rexamarin Dec 1, 2021
89eb0ec
small js fix
t-rexamarin Dec 1, 2021
949eb6a
Merge remote-tracking branch 'origin/lesson_6' into lesson_6
t-rexamarin Dec 1, 2021
abe38d2
Merge pull request #6 from t-rexamarin/lesson_6
t-rexamarin Dec 1, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion geekshop/.gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
/.idea
db.sqlite3
db.sqlite3
__pycache__/
Empty file added geekshop/authapp/__init__.py
Empty file.
5 changes: 5 additions & 0 deletions geekshop/authapp/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from django.contrib import admin
from authapp.models import User

# Register your models here.
admin.site.register(User)
6 changes: 6 additions & 0 deletions geekshop/authapp/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from django.apps import AppConfig


class AuthappConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'authapp'
87 changes: 87 additions & 0 deletions geekshop/authapp/forms.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
from django.contrib.auth.forms import UserCreationForm, AuthenticationForm, UserChangeForm
from django.core.exceptions import ValidationError
from django.utils.translation import gettext as _
from authapp.models import User
from django import forms

from authapp.validators import clean_firstname


class UserLoginForm(AuthenticationForm):
class Meta:
model = User
fields = ('username', 'password')

def __init__(self, *args, **kwargs):
super(UserLoginForm, self).__init__(*args, **kwargs)
self.fields['username'].widget.attrs['placeholder'] = 'Введите имя пользователя'
self.fields['password'].widget.attrs['placeholder'] = 'Введите пароль'

for field_name, field in self.fields.items():
field.widget.attrs['class'] = 'form-control py-4'


class UserRegistrationForm(UserCreationForm):
class Meta:
model = User
fields = ('username', 'email', 'first_name', 'last_name', 'password1', 'password2')

def __init__(self, *args, **kwargs):
super(UserRegistrationForm, self).__init__(*args, **kwargs)
self.fields['username'].widget.attrs['placeholder'] = 'Введите имя пользователя'
self.fields['email'].widget.attrs['placeholder'] = 'Введите адрес эл. почты'
self.fields['first_name'].widget.attrs['placeholder'] = 'Введите имя'
self.fields['last_name'].widget.attrs['placeholder'] = 'Введите фамилию'
self.fields['password1'].widget.attrs['placeholder'] = 'Введите пароль'
self.fields['password2'].widget.attrs['placeholder'] = 'Повторите пароль'

for field_name, field in self.fields.items():
field.widget.attrs['class'] = 'form-control py-4'

# сами определяем валидаторы для полей
def clean_username(self):
username = self.cleaned_data['username']
errors = []
errors_status = 0

if User.objects.filter(username=username).exists():
errors_status = 1
errors.append(ValidationError(_('Username already taken.')))
# raise ValidationError(_('Username already taken'))

banned_usernames = ['банан', 'дурак', 'django']
username_l = username.lower()
if username_l in banned_usernames:
errors_status = 1
errors.append(ValidationError(_(f'Username {username_l} is not allowed.')))
# raise ValidationError(_(f'Username {username_l} is not allowed'))

if errors_status:
raise ValidationError(errors)

return username

def clean_email(self):
email = self.cleaned_data['email']
if User.objects.filter(email=email).exists():
raise ValidationError(_('Email already taken.'))
return email


class UserChangeProfileForm(UserChangeForm):
first_name = forms.CharField(widget=forms.TextInput(), validators=[clean_firstname])
age = forms.IntegerField(widget=forms.NumberInput(), required=False)
image = forms.ImageField(widget=forms.FileInput(), required=False)

class Meta:
model = User
fields = ('username', 'email', 'first_name', 'last_name', 'age', 'image')

def __init__(self, *args, **kwargs):
super(UserChangeProfileForm, self).__init__(*args, **kwargs)
self.fields['username'].widget.attrs['readonly'] = True
self.fields['email'].widget.attrs['readonly'] = True

for field_name, field in self.fields.items():
field.widget.attrs['class'] = 'form-control py-4'
self.fields['image'].widget.attrs['class'] = 'custom-file-input'
Empty file.
13 changes: 13 additions & 0 deletions geekshop/authapp/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from django.contrib.auth.models import AbstractUser
from django.db import models
from django.utils.timezone import now


# Create your models here.
class User(AbstractUser):
image = models.ImageField(upload_to='users_image', blank=True)
age = models.PositiveIntegerField(default=18)
# created_at = models.DateTimeField(verbose_name='дата создания', auto_now_add=True)
# если указывать now(), а не now, то при создании миграции будет высвечивать ворнинг Fixed default value provided
created_at = models.DateTimeField(verbose_name='дата создания', default=now)
updated_at = models.DateTimeField(verbose_name='дата изменения', auto_now=True)
34 changes: 34 additions & 0 deletions geekshop/authapp/templates/authapp/base.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{% load static %}

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/>
<meta name="description" content=""/>
<meta name="author" content=""/>
<title>{{ title }}</title>
<link href="{% static 'css/auth-admin.css' %}" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.1/js/all.min.js"
crossorigin="anonymous"></script>
</head>
<body class="bg-primary">
<div id="layoutAuthentication">
<div id="layoutAuthentication_content">
<main>
<div class="container">
<div class="row justify-content-center">
{% block content %}
{% endblock %}
</div>
</div>
</main>
</div>
</div>
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"
crossorigin="anonymous"></script>
<script src="{% static 'js/auth-admin.js' %}"></script>
</body>
</html>
52 changes: 52 additions & 0 deletions geekshop/authapp/templates/authapp/login.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
{% extends 'authapp/base.html' %}

{% block content %}
<div class="col-lg-5">

{% if form.non_field_errors or messages %}
<div class="alert {% if messages %} alert-success {% else %} alert-warning {% endif %} alert-dismissible fade show" role="alert"
style="margin-top: 50px;">

{% if messages %}
{% for message in messages %}
<strong>{{ message }}</strong>
{% endfor %}
{% else %}
{% for error in form.non_field_errors %}
<strong>{{ error|escape }}</strong>
{% endfor %}
{% endif %}

<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
{% endif %}

<div class="card shadow-lg border-0 rounded-lg mt-5">
<div class="card-header"><h3 class="text-center font-weight-light my-4">Авторизация</h3>
</div>
<div class="card-body">
<form action="{% url 'authapp:login' %}" method="post">
{% csrf_token %}
<div class="form-group">
<label class="small mb-1" for="{{ form.username.id_for_label }}">Имя пользователя</label>
{{ form.username }}
</div>
<div class="form-group">
<label class="small mb-1" for="{{ form.password.id_for_label }}">Пароль</label>
{{ form.password }}
</div>
<div class="form-group d-flex align-items-center justify-content-between mt-4 mb-0">
<a class="small" href="#">Забыли пароль?</a>
<input class="btn btn-primary" type="submit" value="Авторизоваться">
</div>
</form>
</div>
<div class="card-footer text-center">
<div class="small"><a href="{% url 'authapp:registration' %}">Нужен аккаунт? Зарегистрируйся!</a></div>
</div>
</div>
</div>
{% endblock %}

101 changes: 101 additions & 0 deletions geekshop/authapp/templates/authapp/profile.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
{% extends 'mainapp/base.html' %}
{% load static %}

{% block css %}
<link href="{% static 'css/profile.css' %}" rel="stylesheet">
{% endblock %}

{% block content %}
<div class="container">
<div class="row">
<div class="col-lg-7">

{% if messages %}
{% for message in messages %}
<div class="alert {% if message.level == DEFAULT_MESSAGE_LEVELS.SUCCESS %} alert-success {% else %} alert-warning {% endif %} alert-dismissible fade show" role="alert"
style="margin-top: 50px;">
{% if message.level == DEFAULT_MESSAGE_LEVELS.ERROR %}
{% for msgs in message.message %}
{% for msg in msgs %}
<strong>{{ msg }}</strong>
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
<br>
{% endfor %}
{% endfor %}
{% else %}
<strong>{{ message|striptags }}</strong>
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
{% endif %}
</div>
{% endfor %}
{% endif %}

<h4 class="mt-3 mb-3">Профиль</h4>
<div class="col-lg-12 text-center">
<img width="100" height="100"
src="
{% if user.image %}
{{ user.image.url }}
{% else %}
{% static 'vendor/img/users/default_avatar.jpg' %}
{% endif %}"
class="img-thumbnail">
</div>
<form action="{% url 'authapp:profile' %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
<div class="form-row">
<div class="col-lg-6">
<div class="form-group">
<label class="small mb-1" for="{{ form.first_name.id_for_label }}">Имя</label>
{{ form.first_name }}
</div>
</div>
<div class="col-lg-6">
<div class="form-group">
<label class="small mb-1" for="{{ form.last_name.id_for_label }}">Фамилия</label>
{{ form.last_name }}
</div>
</div>
</div>
<div class="form-row mb-2">
<div class="col-lg-12">
<div class="custom-file">
{{ form.image }}
<label class="custom-file-label" for="{{ form.image.id_for_label }}">Выберите изображение</label>
</div>
</div>
</div>
<div class="form-row">
<div class="col-lg-6">
<label class="small mb-1" for="{{ form.username.id_for_label }}">Имя пользователя</label>
{{ form.username }}
</div>
<div class="col-lg-6">
<label class="small mb-1" for="{{ form.email.id_for_label }}">Адрес электронной
почты</label>
{{ form.email }}
</div>
</div>
<div class="form-row">
<div class="col-lg-6">
<label class="small mb-1" for="{{ form.age.id_for_label }}">Возраст</label>
{{ form.age }}
</div>
</div>
<div class="form-row">
<div class="col-lg-12" style="margin-top: 33px;">
<input class="btn btn-info btn-block" type="submit" value="Сохранить">
</div>
</div>
</form>
</div>
<div class="col-lg-5">
{% include 'baskets/basket.html' %}
</div>
</div>
</div>
{% endblock %}
78 changes: 78 additions & 0 deletions geekshop/authapp/templates/authapp/registration.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
{% extends 'authapp/base.html' %}

{% block content %}
<div class="col-lg-7">

{% if form.errors %}
<div class="alert alert-warning alert-dismissible fade show" role="alert"
style="margin-top: 50px;">

{% for field in form %}
{% for error in field.errors %}
<strong>{{ error|escape }}</strong><br/>
{% endfor %}
{% endfor %}

<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
{% endif %}

<div class="card shadow-lg border-0 rounded-lg mt-5">
<div class="card-header"><h3 class="text-center font-weight-light my-4">Создать аккаунт</h3>
</div>
<div class="card-body">
<form action="{% url 'authapp:registration' %}" method="post">
{% csrf_token %}
<div class="form-row">
<div class="col-md-6">
<div class="form-group">
<label class="small mb-1" for="{{ form.username.id_for_label }}">Имя пользователя</label>
{{ form.username }}
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label class="small mb-1" for="{{ form.email.id_for_label }}">Адрес электронной
почты</label>
{{ form.email }}
</div>
</div>
</div>
<div class="form-row">
<div class="col-md-6">
<label class="small mb-1" for="{{ form.first_name.id_for_label }}">Имя</label>
{{ form.first_name }}
</div>
<div class="col-md-6">
<label class="small mb-1" for="{{ form.last_name.id_for_label }}">Фамилия</label>
{{ form.last_name }}
</div>
</div>
<div class="form-row">
<div class="col-md-6">
<div class="form-group">
<label class="small mb-1" for="{{ form.password1.id_for_label }}">Пароль</label>
{{ form.password1 }}
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label class="small mb-1" for="{{ form.password2.id_for_label }}">Подтверждение
пароля</label>
{{ form.password2 }}
</div>
</div>
</div>
<div class="form-group mt-4 mb-0">
<input class="btn btn-primary btn-block" type="submit" value="Создать аккаунт">
</div>
</form>
</div>
<div class="card-footer text-center">
<div class="small"><a href="{% url 'authapp:login' %}">Уже есть аккаунт? Авторизоваться</a></div>
</div>
</div>
</div>
{% endblock %}
3 changes: 3 additions & 0 deletions geekshop/authapp/tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from django.test import TestCase

# Create your tests here.
Loading