Hi,
I am making currently a form where the user can edit his profile image. I am trying to delete the profile image that the user had before, after he changes his profile image to a new one. I made so far the scripts, but by the print commans I found out, my submit button(my script) get's triggered twice.
Some Informations: I am using Django 3.1 - Python 3.7.2 - JS,Bootstrap from CDN
html site code
{% extends "blog/base.html" %}
{% load crispy_forms_tags %}
{% block content %}
<div class="content-section">
<div class="media">
<img class="rounded-circle account-img" src="{{ user.profile.image.url }}">
<div class="media-body">
<h2 class="account-heading">{{ user.username }}</h2>
<p class="text-secondary">{{ user.email }}</p>
</div>
</div>
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
<fieldset class="form-group">
<legend class="border-bottom mb-4">Informazioni sul profilo</legend>
{{ u_form|crispy }}
{{ p_form|crispy }}
</fieldset>
<div class="form-group">
<button class="btn btn-outline-info" type="submit">Aggiorna</button>
</div>
</form>
<!--form here-->
</div>
{% endblock content %}
models.py
from django.db import models
from django.contrib.auth.models import User
from PIL import Image, ImageChops
import os
import time
# Create your models here.
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
image = models.ImageField(default='profile_pics/default.jpg', upload_to='profile_pics')
def __str__(self):
return f'{self.user.username} Profile'
def save(self):
super().save()
#
path = 'media/profile_pics/'
media_pics = os.listdir(path)
img = Image.open(self.image.path)
for imgm in media_pics:
print(imgm)
im2 = Image.open('media/profile_pics/' + imgm)
if list(img.getdata()) == list(im2.getdata()):
print(imgm)
print('Identical')
im2.close()
os.remove('media/profile_pics/' + imgm)
break
else:
print(imgm)
print('Different')
#
if img.height > 300 or img.height > 300:
output_size = (300, 300)
img.thumbnail(output_size)
img.save(self.image.path)
views.py(Here gets the model.py triggered)
from django.shortcuts import render, redirect
from django.contrib import messages
from .forms import UserRegisterForm, UserUpdateForm, ProfileUpdateForm
from django.contrib.auth.decorators import login_required
# Create your views here.
def register(request):
if request.method == 'POST':
form = UserRegisterForm(request.POST)
if form.is_valid():
form.save()
username = form.cleaned_data.get('username')
messages.success(request, f'Account di {username} è stato creato!')
return redirect('login')
else:
form = UserRegisterForm()
return render(request, 'users/register.html', {'form': form})
#login_required
def profile(request):
if request.method == 'POST':
u_form = UserUpdateForm(request.POST, instance=request.user)
p_form = ProfileUpdateForm(request.POST, request.FILES, instance=request.user.profile)
if u_form.is_valid() and p_form.is_valid():
u_form.save()
p_form.save()
messages.success(request, f'Tuo account è stato aggiornato!')
return redirect('profile')
else:
u_form = UserUpdateForm(instance=request.user)
p_form = ProfileUpdateForm(instance=request.user.profile)
context = {
'u_form': u_form,
'p_form': p_form,
}
return render(request, 'users/profile.html', context)
urls.py
from django.contrib import admin
from django.urls import path, include
from django.conf import settings
from django.conf.urls.static import static
from users import views as user_views
from django.contrib.auth import views as auth_views
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('blog.urls')),
path('register/', user_views.register, name='register'),
path('login/', auth_views.LoginView.as_view(template_name='users/login.html'), name='login'),
path('logout/', auth_views.LogoutView.as_view(template_name='users/logout.html'), name='logout'),
path('profile/', user_views.profile, name='profile'),
]
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
-django_project
--blog (has nothing to do with this scripts up here/\)
--django_project
---__init__.py
---asgi.py
---settings.py
---urls.py
---wsgi.py
--media
---profile_pics
----(bunch of player added images)
--static
---CSS
----main.css
----JS (nothing inside)
----Images (nothing inside)
-users
--__pycache__
--migrations
--templates
---users
----profile.html
----register.html
----login.html
----logout.html
--__init__.py
--admin.py
--apps.py
--forms.py
--models.py
--signals.py
--tests.py
--views.py
Have a nice day!
The submit button does not trigger twice.
The prints happen in the code that loops over media pics - for imgm in media_pics: It will loop as many times as you have pictures stored in the folder media/profile_pics.
You probably want to check for old image before calling super().save().
You can get the old version by calling eg - old_profile = Profile.objects.get(pk=self.pk) and compare/delete the image (os.remove(old_profile.image.name) and then call super().save()
Related
I am following the tutorial on [Protecting Views][1] and I have trouble understanding the tutorial. When I click the the Reply Button, it does not take me to the link to reply to the topic, and displayed a # in the URL instead. I had to type in the URL to get to that point. And when I posted something, it didn't redirect, and the new topic that I replied to wasn't there. I don't know why this is happening.
Here's my forms.py file
from django import forms
from .models import Topic, Post
class NewTopicForm(forms.ModelForm):
message = forms.CharField(
widget=forms.Textarea(),
max_length=4000,
help_text='The max length of this field is 4000.'
)
class Meta:
model = Topic
fields = ['subject', 'message']
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = ['message', ]
and here's my urls.py file
from django.conf.urls import url
from django.contrib import admin
from django.contrib.auth import views as auth_views
from accounts import views as accounts_views
from boards import views
urlpatterns = [
url(r'^$', views.home, name='home'),
url(r'^signup/$', accounts_views.signup, name='signup'),
url(r'^login/$', auth_views.LoginView.as_view(template_name='login.html'), name='login'),
url(r'^logout/$', auth_views.LogoutView.as_view(), name='logout'),
url(r'^reset/$',
auth_views.PasswordResetView.as_view(
template_name='password_reset.html',
email_template_name='password_reset_email.html',
subject_template_name='password_reset_subject.txt'
),
name='password_reset'),
url(r'^reset/done/$',
auth_views.PasswordResetDoneView.as_view(template_name='password_reset_done.html'),
name='password_reset_done'),
url(r'^reset/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$',
auth_views.PasswordResetConfirmView.as_view(template_name='password_reset_confirm.html'),
name='password_reset_confirm'),
url(r'^reset/complete/$',
auth_views.PasswordResetCompleteView.as_view(template_name='password_reset_complete.html'),
name='password_reset_complete'),
url(r'^settings/password/$', auth_views.PasswordChangeView.as_view(template_name='password_change.html'),
name='password_change'),
url(r'^settings/password/done/$', auth_views.PasswordChangeDoneView.as_view(template_name='password_change_done.html'),
name='password_change_done'),
url(r'^boards/(?P<pk>\d+)/$', views.board_topics, name='board_topics'),
url(r'^boards/(?P<pk>\d+)/new/$', views.new_topic, name='new_topic'),
url(r'^boards/(?P<pk>\d+)/topics/(?P<topic_pk>\d+)/$', views.topic_posts, name='topic_posts'),
url(r'^boards/(?P<pk>\d+)/topics/(?P<topic_pk>\d+)/reply/$', views.reply_topic, name='reply_topic'),
url(r'^admin/', admin.site.urls),
]
And here is my views.py file
from django.contrib.auth.decorators import login_required
from django.shortcuts import get_object_or_404, redirect, render
from .forms import NewTopicForm, PostForm
from .models import Board, Post, Topic
def home(request):
boards = Board.objects.all()
return render(request, 'home.html', {'boards': boards})
def board_topics(request, pk):
board = get_object_or_404(Board, pk=pk)
return render(request, 'topics.html', {'board': board})
#login_required
def new_topic(request, pk):
board = get_object_or_404(Board, pk=pk)
if request.method == 'POST':
form = NewTopicForm(request.POST)
if form.is_valid():
topic = form.save(commit=False)
topic.board = board
topic.starter = request.user
topic.save()
Post.objects.create(
message=form.cleaned_data.get('message'),
topic=topic,
created_by=request.user
)
return redirect('topic_posts', pk=pk, topic_pk=topic.pk)
else:
form = NewTopicForm()
return render(request, 'new_topic.html', {'board': board, 'form': form})
def topic_posts(request, pk, topic_pk):
topic = get_object_or_404(Topic, board__pk=pk, pk=topic_pk)
return render(request, 'topic_posts.html', {'topic': topic})
#login_required
def reply_topic(request, pk, topic_pk):
topic = get_object_or_404(Topic, board__pk=pk, pk=topic_pk)
if request.method == 'POST':
form = PostForm(request.POST)
if form.is_valid():
post = form.save(commit=False)
post.topic = topic
post.created_by = request.user
post.save()
return redirect('topic_posts', pk=pk, topic_pk=topic_pk)
else:
form = PostForm()
return render(request, 'reply_topic.html', {'topic': topic, 'form': form})
and here's my templates/reply_topic file
{% extends 'base.html' %}
{% load static %}
{% block title %}Post a reply{% endblock %}
{% block breadcrumb %}
<li class="breadcrumb-item">Boards</li>
<li class="breadcrumb-item">{{ topic.board.name }}</li>
<li class="breadcrumb-item">{{ topic.subject }}</li>
<li class="breadcrumb-item active">Post a reply</li>
{% endblock %}
{% block content %}
<form method="post" class="mb-4" novalidate>
{% csrf_token %}
{% include 'includes/form.html' %}
<button type="submit" class="btn btn-success">Post a reply</button>
</form>
{% for post in topic.posts.all %}
<div class="card mb-2">
<div class="card-body p-3">
<div class="row mb-3">
<div class="col-6">
<strong class="text-muted">{{ post.created_by.username }}</strong>
</div>
<div class="col-6 text-right">
<small class="text-muted">{{ post.created_at }}</small>
</div>
</div>
{{ post.message }}
</div>
</div>
{% endfor %}
{% endblock %}
I followed the tutorial exactly, but the reply worked when I typed in the URL, not when I clicked on the reply button. Is there an explanation for this, or am I missing something?
I am trying to add a user registration page but its showing
NoReverseMatch at /register/
Here is my project urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('', include('pages.urls')),
path('accounts/', include('django.contrib.auth.urls')),
path('admin/', admin.site.urls),
]
Pages urls.py
from django.urls import path
from .views import *
from django.contrib.auth import views
app_name = 'pages'
urlpatterns = [
path('', home_view, name='home'),
path('register/', register_user, name='register'),
]
Pages views.py
def home_view(request, *args, **kwargs):
return render(request, 'home.html', {})
def register_user(request, *args, **kwargs):
if request.method=='POST':
form = UserCreationForm(request.POST)
if form.is_valid():
form.save()
username = form.cleaned_data['username']
password = form.cleaned_data['password1']
user = authenticate(username=username, password=password)
login(request, user)
return redirect('home')
else:
form = UserCreationForm()
context = {'form': form}
return render(request, 'register.html', context)
register.html
<!DOCTYPE html>
<html>
<head>
<title>Register</title>
</head>
<h2>Register here</h2>
<body>
<form method="post" action="{% url 'register' %}">
{% csrf_token %}
{% if form.errors %}
<p>Invalid details</p>
{% endif %}
{{ form }}
<input type="submit" value="Register">
</form>
</body>
</html>
All is fine but still it's showing error
NoReverseMatch at /register/
Reverse for 'register' not found. 'register' is not a valid view function or pattern name.
In the urls.py file, you specified a namespace:
from django.urls import path
from .views import *
from django.contrib.auth import views
app_name = 'pages'
urlpatterns = [
path('', home_view, name='home'),
path('register/', register_user, name='register'),
]
This means that in order to refer to such named view, you need to prefix it with the namespace. So that means in the template you need to write it like:
<!DOCTYPE html>
<html>
<head>
<title>Register</title>
</head>
<h2>Register here</h2>
<body>
<form method="post" action="{% url 'pages:register' %}">
{% csrf_token %}
{% if form.errors %}
<p>Invalid details</p>
{% endif %}
{{ form }}
<input type="submit" value="Register">
</form>
</body>
</html>
Furthermore the redirect(..) should be rewritten the same way:
def register_user(request, *args, **kwargs):
if request.method=='POST':
form = UserCreationForm(request.POST)
if form.is_valid():
form.save()
username = form.cleaned_data['username']
password = form.cleaned_data['password1']
user = authenticate(username=username, password=password)
login(request, user)
return redirect('pages:home')
else:
form = UserCreationForm()
context = {'form': form}
return render(request, 'register.html', context)
I have tried to entered data to Mysql database using Django. The user enters the required data through addSubscriber.html page to save in the database but the data entered is not saved in the database. Whenever I check the Mysql table (in this case 'Subscribers' table), the table is empty. Should I install mysql-connecter or not?
Here are my files:
views.py
from django.shortcuts import render, redirect
from django.contrib.auth.decorators import login_required
from django.views import generic
from .models import Subscribers
from .forms import addSubsForm
#login_required
def dashboard(request):
user = request.user
context = {'user': user}
template = 'dashboard.html'
return render(request, template, context)
#login_required
def addSubscriber(request):
template = 'addSubscriber.html'
if request.method == 'POST':
form = addSubsForm(request.POST)
if form.is_valid():
name = form.cleaned_data['name']
area = form.cleaned_data['area']
phoneNumber = form.cleaned_data['phoneNumber']
installationCost = form.cleaned_data['installationCost']
billNumber = form.cleaned_data['billNumber']
print name
Subs = Subscribers.objects.create(name=name, area=area, phoneNumber=phoneNumber, installationCost=installationCost, billNumber=billNumber)
Subs.save()
return redirect('report')
else:
form = addSubsForm()
return render(request, template, {'form': form})
#login_required
def report(request):
context = locals()
template = 'report.html'
return render(request, template, context)
models.py
from __future__ import unicode_literals
from django.db import models
class Subscribers(models.Model):
name = models.CharField(max_length=120)
area = models.CharField(max_length=30)
phoneNumber = models.CharField(max_length=10)
installationCost = models.CharField(max_length=10)
billNumber = models.CharField(max_length=100, unique=True)
addSubscriber.html
{%extends 'base.html'%}
{% load staticfiles %}
{% load crispy_forms_tags %}
{% block content %}
<div class="row">
<div class="col-xs-7">
{% if form %}
<br>
<form class="POST" action="." method="post">
{% csrf_token %}
{{ form|crispy }}
<input type="submit" value="submit form" class="btn btn-primary"/>
</form>
{% endif %}
</div>
</div>
{% endblock %}
urls.py
from dashboard import views as dashboard_views
from profiles import views as profiles_views
from django.conf import settings
from django.conf.urls import url, include
from django.conf.urls.static import static
from django.contrib import admin
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^$', profiles_views.home, name='homepage'),
url(r'^contact/$', profiles_views.contact, name='contact'),
url(r'^dashboard/$', dashboard_views.dashboard, name='dashboard'),
url(r'^dashboard/addSubscriber/$', dashboard_views.addSubscriber, name='addSubscriber'),
url(r'^dashboard/userDetail/$', dashboard_views.userDetail, name='userDetail'),
url(r'^dashboard/report/$', dashboard_views.report, name='report'),
url(r'^account/', include('allauth.urls')),
]
# this statement says that: if in the settings file, DEBUG is true than use this static URL
if settings.DEBUG:
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
Since you are using two databases, for saving entities you should specify which database to save by specifying
Subs.save(using='db2')
According to Django documentation:
If you don’t specify using, the save() method will save into the
default database allocated by the routers.
well you dont need all this extra things in the view as you are using form and why use create and also save??
just try this inside the form.is_valid
if form.is_valid():
f = form.save(commit=False)
f.save(using='db2')
return redirect('report')
I am new to django and I am currently trying to build a website that allows users to sign in and view other users profiles. So far I have managed to let users sign in but I can't work out how to view other peoples profiles.
Each profile uses the users username to create a url for their profile. Currently if I sign in as one user and change the URL to another users profile URL, it still displays the current users profile. I want something similar to pinterest where any person whether they are signed in or not can view peoples profiles.
Any help would be appreciated!
View
from django.http import HttpResponse
from django.shortcuts import render
from howdidu.forms import UserProfileForm
from howdidu.models import UserProfile
from django.contrib.auth.decorators import login_required
from django.shortcuts import get_object_or_404
from django.contrib.auth.models import User
def index(request):
context_dict = {'boldmessage': "I am bold font from the context"}
return render(request, 'howdidu/index.html', context_dict)
#user profile form
#login_required
def register_profile(request):
profile = UserProfile.objects.get(user=request.user)
if request.method == 'POST':
form = UserProfileForm(request.POST, request.FILES, instance=profile)
if form.is_valid():
form.save()
return index(request)
else:
print form.errors
else:
form = UserProfileForm()
return render(request, 'howdidu/register_profile.html', {'form': form})
#profile page using user name as url
#login_required
def profile_page(request, username):
user = get_object_or_404(User, username=username)
return render(request, 'howdidu/profile.html', {'profile_user': user})
project url
from django.conf.urls import patterns, include, url
from django.contrib import admin
from django.conf import settings
from registration.backends.simple.views import RegistrationView
class MyRegistrationView(RegistrationView): #redirects to home page after registration
def get_success_url(self,request, user):
return '/register_profile'
urlpatterns = patterns('',
# Examples:
# url(r'^$', 'howdidu_project.views.home', name='home'),
# url(r'^blog/', include('blog.urls')),
url(r'^admin/', include(admin.site.urls)),
url(r'', include('howdidu.urls')),
url(r'^accounts/register/$', MyRegistrationView.as_view(), name='registration_register'), #redirects to home page after registration
(r'^accounts/', include('registration.backends.simple.urls')),
url(r'^(?P<username>\w+)/', include('howdidu.urls')), #do i need this?
)
# media
if settings.DEBUG:
urlpatterns += patterns(
'django.views.static',
(r'^media/(?P<path>.*)',
'serve',
{'document_root': settings.MEDIA_ROOT}), )
app url
from django.conf.urls import patterns, url
from howdidu import views
urlpatterns = patterns('',
url(r'^$', views.index, name='index'),
url(r'^register_profile/$', views.register_profile, name='register_profile'),
url(r'^(?P<username>\w+)/$', views.profile_page, name='user_profile'),
)
template
{% extends 'howdidu/base.html' %}
{% load staticfiles %}
{% block title %}{{ user.username }}{% endblock %}
{% block body_block %}
{% if user.is_authenticated %}
<h1>{{ user.username }} welcome to your profile page</h1>
<img src="{{ user.userprofile.profile_picture.url }}" width = "150" height = "150" />
<h2>{{ user.userprofile.first_name }}</h2>
<h2>{{ user.userprofile.second_name }}</h2>
<h2>{{ user.userprofile.user_country }}</h2>
{% endif %}
{% endblock %}
Register urls of your app in the configuration folder project_name/urls.py :
E.g :
from django.conf.urls import include, url
from django.contrib import admin
from django.conf import settings
urlpatterns = [
url(r'^user/', include('<app_name>.urls')),
url(r'^admin/', include(admin.site.urls)),
]
Add a new route in your <app_name>/urls.py.
E.g :
from . import views
urlpatterns = [
url(r'profile/(?P<username>[a-zA-Z0-9]+)$', views.get_user_profile),
]
Add a view in <app_name>/views.py that take username (username of the user) to retrieve its information and send them into a template
E.g :
from django.shortcuts import render
def get_user_profile(request, username):
user = User.objects.get(username=username)
return render(request, '<app_name>/user_profile.html', {"user":user})
Create a template file in <app_name>/templates/<app_name>/user_profile.htmlto display user object :
{{ user.username }}
{{ user.email }}
{{ user.first_name }}
{{ user.last_name }}
Replace <app_name> by the name of your app and it should be good.
I was creating a user registration system in django1.8. But when I click register button on the form, it does not redirect to the success url. I am also not sure if this is the right way to save a user information in the database. Please recommend if there is a better way to approach user registration in django.
Models.py
from django.db import models
from django.contrib.auth.models import User
class UserProfile(models.Model):
user = models.OneToOneField(User)
age = models.IntegerField(blank=True)
gender_choices = (('M', 'Male'), ('F', 'Female'))
gender = models.CharField(max_length=1, choices=gender_choices, default='Male')
forms.py
from django import forms
from .models import UserProfile
class UserProfileForm(forms.ModelForm):
class Meta:
model = UserProfile
exclude = ['user']
Views.py
from django.shortcuts import render, redirect
from django.core.urlresolvers import reverse
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
from .forms import UserProfileForm
# Create your views here.
def registerView(request):
if request.method == "POST":
user_form = UserCreationForm(request.POST)
user_profile_form = UserProfileForm(request.POST)
if user_form.is_valid() and user_profile_form.is_valid():
new_user = user_form.save()
new_user_profile = user_profile_form.save()
return redirect(reverse('success'))
else:
return render(request, 'register.html', {'user_form': user_form, 'user_profile_form': user_profile_form})
else:
user_form = UserCreationForm(request.POST)
user_profile_form = UserProfileForm(request.POST)
return render(request, 'register.html', {'user_form': user_form, 'user_profile_form': user_profile_form})
def successView(request):
username = User.objects.get('username')
return render(request, 'success.html', {'username': username})
urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^$', views.registerView, name='register'),
url(r'^success/$', views.successView, name='success')
]
register.html
<h1> Welcome </h1>
<form method="POST" action="{% url 'success' %}">
{% csrf_token %}
{{ user_form.as_p }}
{{ user_profile_form.as_p }}
<input type="button" value="Register"/>
</form>
success.html
<h4> Yo Mr...{{ username }}</h4>
<h1>Welcome</h1>
You need to make the following changes:
<h1> Welcome </h1>
<form method="POST" action="{% url 'register' %}">
{% csrf_token %}
{{ user_form.as_p }}
{{ user_profile_form.as_p }}
<input type="submit" value="Register"/>
</form>