diff --git a/README.md b/README.md index fa52ce0..d260e37 100644 --- a/README.md +++ b/README.md @@ -7,4 +7,4 @@ Tasks and projects from the Learn Python course
If you find something useful - put a star! Thank you =)
-[![Stargazers repo roster for @Sinrez/pyCoursera](https://reporoster.com/stars/dark/Sinrez/learn_python_course)](https://github.com/Sinrez/learn_python_course/stargazers) + diff --git a/bank_bottom_proj/webapp_bottom/__init__.py b/bank_bottom_proj/webapp_bottom/__init__.py index 9c844d1..16c6712 100644 --- a/bank_bottom_proj/webapp_bottom/__init__.py +++ b/bank_bottom_proj/webapp_bottom/__init__.py @@ -25,18 +25,20 @@ def create_app(): db.init_app(app) migrate = Migrate(app, db) - def get_count_from_db(days=15, cat = ''): + def get_count_from_db(days=7, cat = ''): delta = datetime.timedelta(days) now_day = datetime.date.today() delta_days = now_day - delta + print(delta_days) date_obj = datetime.datetime.strptime(str(delta_days), '%Y-%m-%d') formatted_date_str = date_obj.strftime('%d.%m.%Y') + print(formatted_date_str) # в зависимости наличия катеогории или возвращаем все отзывы или по категориям if not cat: - qr = db.session.query(Feedback.bank_name,db.func.count(Feedback.url_page)).filter(Feedback.response_date >= formatted_date_str).group_by(Feedback.bank_name).having(db.func.count(Feedback.url_page) > 10).order_by(db.func.count(Feedback.url_page).desc()).all() + qr = db.session.query(Feedback.bank_name,db.func.count(Feedback.url_page)).filter(Feedback.response_date >= formatted_date_str).group_by(Feedback.bank_name).having(db.func.count(Feedback.url_page) >= 1).order_by(db.func.count(Feedback.url_page).desc()).all() return qr else: - qr = db.session.query(Feedback.bank_name,db.func.count(Feedback.url_page)).filter(Feedback.response_date >= formatted_date_str).filter(Feedback.category == cat).group_by(Feedback.bank_name).having(db.func.count(Feedback.url_page) > 5).order_by(db.func.count(Feedback.url_page).desc()).all() + qr = db.session.query(Feedback.bank_name,db.func.count(Feedback.url_page)).filter(Feedback.response_date >= formatted_date_str).filter(Feedback.category == cat).group_by(Feedback.bank_name).having(db.func.count(Feedback.url_page) >= 1).order_by(db.func.count(Feedback.url_page).desc()).all() return qr @app.route('/bottom/api/v1.0/weeklyfeedback', methods=['GET']) diff --git a/bank_bottom_proj/webapp_bottom/bottom_parser.py b/bank_bottom_proj/webapp_bottom/bottom_parser.py index 11ed01e..8f6d0f4 100644 --- a/bank_bottom_proj/webapp_bottom/bottom_parser.py +++ b/bank_bottom_proj/webapp_bottom/bottom_parser.py @@ -13,19 +13,22 @@ from config import categories from check_resource import check_url -def page_fliper(categories: list = categories, start: int = 1, limit: int = 4) -> None: +def page_fliper(categories: list = categories, start: int = 1, limit: int = 3) -> None: # limit = 150 #1440 - c начала 22 - # limit = 4 # !!!cтавим на период теста чтобы не дудосить!!! + # limit = 3 или 4 # !!!cтавим на период теста чтобы не дудосить!!! url_base_site = 'https://www.banki.ru' check_url(url_base_site) for cat in categories: + print(f'Обрабатываю категорию {cat}') + print() #цикл перебора следуюших страниц, так как есть параметр page= и с ним не вытащить ссылки из цикла выше for l in range(start, limit+1): url_categor_history = f'https://www.banki.ru/services/responses/list/product/{cat}/?page={l}&is_countable=on&rate[]=1&rate[]=2' + print(url_categor_history) for url in urls_parser(url_categor_history,url_base_site): - check_url(url) if url: + # print(url) try: *result, = page_parser(url, cat) save_response(*result) @@ -33,7 +36,8 @@ def page_fliper(categories: list = categories, start: int = 1, limit: int = 4) - print(''.join(result)) print(f'Ошибка: {te}') exit() - sleep(randint(1,2)) + sleep(randint(2,3)) + sleep(randint(1,2)) def urls_parser(url_in: str, url_base_site: str) -> list: url_from_parse = [] @@ -74,7 +78,7 @@ def page_parser(url_page: str, category: str ='') -> tuple: #получаем id отзыва id_url = url_page.split('/')[7] except AttributeError as ar: - return f'Произошла ошибка в блоке BeautifulSoup парсинга: {ar}' + return f'Произошла ошибка в блоке BeautifulSoup парсинга: {ar} на {url_page}' except Exception as ex: return f'Произошла ошибка в функции page_parser: {ex}' return id_url, url_page, bank_name, category, short_feedback, response_date, response_city, response_full diff --git a/dogs_around/.gitignore b/dogs_around/.gitignore new file mode 100644 index 0000000..c4197bf --- /dev/null +++ b/dogs_around/.gitignore @@ -0,0 +1,39 @@ +*.pyc +*.egg-info + +# Если вы программируете на Mac +.DS_Store +../.DS_Store + +# Если вы пользуетесь виртуальными окружениями +/env +/env_dogs +/res.txt +/bs.txt + +# Настройки и хранение секретных данных +/.env +/.env_dogs +settings.py +*.log +.db +.vscode/ +.idea/ +env/ +.DS_Store +__pycache__/ +config.py +__pycache__/ +.vscode/ +env/ +drafts +vscode +DS_Store +dogs.db +dogs +celerybeat-schedule.db +celerybeat-schedule +.sqbpro +/.sqbpro +.sqbpro/ +sqbpro diff --git a/dogs_around/README.md b/dogs_around/README.md new file mode 100644 index 0000000..8f3b2bf --- /dev/null +++ b/dogs_around/README.md @@ -0,0 +1,18 @@ +# Dogs Around + +Собакруг- это pat-проект, MVP0, социальной сети для собак. Основная идея - объединение собаководов для совместного выгула собак, концепт может дорабатываться. Идея "круга" - возможное объединение по близким локациям для выгула. +Это проект монолитной архитектуры, разработанный на Python. Ядро - Flask + DB SQLlite. + +На этапе MVP0 реализован основной функционал: добавление пользователя, добавление его собак(и), добавление в друзья других собак. Реализована функция аутентификации, валидации полей ввода. + +UI выполнен достаточно просто, так как основная цель проекта была отработать функционирования back-end части. +Соц сеть может быть адаптирована не только для собак, но и доработана под другие предметные области. + + +DogsAround is a pat project, MVP0, a social network for dogs. The main idea is to unite dog breeders for joint dog walking, the concept can be finalized. +This is a monolithic architecture project developed in Python. The core is Flask + DB Sqlite. + +At the MVP 0 stage, the main functionality is implemented: adding a user, adding his dogs (and), adding other dogs to friends. The function of authentication, validation of input fields is implemented. + +The UI is quite simple, since the main goal of the project was to work out the functioning of the back-end part. +The social network can be adapted not only for dogs, but also modified for other subject areas. \ No newline at end of file diff --git a/dogs_around/create_db.py b/dogs_around/create_db.py new file mode 100644 index 0000000..39012a7 --- /dev/null +++ b/dogs_around/create_db.py @@ -0,0 +1,11 @@ +#это локальные костыли для доступности вспомогательных файлов, добавлять перед импортом основных библиотек +import sys +sys.path.append('..') +sys.path.append('/Volumes/D/learn_python_course/dogs_around/webapp_dogs') + +from webapp_dogs import create_app +from webapp_dogs.model import db + +app = create_app() +with app.app_context(): + db.create_all() \ No newline at end of file diff --git a/dogs_around/requirements.txt b/dogs_around/requirements.txt new file mode 100644 index 0000000..aa91330 --- /dev/null +++ b/dogs_around/requirements.txt @@ -0,0 +1,31 @@ +certifi==2022.12.7 +charset-normalizer==3.0.1 +click==8.1.3 +Flask==2.2.3 +Flask-Login==0.6.2 +Flask-SQLAlchemy==3.0.3 +Flask-WTF==1.1.1 +idna==3.4 +itsdangerous==2.1.2 +Jinja2==3.1.2 +MarkupSafe==2.1.2 +requests==2.28.2 +soupsieve==2.4 +SQLAlchemy==2.0.4 +typing_extensions==4.5.0 +urllib3==1.26.14 +Werkzeug==2.2.3 +WTForms==3.0.1 +flask-migrate==4.0.4 +bokeh==3.1.0 +plotly==5.13.1 +cffi==1.14.0 +cryptography==2.9.2 +decorator==4.4.2 +future==0.18.2 +pycparser==2.20 +PySocks==1.7.1 +python-telegram-bot==12.7 +six==1.14.0 +tornado==6.0.4 +emoji==0.5.4 diff --git a/dogs_around/run.sh b/dogs_around/run.sh new file mode 100755 index 0000000..29520ef --- /dev/null +++ b/dogs_around/run.sh @@ -0,0 +1,2 @@ +#!/bin/sh +export FLASK_APP=webapp_dogs && export FLASK_ENV=development && flask run \ No newline at end of file diff --git a/dogs_around/webapp_dogs/__init__.py b/dogs_around/webapp_dogs/__init__.py new file mode 100644 index 0000000..8256918 --- /dev/null +++ b/dogs_around/webapp_dogs/__init__.py @@ -0,0 +1,214 @@ +# source env_dogs/bin/activate +# ./run.sh + +from flask import Flask, render_template, flash, redirect, url_for,request, session, jsonify, abort +from datetime import datetime +from wtforms.validators import DataRequired, Length, ValidationError +from flask_wtf import FlaskForm, csrf +from wtforms import StringField, SubmitField +from webapp_dogs import config +from werkzeug.security import generate_password_hash +from webapp_dogs.model import db, User, Dog, get_user_dogs, Friendship, FrendStatusEnum +from webapp_dogs.forms import RegistrationForm, DogForm , LoginForm +from webapp_dogs.utils_dog import generate_id_user, get_or_create_user, generate_id_dog, get_or_create_dog +from flask_login import LoginManager,login_user, logout_user, current_user, login_required + +def create_app(): + app = Flask(__name__) + app.secret_key = config.SECRET_KEY + app.config.from_pyfile('config.py') + db.init_app(app) + + login_manager = LoginManager() + login_manager.init_app(app) + login_manager.login_view = 'login' + + @login_manager.user_loader + def load_user(user_id): + return User.query.get(user_id) + + @app.route("/") + def index(): + title = 'Собакруг' + dogs = Dog.query.order_by(Dog.response_date.desc()).all() + return render_template('index.html', page_title=title, dogs= dogs) + + @app.route("/cabinet") + def cabinet(): + title = 'Мой профиль' + email = session.get('email') + dogs = Dog.query.order_by(Dog.response_date.desc()).all() + print(dogs) + my_dogs = get_user_dogs(email) + res_my_dogs = ', '.join([dog.name_dog for dog in my_dogs]) + return render_template('cabinet.html', page_title=title, dogs= dogs, my_dogs = res_my_dogs, email = email) + + @app.route("/profile") + def profile(): + email = session.get('email') + user = User.query.filter_by(email=email).first() + title = 'Мой профиль' + + return render_template('profile.html', page_title=title, user=user) + + @app.route('/dog/') + def profile_dog(dog_id): + email = session.get('email') + dog = Dog.query.filter_by(id_dog=dog_id).first() + title = 'Профиль собачки' + return render_template('profile_dog.html', page_title=title, dog=dog) + + @app.route('/add_friend/', methods=['POST']) + @login_required + def add_friend(dog_id): + # user_id = session.get('user_id') + email = session.get('email') + my_dog = get_user_dogs(email)[0] + dog = Dog.query.get(dog_id) + if dog is None: + abort(404) + print(current_user.id_user) + print(my_dog) + if my_dog: + friendship_request = Friendship(sender_dog_id=my_dog.id_dog, receiver_dog_id=dog_id) + db.session.add(friendship_request) + db.session.commit() + flash(f'Вы отправили запрос на дружбу {dog.name_dog}!', 'success') + else: + flash('Произошла ошибка! Попробуйте еще раз.', 'danger') + return redirect(url_for('user_dogs')) + + @app.route('/accept_request/') + def accept_request(id_dog): + request = Friendship.query.filter_by(sender_dog_id=id_dog, status=FrendStatusEnum.pending.value).first() + if request: + request.accept_request() + return redirect(url_for('user_dogs')) + + @app.route('/reject_request/') + def reject_request(id_dog): + request = Friendship.query.filter_by(sender_dog_id=id_dog, status=FrendStatusEnum.pending.value).first() + if request: + request.decline_request() + return redirect(url_for('user_dogs')) + + + @app.route('/login', methods=['GET', 'POST']) + def login(): + title = "Авторизация" + form = LoginForm() + email = None + + if request.method == 'POST' and form.validate(): + user = User.query.filter_by(email=form.email.data).first() + if user and user.check_password(form.password.data): + login_user(user) # авторизация пользователя + print(user.get_mail()) + email = user.get_mail() + session['email'] = email + user_id = user.get_id() + session['user_id'] = user_id + flash('Вы успешно авторизовались!', 'success') + next_page = request.args.get('next') # получаем параметр next из URL + if next_page: + return redirect(next_page) # если параметр есть, переходим по нему + else: + return redirect(url_for('cabinet')) + else: + flash('Неправильное имя пользователя или пароль', 'danger') + + return render_template('login.html', form=form, title=title, email=email) + + @app.route('/logout') + def logout(): + logout_user() + flash('Вы успешно разлогинились') + return redirect(url_for('index')) + + @app.route('/registration', methods=['GET', 'POST']) + def registration(): + form = RegistrationForm() + if request.method == 'POST' and form.validate_on_submit(): + # Получение данных из формы + id_user = generate_id_user() + first_name = request.form['first_name'] + last_name = request.form['last_name'] + user_name = request.form['user_name'] + email = request.form['email'] + password = request.form['password'] + confirm_password = request.form['confirm_password'] + + # Валидация данных + error = None + if not first_name: + error = 'Имя пользователя обязательно для заполнения.' + elif not last_name: + error = 'Фамилия пользователя обязательна для заполнения.' + elif not password: + error = 'Пароль обязателен для заполнения.' + elif password != confirm_password: + error = 'Пароли не совпадают.' + + if error is None: + # Сохранение данных в бд + hashed_password = generate_password_hash(password) + res = get_or_create_user(id_user,first_name, last_name, user_name, email, hashed_password) + if res: + return redirect(url_for('login')) + # Если данные не прошли валидацию, показываем ошибки пользователю + return render_template('registration.html', error=error) + else: + print(form.errors) + # Если метод запроса GET, просто отображаем шаблон + return render_template('registration.html', form=form) + + @app.route('/user_dogs', methods=['GET']) + def user_dogs(): + email = session.get('email') # получаем email пользователя из запроса + print(email) + user_dogs = get_user_dogs(email) + print(user_dogs) + friend_requests = [dog.get_friend_requests() for dog in user_dogs][0] + print(f'Список запросов в друзья: {friend_requests}') + friends = [dog.get_friends() for dog in user_dogs][0] + print(friends) + if user_dogs: + return render_template('user_dogs.html', dogs= user_dogs, email = email, friend_requests = friend_requests, friends= friends) + else: + return {'message': 'User not found'}, 404 # возвращаем сообщение об ошибке, если пользователь не найден + + @app.route('/register_dog', methods=['GET', 'POST']) + @login_required + def register_dog(): + form = DogForm() + if request.method == 'POST' and form.validate_on_submit(): + username = current_user.email + print(username) + name_dog = form.name_dog.data + age_dog = form.age_dog.data + breed_dog = form.breed_dog.data + response_date = datetime.now() + city_dog = form.city_dog.data + foto_dog = form.foto_dog.data + voice_dog = form.voice_dog.data + id_dog = generate_id_dog(name_dog, age_dog, breed_dog, response_date, city_dog) + + # Валидация данных + error = None + if not name_dog: + error = 'Кличка собаки обязательна для заполнения.' + elif not age_dog: + error = 'Возраст собаки обязателен для заполнения.' + elif not breed_dog: + error = 'Порода обязательна для заполнения.' + elif not city_dog: + error = 'Город обязателе для заполнения.' + + if error is None: + get_or_create_dog(id_dog,name_dog, age_dog, breed_dog, response_date,city_dog, foto_dog, voice_dog, username) + flash('Респекты, ваш песель зарегистрирован!') + return redirect(url_for('cabinet')) + else: + print(form.errors) + return render_template('register_dog.html', form=form) + return app \ No newline at end of file diff --git a/dogs_around/webapp_dogs/forms.py b/dogs_around/webapp_dogs/forms.py new file mode 100644 index 0000000..309d79b --- /dev/null +++ b/dogs_around/webapp_dogs/forms.py @@ -0,0 +1,28 @@ +from flask_wtf import FlaskForm, CSRFProtect +from wtforms import StringField, PasswordField, SubmitField +from wtforms.validators import DataRequired, EqualTo, Email, Length + +csrf = CSRFProtect() + +class LoginForm(FlaskForm): + email = StringField('Почта пользователя', validators=[DataRequired()]) + password = PasswordField('Пароль', validators=[DataRequired()]) + submit = SubmitField('Отправить') + +class RegistrationForm(FlaskForm): + first_name = StringField('Имя пользователя', validators=[DataRequired(), Length(max=100)]) + last_name = StringField('Фамилия пользователя', validators=[DataRequired(),Length(max=200)]) + user_name = StringField('Ник пользователя', validators=[DataRequired()]) + email = StringField('Email', validators=[DataRequired(), Length(max=120)]) + password = PasswordField('Пароль', validators=[DataRequired()]) + confirm_password = PasswordField('Подтвердите пароль', validators=[DataRequired(), EqualTo('password')]) + submit = SubmitField('Зарегистрироваться') + +class DogForm(FlaskForm): + name_dog = StringField('Имя собаки', validators=[DataRequired()]) + age_dog = StringField('Возраст собаки', validators=[DataRequired()]) + breed_dog = StringField('Порода собаки', validators=[DataRequired()]) + city_dog = StringField('Город', validators=[DataRequired()]) + foto_dog = StringField('Фото собаки', validators=[DataRequired()]) + voice_dog = StringField('Голос собаки', validators=[DataRequired()]) + submit = SubmitField('Отправить') diff --git a/dogs_around/webapp_dogs/model.py b/dogs_around/webapp_dogs/model.py new file mode 100644 index 0000000..2db71bc --- /dev/null +++ b/dogs_around/webapp_dogs/model.py @@ -0,0 +1,127 @@ +from flask_sqlalchemy import SQLAlchemy +import enum +from werkzeug.security import check_password_hash +from flask_login import UserMixin + +db = SQLAlchemy() + +def get_user_dogs(email): + user = User.query.filter_by(email=email).first() # ищем пользователя в базе данных по email + if user: + dogs = user.dogs # получаем список собак, связанных с данным пользователем + print(dogs) + return dogs + +#для обарботки статусов дружбы accepted, declined, friendship +class FrendStatusEnum(enum.Enum): + pending = 0 + accepted = 1 + friendship = 2 + declined = 3 + +# таблица для связи многие-ко многим владелец-собака, так как у собаки может быть более 1 владельца +association_table = db.Table('association', + db.Column('user_id', db.String, db.ForeignKey('user.id_user')), + db.Column('dog_id', db.String, db.ForeignKey('dog.id_dog')) +) + +# а этот класс для отображаения "дружбы" между собакой и собакой/собаками пользователя через пользовтеля класс User +# status может принимать варианты accepted, declined, friendship - хранятся в config.py +class Friendship(db.Model): + id = db.Column(db.Integer, primary_key=True) + sender_dog_id = db.Column(db.String, db.ForeignKey('dog.id_dog')) + receiver_dog_id = db.Column(db.String, db.ForeignKey('dog.id_dog')) + status = db.Column(db.String, default=FrendStatusEnum.pending.value) + + def accept_request(self): + self.status = FrendStatusEnum.accepted.value + db.session.commit() + + def decline_request(self): + self.status = FrendStatusEnum.declined.value + db.session.commit() + + @classmethod + def add_friendship(cls, sender_dog, receiver_user): + # Создаем новый объект Friendship + friendship = cls(sender_dog_id=sender_dog.id_dog, receiver_dog_id=receiver_user.dogs[0].id_dog) + # Добавляем его в сессию для сохранения в базе данных + db.session.add(friendship) + db.session.commit() + + +class Dog(db.Model): + id_dog = db.Column(db.String, unique=True, primary_key=True, nullable=False) + name_dog = db.Column(db.String, nullable=False) + age_dog = db.Column(db.Integer, nullable=False, default=0) + breed_dog = db.Column(db.String, nullable=False) + response_date = db.Column(db.DateTime, nullable=False) + city_dog = db.Column(db.String, nullable=True) + foto_dog = db.Column(db.String, nullable=True) + voice_dog = db.Column(db.String, nullable=True) + users = db.relationship('User', secondary=association_table, back_populates='dogs') + + def add_friend_request(self, user_id): + friendship = Friendship(sender_dog_id=self.id_dog, receiver_dog_id=user_id) + db.session.add(friendship) + db.session.commit() + + def get_friends(self): + friends = [] + friendships = Friendship.query.filter_by(status=FrendStatusEnum.accepted.value).all() + for friendship in friendships: + if friendship.sender_dog_id == self.id_dog: + friend = Dog.query.filter_by(id_dog=friendship.receiver_dog_id).first() + if friend: + friends.append(friend) + elif friendship.receiver_dog_id == self.id_dog: + friend = Dog.query.filter_by(id_dog=friendship.sender_dog_id).first() + if friend: + friends.append(friend) + return friends + + def get_friend_requests(self): + friend_requests = [] + requests_from_user = Friendship.query.filter_by(receiver_dog_id=self.id_dog, status=FrendStatusEnum.pending.value).all() + print(requests_from_user) + for req in requests_from_user: + print(f'req.sender_dog_id: {req.sender_dog_id}') + dog = Dog.query.filter_by(id_dog=req.sender_dog_id).first() + print(f'DOG {dog}') + if dog: + friend_requests.append(dog) + print(f'Список DOG {friend_requests}') + return friend_requests + + + def __repr__(self): + return f'{self.id_dog}, {self.name_dog}, {self.breed_dog}, {self.age_dog}' + + + +class User(db.Model): + id_user = db.Column(db.String,unique=True, primary_key=True, nullable=False) + first_name = db.Column(db.String, nullable=False) + last_name = db.Column(db.String, nullable=False) + user_name = db.Column(db.String, nullable=True) + email = db.Column(db.String, nullable=False) + password = db.Column(db.String, nullable=False) + chat_id = db.Column(db.String,unique=True, nullable=True) + subscribed = db.Column(db.Boolean, default=False, nullable=True) + dogs = db.relationship('Dog', secondary=association_table, back_populates='users') + + def check_password(self, password): + return check_password_hash(self.password, password) + + def is_active(self): + # возвращает True, если пользователь активен, иначе - False + return True + + def get_id(self): + return str(self.id_user) + + def get_mail(self): + return str(self.email) + + def is_authenticated(self): + return True \ No newline at end of file diff --git a/dogs_around/webapp_dogs/static/logo.png b/dogs_around/webapp_dogs/static/logo.png new file mode 100644 index 0000000..8300489 Binary files /dev/null and b/dogs_around/webapp_dogs/static/logo.png differ diff --git a/dogs_around/webapp_dogs/static/logo_res.png b/dogs_around/webapp_dogs/static/logo_res.png new file mode 100644 index 0000000..0608b93 Binary files /dev/null and b/dogs_around/webapp_dogs/static/logo_res.png differ diff --git a/dogs_around/webapp_dogs/templates/cabinet.html b/dogs_around/webapp_dogs/templates/cabinet.html new file mode 100644 index 0000000..eb37bdc --- /dev/null +++ b/dogs_around/webapp_dogs/templates/cabinet.html @@ -0,0 +1,181 @@ + + + + + + + {{page_title}} + + + + + + {% with messages = get_flashed_messages() %} + {% if messages %} +
    + {% for message in messages %} +
  • {{ message }}
  • + {% endfor %} +
+ {% endif %} + {% endwith %} +
  • Пользователь: {{ email }}
  • +
  • Мои собачки: {{ my_dogs }}
  • + +
    + {% for dog in dogs %} +
    +
    + {{ dog.name_dog }} +
    +
    +

    Кличка: {{ dog.name_dog }}

    +

    Порода: {{ dog.breed_dog }}

    +

    Возраст: {{ dog.age_dog }}

    +
    +
    + Профиль +
    + + +
    + +
    +
    + {% endfor %} +
    + + + + + + + \ No newline at end of file diff --git a/dogs_around/webapp_dogs/templates/index.html b/dogs_around/webapp_dogs/templates/index.html new file mode 100644 index 0000000..b461e89 --- /dev/null +++ b/dogs_around/webapp_dogs/templates/index.html @@ -0,0 +1,151 @@ + + + + + + + {{page_title}} + + + + + + {% with messages = get_flashed_messages() %} + {% if messages %} +
      + {% for message in messages %} +
    • {{ message }}
    • + {% endfor %} +
    + {% endif %} + {% endwith %} +
    + Собакруг +
    +
    + {{page_title}} +
    + +

    Сегодня в круге:

    +
    + {% for dog in dogs %} +
    +
    + {{ dog.name_dog }} +
    +
    +

    Кличка: {{ dog.name_dog }}

    +

    Порода: {{ dog.breed_dog }}

    +

    Возраст: {{ dog.age_dog }}

    +
    +
    + {% endfor %} +
    + + + + + + + \ No newline at end of file diff --git a/dogs_around/webapp_dogs/templates/login.css b/dogs_around/webapp_dogs/templates/login.css new file mode 100644 index 0000000..67664a8 --- /dev/null +++ b/dogs_around/webapp_dogs/templates/login.css @@ -0,0 +1,6 @@ +.form-container { + display: flex; + justify-content: center; + align-items: center; + height: 100vh; + } \ No newline at end of file diff --git a/dogs_around/webapp_dogs/templates/login.html b/dogs_around/webapp_dogs/templates/login.html new file mode 100644 index 0000000..94d4f7e --- /dev/null +++ b/dogs_around/webapp_dogs/templates/login.html @@ -0,0 +1,50 @@ + + + + + + + {{ page_title }} + + + + + + + + + {% with messages = get_flashed_messages() %} + {% if messages %} +
      + {% for message in messages %} +
    • {{ message }}
    • + {% endfor %} +
    + {% endif %} + {% endwith %} +
    +
    + {{ form.hidden_tag() }} +
    + {{ form.email.label }} {{ form.email(size=20, class_='form-control', style='width:30%;') }} + {% for error in form.email.errors %} +
    {{ error }}
    + {% endfor %} +
    +
    + {{ form.password.label }} {{ form.password(size=20, class_='form-control', style='width:30%;') }} + {% for error in form.password.errors %} +
    {{ error }}
    + {% endfor %} +
    + {{ form.submit }} +
    +
    + + + + + + + + diff --git a/dogs_around/webapp_dogs/templates/profile.html b/dogs_around/webapp_dogs/templates/profile.html new file mode 100644 index 0000000..f598f7e --- /dev/null +++ b/dogs_around/webapp_dogs/templates/profile.html @@ -0,0 +1,46 @@ + + + + + + + + + + + {{ page_title }} + + +
    +

    {{ page_title }}

    + +
    +
    + {% with messages = get_flashed_messages() %} + {% if messages %} + + {% endif %} + {% endwith %} +
    + {% if user %} +
    +

    Имя: {{ user.first_name }}

    +

    Фамилия: {{ user.last_name }}

    +

    Ник: {{ user.user_name }}

    +

    Почта: {{ user.email }}

    +
    + {% endif %} +
    +
    +
    +
    + + + + + + + + + + + + diff --git a/dogs_around/webapp_dogs/templates/registration.html b/dogs_around/webapp_dogs/templates/registration.html new file mode 100644 index 0000000..43016d2 --- /dev/null +++ b/dogs_around/webapp_dogs/templates/registration.html @@ -0,0 +1,67 @@ + + + + + + + {{ page_title }} + + + + + + + + +
    +

    Registration

    +
    + {{ form.csrf_token }} +
    + {{ form.first_name.label }} {{ form.first_name(size=20, class_='form-control', style='width:50%;') }} + {% for error in form.first_name.errors %} +
    {{ error }}
    + {% endfor %} +
    +
    + {{ form.last_name.label }} {{ form.last_name(size=20, class_='form-control',style='width:50%;') }} + {% for error in form.last_name.errors %} +
    {{ error }}
    + {% endfor %} +
    +
    + {{ form.user_name.label }} {{ form.user_name(size=20, class_='form-control', style='width:50%;') }} + {% for error in form.user_name.errors %} +
    {{ error }}
    + {% endfor %} +
    +
    + {{ form.email.label }} {{ form.email(size=20, class_='form-control', style='width:50%;') }} + {% for error in form.email.errors %} +
    {{ error }}
    + {% endfor %} +
    +
    + {{ form.password.label }} {{ form.password(size=20, class_='form-control', style='width:50%;') }} + {% for error in form.password.errors %} +
    {{ error }}
    + {% endfor %} +
    +
    + {{ form.confirm_password.label }} {{ form.confirm_password(size=20, class_='form-control', style='width:50%;') }} + {% for error in form.confirm_password.errors %} +
    {{ error }}
    + {% endfor %} +
    +
    + {{ form.submit(class_='btn btn-primary') }} +
    +
    +
    + + + + + + + diff --git a/dogs_around/webapp_dogs/templates/user_dogs.html b/dogs_around/webapp_dogs/templates/user_dogs.html new file mode 100644 index 0000000..cbc2b4e --- /dev/null +++ b/dogs_around/webapp_dogs/templates/user_dogs.html @@ -0,0 +1,210 @@ + + + + + + + {{ page_title }} + + + + + + + + + + {% with messages = get_flashed_messages() %} + {% if messages %} +
      + {% for message in messages %} +
    • {{ message }}
    • + {% endfor %} +
    + {% endif %} +{% endwith %} +
    +

    Мои собачки:

    +
    + {% for dog in dogs %} +
    +
    + {{ dog.name_dog }} +
    +
    +

    Кличка: {{ dog.name_dog }}

    +

    Порода: {{ dog.breed_dog }}

    +

    Возраст: {{ dog.age_dog }}

    +
    + +
    + {% endfor %} +
    +
    +
    +
    +

    Друзья собачек:

    +
    + {% for friend in friends %} +
    +
    +

    Кличка: {{ friend.name_dog }}

    +

    Порода: {{ friend.breed_dog }}

    +

    Возраст: {{ friend.age_dog }}

    +
    + +
    + {% endfor %} +
    +
    +
    + +
    +

    Заявки в друзья:

    +
    + {% for request in friend_requests %} +
    +
    +

    Кличка: {{ request.name_dog }}

    +

    Порода: {{ request.breed_dog }}

    +

    Возраст: {{ request.age_dog }}

    +
    + +
    + {% endfor %} +
    +
    + + + + + + + + \ No newline at end of file diff --git a/dogs_around/webapp_dogs/utils_dog.py b/dogs_around/webapp_dogs/utils_dog.py new file mode 100644 index 0000000..0648637 --- /dev/null +++ b/dogs_around/webapp_dogs/utils_dog.py @@ -0,0 +1,63 @@ +from flask import Flask +from webapp_dogs.model import db, User, Dog +from webapp_dogs.config import SQLALCHEMY_DATABASE_URI +from sqlalchemy.exc import SQLAlchemyError +from flask_sqlalchemy import SQLAlchemy +import hashlib +import uuid + +def generate_id_user(): + uuid_val = uuid.uuid4().bytes + # Получаем хэш от UUID с использованием sha256 + hash_object = hashlib.sha256(uuid_val) + hex_dig = hash_object.hexdigest() + return hex_dig + +def generate_id_dog(name_dog, age_dog, breed_dog, response_date, city_dog): + input_str = f"{name_dog}-{age_dog}-{breed_dog}-{response_date}-{city_dog}" + # Получаем хэш от строки с использованием sha256 + hash_object = hashlib.sha256(input_str.encode()) + hex_dig = hash_object.hexdigest() + return hex_dig + +def get_or_create_user(id_user, first_name, last_name, user_name, email, hashed_password) -> None: + app = Flask(__name__) + app.config['SQLALCHEMY_DATABASE_URI'] = SQLALCHEMY_DATABASE_URI + try: + with app.app_context(): + try: + db.init_app(app) + user_exists = User.query.filter(User.email == email).first() + if not user_exists: + new_user = User(id_user=id_user, first_name=first_name, last_name=last_name, user_name=user_name, email= email, password=hashed_password) + db.session.add(new_user) + db.session.commit() + return f'Пользователь с почтой {email} зарегистрирован.' + else: + return f'Пользователь с почтой {email} уже зарегистрирован.' + except SQLAlchemyError as sq: + print(f'Ошибка sqlalchemy записи пользователя tg в get_or_create_user в бд: {sq}') + except Exception as ex1: + print(f'Ошибка в функции обработки данных пользователя: {ex1}') + +def get_or_create_dog(id_dog, name_dog, age_dog, breed_dog, response_date, + city_dog, foto_dog, voice_dog, username) -> None: + app = Flask(__name__) + app.config['SQLALCHEMY_DATABASE_URI'] = SQLALCHEMY_DATABASE_URI + try: + with app.app_context(): + try: + db.init_app(app) + user = User.query.filter_by(email=username).first() + dog_exists = Dog.query.filter(Dog.id_dog == id_dog).first() + if not dog_exists: + new_dog = Dog(id_dog=id_dog,name_dog=name_dog, age_dog=age_dog, breed_dog=breed_dog, response_date=response_date, + city_dog=city_dog, foto_dog=foto_dog, voice_dog=voice_dog) + user.dogs.append(new_dog) + db.session.add(new_dog) + db.session.commit() + return dog_exists + except SQLAlchemyError as sq: + print(f'Ошибка sqlalchemy записи пользователя tg в get_or_create_user в бд: {sq}') + except Exception as ex1: + print(f'Ошибка функции обработки данных собаки: {ex1}') \ No newline at end of file