This commit is contained in:
Dominic DiTaranto 2025-10-23 11:13:56 -04:00
parent 799d0a7378
commit 287aa02b9c
6 changed files with 65 additions and 9 deletions

View file

@ -1,10 +1,13 @@
[x] login page [x] login page
[x] logout [x] logout
[ ] change password [ ] change password
[ ] member profile update and avatar [x] member profile update and avatar
[x] forum [x] forum
[ ] view other's profiles, add links in forums
[x] member type [x] member type
[ ] nav bar [ ] nav bar
[ ] users must be authed
[ ] signup must redirect NOT auto grant users access, and MUST give them some info on what to expect
[ ] determine where which pages should live where [ ] determine where which pages should live where
[ ] easier way to handle sites var, API endpoint? [ ] easier way to handle sites var, API endpoint?
[ ] send out emails to existing users letting them know they have a password and to change it [ ] send out emails to existing users letting them know they have a password and to change it

View file

@ -32,12 +32,11 @@ class SignupForm(UserCreationForm):
class EditProfileForm(forms.Form): class EditProfileForm(forms.Form):
avatar = forms.ImageField(allow_empty_file=True, validators=) avatar = forms.ImageField(allow_empty_file=True, required=False)
url = forms.URLField(max_length=200, help_text='Required') url = forms.URLField(max_length=200, help_text='Required')
description = forms.CharField(widget=forms.Textarea) description = forms.CharField(widget=forms.Textarea)
class ThreadPostForm(forms.Form): class ThreadPostForm(forms.Form):
content = MarkdownxFormField() content = MarkdownxFormField()

View file

@ -126,8 +126,8 @@
</div> </div>
<div class="container nav" style="margin-top:-10px;"> <div class="container nav" style="margin-top:-10px;">
<center> <center>
<a href="#">Forum</a> <a href="{% url 'forum_threads' %}">Forum</a>
<a href="#">Profile</a> <a href="{% url 'profile' %}">Profile</a>
<a href="{% url 'custom_logout' %}">Logout</a> <a href="{% url 'custom_logout' %}">Logout</a>
</center> </center>
</div> </div>

View file

@ -2,8 +2,36 @@
{% extends "base.html" %} {% extends "base.html" %}
{% block content %} {% block content %}
<h2>{{ user.username }}'s Profile</h2> <h2>{{ user.username }}'s Profile</h2>
<img src="{{user.avatar}}"> <img src="{{ user.avatar }}">
<form method="post"> <form method="post" enctype='multipart/form-data'>
<p>
<label for="id_avatar">Avatar:</label>
<br>
<input type="file" name="avatar" accept="image/*">
<br>
</p>
<p>
<label for="id_url">Url:</label>
<br>
<small style="color: grey">Required</small>
<br>
<input type="url"
name="url"
maxlength="200"
required
aria-describedby="id_url_helptext"
id="id_url"
value="{{ user.url }}">
<br>
</p>
<p>
<label for="id_description">Description:</label>
<br>
<textarea name="description" cols="40" rows="10" required id="id_description">{{user.description}}
</textarea>
<br>
</p>
<button type="submit">Save</button>
{% csrf_token %} {% csrf_token %}
</form> </form>
{% endblock %} {% endblock %}

View file

@ -13,6 +13,7 @@
{% for post in posts %} {% for post in posts %}
<tr> <tr>
<td> <td>
<img src="{{post.created_by.avatar}}" alt="">
<small> <small>
<b>{{ post.created_by }}</b> ({{ post.created_by.flair }}) <b>{{ post.created_by }}</b> ({{ post.created_by.flair }})
<br> <br>

View file

@ -1,7 +1,11 @@
import base64
from io import BytesIO
from PIL import Image
from django.shortcuts import render, redirect, get_object_or_404 from django.shortcuts import render, redirect, get_object_or_404
from django.contrib.auth import login, logout from django.contrib.auth import login, logout
from django.urls import reverse from django.urls import reverse
from web.forms import SignupForm, ThreadPostForm from web.forms import SignupForm, ThreadPostForm, EditProfileForm
from web.models.forum_subcategory import ForumSubcategory from web.models.forum_subcategory import ForumSubcategory
from web.models.forum_post import ForumPost from web.models.forum_post import ForumPost
@ -88,7 +92,28 @@ def custom_logout(request):
def profile(request): def profile(request):
if request.method == 'POST':
form = EditProfileForm(request.POST)
if form.is_valid():
if request.FILES:
avatar_size = 200, 200
image = Image.open(request.FILES['avatar'])
image.thumbnail(avatar_size, Image.Resampling.LANCZOS)
buffered = BytesIO()
image.save(buffered, format="png")
img_str = base64.b64encode(buffered.getvalue())
img_base64 = bytes("data:image/png;base64,", encoding='utf-8') + img_str
request.user.avatar = img_base64.decode('utf-8')
request.user.description = request.POST['description']
request.user.url = request.POST['url']
request.user.save()
form = EditProfileForm()
context = { context = {
'user': request.user 'user': request.user,
'form': form,
} }
return render(request, 'profile.html', context) return render(request, 'profile.html', context)