Refactor UserData admin interface; enhance user registration forms and validation; update Dockerfile for static files collection

with_posts
Jukoga 2026-03-08 12:54:11 +01:00
parent 9d7305ef13
commit c62d0deb33
14 changed files with 36 additions and 89 deletions

View File

@ -25,11 +25,9 @@ DEFAULT_AUTO_FIELD='django.db.models.AutoField'
# Load the Env
load_dotenv()
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = os.getenv('SECRET_KEY')
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = False
DEBUG = os.environ.get('DEBUG', 'False') == 'True'
ALLOWED_HOSTS = ['localhost', '127.0.0.1', 'beyond-heroes.com', 'www.beyond-heroes.com']
@ -40,7 +38,7 @@ INSTALLED_APPS = [
'crispy_forms',
'crispy_bootstrap4',
'blog.apps.BlogConfig',
'users.apps.UsersConfig',
'users',
'api.apps.APIConfig',
'django.contrib.admin',
'django.contrib.auth',

View File

@ -30,5 +30,5 @@ EXPOSE 3030
# Define environment variable for Gunicorn
ENV GUNICORN_CMD_ARGS="--bind 0.0.0.0:3030"
# Run Gunicorn server with your Django application
CMD ["gunicorn", "BH.wsgi:application"]
# Collect static files and run Gunicorn
CMD ["sh", "-c", "python manage.py collectstatic --noinput && gunicorn BH.wsgi:application"]

View File

@ -1,23 +0,0 @@
# Generated by Django 5.2.9 on 2026-02-19 10:09
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('blog', '0001_initial'),
]
operations = [
migrations.AlterField(
model_name='blog',
name='id',
field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
),
migrations.AlterField(
model_name='post',
name='id',
field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
),
]

View File

@ -10,6 +10,7 @@
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;700&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Mozilla+Headline" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<style type="text/css">
:root {
@ -23,7 +24,7 @@
@font-face {
font-family: 'Alte DIN 1451 Mittelschrift';
src: url('mittelschrift.ttf') format('truetype'); /* Chrome 4+, Firefox 3.5, Opera 10+, Safari 3—5 */
src: url('media/mittelschrift.ttf') format('truetype'); /* Chrome 4+, Firefox 3.5, Opera 10+, Safari 3—5 */
}
body {
font-family: 'Alte DIN 1451 Mittelschrift', sans-serif;

View File

@ -2,7 +2,6 @@
{% block content %}
{% load markdown_extras %}
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<br><br>
<!-- Main Content -->
<div class="container mt-5">

View File

@ -1,7 +1,6 @@
{% extends 'base.html' %}
{% block content %}
{% load crispy_forms_tags %}
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<br><br>
<div class="container mt-5">
<form method="POST">

View File

@ -2,7 +2,6 @@
{% block content %}
{% load crispy_forms_tags %}
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<br><br>
{% if messages %}
{% for message in messages %}

View File

@ -1,7 +1,6 @@
{% extends 'base.html' %}
{% block content %}
{% load crispy_forms_tags %}
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<br>
<br>
<div class="container mt-5">

0
users/__init__.py Normal file
View File

View File

@ -1,5 +1,9 @@
from django.contrib import admin
from .models import *
from .models import UserData
admin.site.register(UserData)
@admin.register(UserData)
class UserDataAdmin(admin.ModelAdmin):
list_display = ('user', 'name', 'xp', 'money')
search_fields = ('user__username', 'name')
readonly_fields = ('user', 'xp', 'money', 'equipment', 'inventory')

View File

@ -1,7 +1,6 @@
from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
from .models import *
class UserRegisterForm(UserCreationForm):
@ -11,6 +10,12 @@ class UserRegisterForm(UserCreationForm):
model = User
fields = ['username', 'email', 'password1', 'password2']
def clean_email(self):
email = self.cleaned_data.get('email')
if User.objects.filter(email__iexact=email).exists():
raise forms.ValidationError('An account with this email address already exists.')
return email.lower()
class UserUpdateForm(forms.ModelForm):
email = forms.EmailField()
@ -19,3 +24,10 @@ class UserUpdateForm(forms.ModelForm):
model = User
fields = ['username', 'email']
def clean_email(self):
email = self.cleaned_data.get('email')
# Allow the current user to keep their own email
if User.objects.filter(email__iexact=email).exclude(pk=self.instance.pk).exists():
raise forms.ValidationError('An account with this email address already exists.')
return email.lower()

View File

@ -6,11 +6,10 @@ from django.contrib.auth.models import User
class UserData(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
name = models.CharField(max_length=40)
xp = models.IntegerField()
money = models.IntegerField()
equipment = models.CharField(max_length=1024, default='0;')
inventory = models.CharField(max_length=1024, default='0;')
xp = models.IntegerField(default=0)
money = models.IntegerField(default=10000)
equipment = models.CharField(max_length=1024, default='0;', blank=True)
inventory = models.CharField(max_length=1024, default='0;', blank=True)
def __str__(self):
return f"{self.user.username}'s data"

View File

@ -1,7 +1,9 @@
from rest_framework import serializers
from .models import *
from .models import UserData
class UserDataSerializer(serializers.ModelSerializer):
class Meta:
model = UserData
fields = ['user', 'name', 'xp', 'money', 'equipment', 'inventory']
read_only_fields = ['user', 'xp', 'money', 'equipment', 'inventory']

View File

@ -1,54 +1,12 @@
from django.shortcuts import render, redirect
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.auth.models import User
from django.views.generic import ListView
from .forms import UserRegisterForm
from blog.models import *
from .models import *
from django.views.generic import *
# Create your views here.
# def users(request):
# return render(request, 'users/users.html', {'title': 'Users'})
# def getFromArr(arr, indices, *args, **kwargs):
# x = []
# for i in indices:
# x.append(arr[i])
# return x
# @login_required
# def profile(request, *args, **kwargs):
# try:
# user = User._default_manager.all()[kwargs['pk'] - 1]
# except:
# user = request.user
# print(user.id)
# allow_empty = True
# queryset = Post._default_manager.all()
# context_object_name = 'posts'
# ordering = ['-date_posted']
# if ordering:
# if isinstance(ordering, str):
# ordering = (ordering,)
# queryset = queryset.order_by(*ordering)
# return render(request, 'users/profile.html', {'title': 'Profile', 'profileUser': user, context_object_name: queryset})
# def people(request):
# return render(request, 'users/people.html', {'title': 'People', 'users': User._default_manager.all()})
users = {
'user': User.objects.all()
}
class UserListView(ListView):
class UserListView(LoginRequiredMixin, ListView):
model = User
template_name = 'users/people.html'
context_object_name = 'users'