mirror of
https://github.com/aykhans/series-robot-web.git
synced 2025-09-08 15:30:43 +00:00
first commit
This commit is contained in:
0
src/account/__init__.py
Normal file
0
src/account/__init__.py
Normal file
13
src/account/admin.py
Normal file
13
src/account/admin.py
Normal file
@@ -0,0 +1,13 @@
|
||||
from django.contrib import admin
|
||||
from django.contrib.auth.admin import UserAdmin
|
||||
from .models import User
|
||||
|
||||
|
||||
@admin.register(User)
|
||||
class CustomAdmin(UserAdmin):
|
||||
list_display = ('username', 'email')
|
||||
fieldsets = UserAdmin.fieldsets + (
|
||||
('IMDB API Key Field', {
|
||||
'fields': ['imdb_api_key']
|
||||
}),
|
||||
)
|
6
src/account/apps.py
Normal file
6
src/account/apps.py
Normal file
@@ -0,0 +1,6 @@
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class AccountConfig(AppConfig):
|
||||
default_auto_field = 'django.db.models.BigAutoField'
|
||||
name = 'account'
|
2
src/account/forms/__init__.py
Normal file
2
src/account/forms/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
||||
from .register import RegisterForm
|
||||
from .profile_editing import ProfileEditingForm
|
10
src/account/forms/profile_editing.py
Normal file
10
src/account/forms/profile_editing.py
Normal file
@@ -0,0 +1,10 @@
|
||||
from django.contrib.auth.forms import UserChangeForm
|
||||
from account.models import User
|
||||
|
||||
|
||||
class ProfileEditingForm(UserChangeForm):
|
||||
password = None
|
||||
|
||||
class Meta:
|
||||
model = User
|
||||
fields = ('email', 'username', 'imdb_api_key')
|
14
src/account/forms/register.py
Normal file
14
src/account/forms/register.py
Normal file
@@ -0,0 +1,14 @@
|
||||
from django.contrib.auth.forms import UserCreationForm
|
||||
from account.models import User
|
||||
|
||||
|
||||
class RegisterForm(UserCreationForm):
|
||||
password = None
|
||||
|
||||
class Meta:
|
||||
model = User
|
||||
fields = ('username',
|
||||
'email',
|
||||
'password1',
|
||||
'password2',
|
||||
'imdb_api_key')
|
25
src/account/models.py
Normal file
25
src/account/models.py
Normal file
@@ -0,0 +1,25 @@
|
||||
from django.db import models
|
||||
from django.contrib.auth.models import AbstractUser
|
||||
from API_client import APIClient
|
||||
from django.core.exceptions import ValidationError
|
||||
|
||||
|
||||
class User(AbstractUser):
|
||||
imdb_api_key = models.CharField(max_length=15, blank=False, null=False)
|
||||
|
||||
def clean(self) -> None:
|
||||
client = APIClient(self.imdb_api_key)
|
||||
client.key_control()
|
||||
# raw_data = get(f"https://imdb-api.com/en/API/Title/{self.imdb_api_key}/tt0110413")
|
||||
|
||||
# if raw_data.status_code == 200: data = raw_data.json()
|
||||
# else: raise ValidationError('Account not created. Please try again later')
|
||||
# if not data['errorMessage']: raise ValidationError(data['errorMessage'])
|
||||
|
||||
class Meta:
|
||||
db_table = 'user'
|
||||
verbose_name = 'User'
|
||||
verbose_name_plural = 'Users'
|
||||
|
||||
def __str__(self):
|
||||
return self.username
|
23
src/account/templates/change_password.html
Normal file
23
src/account/templates/change_password.html
Normal file
@@ -0,0 +1,23 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load crispy_forms_tags %}
|
||||
|
||||
|
||||
{% block title %} Change Password {% endblock title %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<form enctype="multipart/form-data" method="POST">
|
||||
{% csrf_token %}
|
||||
{{form.media}}
|
||||
{{form|crispy}}
|
||||
<style>
|
||||
.btn:hover {
|
||||
background: #fff;
|
||||
color: #0069D9;
|
||||
}
|
||||
</style>
|
||||
<input type="submit" value="Change Password" class="btn btn-primary mt-3 mb-5">
|
||||
</form>
|
||||
|
||||
{% endblock content %}
|
||||
|
24
src/account/templates/login.html
Normal file
24
src/account/templates/login.html
Normal file
@@ -0,0 +1,24 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load crispy_forms_tags %}
|
||||
|
||||
|
||||
{% block title %} Login {% endblock title %}
|
||||
|
||||
{% block content %}
|
||||
{% include 'components/message.html' %}
|
||||
|
||||
<form method="POST">
|
||||
{% csrf_token %}
|
||||
{{form|crispy}}
|
||||
<style>
|
||||
.btn:hover {
|
||||
background: #fff;
|
||||
color: #0069D9;
|
||||
}
|
||||
</style>
|
||||
<input type="submit" value="Login" class="btn btn-primary mt-3 mb-3">
|
||||
<p class="mb-5">No account? <a href="{% url 'register' %}">Signup</a></p>
|
||||
</form>
|
||||
|
||||
{% endblock content %}
|
||||
|
24
src/account/templates/profile_detail.html
Normal file
24
src/account/templates/profile_detail.html
Normal file
@@ -0,0 +1,24 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load static %}
|
||||
|
||||
{% block title %} Profile {% endblock title %}
|
||||
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div class="card mb-3">
|
||||
<div class="card-body">
|
||||
<h5>Username: <small>{{profile.username}}</small></h5>
|
||||
<h5>Email: <small>{{profile.email|default:""}}</small></h5>
|
||||
<h5>IMDB API Key: <small>{{profile.imdb_api_key}}</small></h5>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<a href="/account/profile-editing" style="color: inherit; text-decoration: none;">
|
||||
<button type="button" class="btn btn-primary">Edit Profile</button>
|
||||
</a>
|
||||
<a href="/account/change-password" style="color: inherit; text-decoration: none;">
|
||||
<button type="button" class="btn btn-primary">Change Password</button>
|
||||
</a>
|
||||
|
||||
{% endblock content %}
|
23
src/account/templates/profile_editing.html
Normal file
23
src/account/templates/profile_editing.html
Normal file
@@ -0,0 +1,23 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load crispy_forms_tags %}
|
||||
|
||||
|
||||
{% block title %} Profil Güncəllə {% endblock title %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<form enctype="multipart/form-data" method="POST">
|
||||
{% csrf_token %}
|
||||
{{form.media}}
|
||||
{{form|crispy}}
|
||||
<style>
|
||||
.btn:hover {
|
||||
background: #fff;
|
||||
color: #0069D9;
|
||||
}
|
||||
</style>
|
||||
<input type="submit" value="Update Profile" class="btn btn-primary mt-3 mb-5">
|
||||
</form>
|
||||
|
||||
{% endblock content %}
|
||||
|
25
src/account/templates/register.html
Normal file
25
src/account/templates/register.html
Normal file
@@ -0,0 +1,25 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load crispy_forms_tags %}
|
||||
|
||||
|
||||
{% block title %} Signup {% endblock title %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<form method="POST">
|
||||
{% csrf_token %}
|
||||
{{form.media}}
|
||||
{{form|crispy}}
|
||||
<a href="https://imdb-api.com/Identity/Account/Register">Get API Key</a><br>
|
||||
<style>
|
||||
.btn:hover {
|
||||
background: #fff;
|
||||
color: #0069D9;
|
||||
}
|
||||
</style>
|
||||
<input type="submit" value="Signup" class="btn btn-primary mt-3 mb-3">
|
||||
<p class="mb-5">Already have an account? <a href="{% url 'login' %}">Login</a></p>
|
||||
</form>
|
||||
|
||||
{% endblock content %}
|
||||
|
3
src/account/tests.py
Normal file
3
src/account/tests.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
15
src/account/urls.py
Normal file
15
src/account/urls.py
Normal file
@@ -0,0 +1,15 @@
|
||||
from django.urls import path
|
||||
from account import views
|
||||
from django.contrib.auth import views as auth_views
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
path('login', auth_views.LoginView.as_view(
|
||||
template_name = 'login.html'
|
||||
), name='login'),
|
||||
path('register', views.register_view, name='register'),
|
||||
path('logout', views.logout_view, name='logout'),
|
||||
path('change-password', views.change_password_view, name='change-password'),
|
||||
path('profile-editing', views.profile_editing_view, name='profile-editing'),
|
||||
path('profile', views.ProfileDetailView.as_view(), name='profile')
|
||||
]
|
5
src/account/views/__init__.py
Normal file
5
src/account/views/__init__.py
Normal file
@@ -0,0 +1,5 @@
|
||||
from .register import register_view
|
||||
from .logout import logout_view
|
||||
from .change_password import change_password_view
|
||||
from .profile_editing import profile_editing_view
|
||||
from .profile_detail import ProfileDetailView
|
22
src/account/views/change_password.py
Normal file
22
src/account/views/change_password.py
Normal file
@@ -0,0 +1,22 @@
|
||||
from django.shortcuts import render, redirect
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.contrib.auth.forms import PasswordChangeForm
|
||||
from django.contrib.auth import update_session_auth_hash
|
||||
from django.contrib import messages
|
||||
|
||||
|
||||
@login_required(login_url='/')
|
||||
def change_password_view(request):
|
||||
if request.method == 'POST':
|
||||
form = PasswordChangeForm(request.user, request.POST)
|
||||
if form.is_valid():
|
||||
user = form.save()
|
||||
update_session_auth_hash(request, user)
|
||||
|
||||
messages.success(request, 'Password changed')
|
||||
return redirect('homepage')
|
||||
|
||||
else:
|
||||
form = PasswordChangeForm(request.user)
|
||||
|
||||
return render(request, 'change_password.html', context={'form': form})
|
12
src/account/views/logout.py
Normal file
12
src/account/views/logout.py
Normal file
@@ -0,0 +1,12 @@
|
||||
from django.contrib.auth import logout
|
||||
from django.shortcuts import redirect
|
||||
from django.contrib import messages
|
||||
from django.contrib.auth.decorators import login_required
|
||||
|
||||
|
||||
@login_required(login_url='/account/login')
|
||||
def logout_view(request):
|
||||
logout(request)
|
||||
|
||||
messages.success(request, 'Logged Out')
|
||||
return redirect('login')
|
16
src/account/views/profile_detail.py
Normal file
16
src/account/views/profile_detail.py
Normal file
@@ -0,0 +1,16 @@
|
||||
from django.views.generic import DetailView
|
||||
from account.models import User
|
||||
from django.urls import reverse, reverse_lazy
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
|
||||
|
||||
class ProfileDetailView(LoginRequiredMixin, DetailView):
|
||||
login_url = reverse_lazy('login')
|
||||
template_name = 'profile_detail.html'
|
||||
context_object_name = 'profile'
|
||||
|
||||
def get_object(self):
|
||||
return get_object_or_404(
|
||||
User, id=self.request.user.id
|
||||
)
|
20
src/account/views/profile_editing.py
Normal file
20
src/account/views/profile_editing.py
Normal file
@@ -0,0 +1,20 @@
|
||||
from django.shortcuts import render, redirect
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.contrib import messages
|
||||
from account.forms import ProfileEditingForm
|
||||
|
||||
|
||||
@login_required(login_url='/')
|
||||
def profile_editing_view(request):
|
||||
if request.method == 'POST':
|
||||
form = ProfileEditingForm(request.POST, instance=request.user)
|
||||
if form.is_valid():
|
||||
form.save()
|
||||
|
||||
messages.success(request, 'Profile Updated')
|
||||
return redirect('homepage')
|
||||
|
||||
else:
|
||||
form = ProfileEditingForm(instance=request.user)
|
||||
|
||||
return render(request, 'profile_editing.html', context={"form": form})
|
35
src/account/views/register.py
Normal file
35
src/account/views/register.py
Normal file
@@ -0,0 +1,35 @@
|
||||
from django.shortcuts import render, redirect
|
||||
from django.contrib import messages
|
||||
from account.forms import RegisterForm
|
||||
from django.contrib.auth import login, authenticate
|
||||
from django.core.exceptions import ValidationError
|
||||
from requests import get
|
||||
|
||||
|
||||
def register_view(request):
|
||||
if request.method == 'POST':
|
||||
form = RegisterForm(request.POST)
|
||||
if form.is_valid():
|
||||
# raw_data = get(f"https://imdb-api.com/en/API/Title/{request.POST['imdb_api_key']}/tt0110413")
|
||||
# if raw_data.status_code == 200: data = raw_data.json()
|
||||
# else:
|
||||
# messages.info(request, 'Account not created. Please try again later')
|
||||
# return redirect('register')
|
||||
|
||||
# if data['errorMessage'] == 'Invalid API Key':
|
||||
# messages.info(request, 'Invalid API Key')
|
||||
# return redirect('register')
|
||||
|
||||
form.save()
|
||||
username = form.cleaned_data.get('username')
|
||||
password = form.cleaned_data.get('password1')
|
||||
user = authenticate(username=username, password=password)
|
||||
login(request, user)
|
||||
|
||||
messages.success(request, 'Registration Successful')
|
||||
return redirect('homepage')
|
||||
|
||||
else:
|
||||
form = RegisterForm()
|
||||
|
||||
return render(request, 'register.html', context={"form": form})
|
Reference in New Issue
Block a user