My urls.py is something like this :
from django.conf.urls import url
from django.views.generic import ListView, TemplateView
from .models import Dreamreal
from . import views
urlpatterns = [
url(r'^connection/login/$', views.login),
url(r'^connection/$', TemplateView.as_view(template_name =
'login.html')),
url(r'^login/$', views.login, name = 'login')
]
My views.py is :
from .forms import LoginForm
from . import models
def login(request):
username = "not logged in"
if request.POST:
# GET THE POSTED FORM
MyLoginForm = LoginForm(request.POST)
if MyLoginForm.is_valid():
username = MyLoginForm.cleaned_data['username']
else:
MyLoginForm = LoginForm()
return render(request, 'loggedin.html', {'username' : username})
My forms.py is :
from django import forms
from .models import Dreamreal
class LoginForm(forms.Form):
username = forms.CharField(max_length = 100)
password = forms.CharField(widget = forms.PasswordInput())
# METHOD TO VERIFY IF USER IS IN DB
def clean_message(self):
username = self.cleaned_data.get("username")
dbuser = Dreamreal.objects.filter(name = 'username')
if not dbuser:
raise forms.ValidationError("User does not exist in our db!")
return username
My models.py is :
from django.db import models
class Dreamreal(models.Model):
website = models.CharField(max_length = 50)
mail = models.CharField(max_length = 50)
name = models.CharField(max_length = 50)
phonenumber = models.IntegerField()
class Meta:
db_table = 'dreamreal'
My login.html is :
<html>
<head>
<title>LOG IN</title>
</head>
<body>
<form name="form" action="/connection/login/" method="POST">
{% csrf_token %}
<div style="max-width: 470px;">
<center><input type="text" name="username"
placeholder="username" style="margin-left: 20%;" required>
</center>
</div>
<br>
<div style="max-width: 470px;">
<center><input type="password" name="password"
placeholder="password" style="margin-left: 20%;"></center>
</div>
<br>
<div style="max-width: 470px;">
<center><button style = "border:0px; background-color:#4285F4;
margin-top:8%; height:35px; width:80%;margin-left:19%;" type =
"submit" value = "Login" >
<strong>Login</strong>
</button></center>
</div>
</form>
</body>
</html>
My loggedin.html is :
{% extends 'base.html' %}
<html>
<head>
<title>{% block title%}{{ username }}{% endblock %}</title>
</head>
<body>
{% block content %}
You are : <strong>{{ username }}</strong>
{% endblock %}
When i am running the code and then entering the name and password in the dield input at /connection/ url, it is redirecting to /connectionlogin/ url but showing valid for all the usernames i am entering in the forms rather it should show only those names which are stored in the database name Dreamreal.
Somebody please help!
You are validating the username field, so you should name your method clean_username. Django will only call the clean_message field if the form has a field called message.
To see any form errors in the template you need to include the form in the context when you call render:
return render(request, 'loggedin.html', {'username' : username, 'form': MyLoginForm}
And you won't see the errors in the template unless you use form in the template. The easiest way to do this is to include {{ form }}. If you need to do something more advanced, see the docs on working with forms.
Related
I'm trying to make a user active when I tap a button, and I'm using a DetailView.
views.py
from .models import Model
from django.contrib.auth.models import User
from django.shortcuts import redirect
class UserInspectView(DetailView):
model = Model
template_name = 'user-inspect.html'
# Make the user is_active = True
def accept (request, pk):
user = User.objects.get(id=pk)
user.is_active
return redirect('home')
...
urls.py
from django.urls import path
from . import views
urlpatterns = [
path('inspect/<slug:slug>/', views.UserInspectView.as_view(), name='user-inspect'),
path('inspect/<int:pk>/accept/', views.accept, name="user-accept"),
...
]
user-inspect.html
{% extends 'base.html' %}
{% block title %} <title>User Inspection</title> {% endblock %}
{% block content %}
<div class="d-flex justify-content-center">
<div class="container d-flex flex-column">
<div class="ms-5 ps-5" >
<h3><strong>User:</strong> {{model.user}}</h3>
<br>
<h3><strong>Name:</strong> {{model.name}}</h3>
</div>
</div>
</div>
<br><br><br>
<div class="d-flex justify-content-center">
<div class="btn-toolbar" role="toolbar" aria-label="Toolbar with button groups">
<div class="btn-group me-2 me-5 pe-5" role="group" aria-label="First group">
<form method="post" action="{% url 'user-accept' model.user.pk %}">
{% csrf_token %}
<button type="submit" class="btn btn-primary">Accept</button>
</form>
</div>
<div class="btn-group me-2 me-5 ps-5" role="group" aria-label="First group">
Back
</div>
</div>
</div>
{% endblock %}
models.py
from django.db import models
from django.contrib.auth.models import User
class Model(models.Model):
name = models.CharField(max_length=100)
user = models.ForeignKey(User, on_delete=models.CASCADE)
slug = models.SlugField(unique=True, blank=False, null=False)
Before my accept view looked like this
def accept (request, pk):
user = User.objects.get(id=pk)
user.is_active()
user.save()
return redirect('home')
but I changed it, because I got this error
TypeError at inspect/30/accept/
'bool' object is not callable
When I tap the Accept button, it takes me to the redirect that I have in the accept view, but the user is still inactive.
user.is_active is a boolean not a function.
def accept (request, pk):
user = User.objects.get(id=pk)
user.is_active = True
user.save()
return redirect('home')
I've been trying different ways to send an attachment from a submitted form but I'm not able to get it right.
my model:
from django.db import models
class Document(models.Model):
description = models.CharField(max_length=255, blank=True)
document = models.FileField()
uploaded_at = models.DateTimeField(auto_now_add=True)
views.py
from django.shortcuts import render, redirect
from django.core.mail import EmailMessage
from decouple import config
from .forms import ContactForm
def contact(request):
contact_form = ContactForm()
if request.method == "POST":
contact_form = ContactForm(request.POST, request.FILES)
if contact_form.is_valid():
name = request.POST.get("name")
email = request.POST.get("email")
subject = request.POST.get("subject")
message = request.POST.get("message")
upload = request.POST.get("upload")
email_content= EmailMessage("Message from django-structure project",
f"The user with name {name}, with the email {email},"
f" write the following: \n Subject: {subject} \n File{upload} \n\n Message: {message}",
"", [config('EMAIL_TO')], reply_to=[email])
try:
email_content.send()
return redirect("/contact/?valid")
except:
return redirect("/contact/?invalid")
return render(request, "contact.html", {"form": contact_form})
contact.html
<div class="row">
<div class="col">
<div class="form-group">
{% if "valid" in request.GET %}
<p style="color: blue;">Information sent successfully </p>
{% endif %}
<form action="" method="POST" enctype="multipart/form-data" style="text-align: center;">
{% csrf_token %}
<table style="color: dark; margin:20px auto;">{{form.as_table}}</table>
<input type="submit" value="Send" style="width: 150px;">
</form>
</div>
When I submit the form, I receive the message but in the content of the File, just the following string: "FleNone". (I have attached a pdf)
In my template I have a form that includes two input elements whose values can be adjusted with javascript. I want to be able to take these values and, on form submit, display them in a sentence in a for loop underneath.
index.html:
<form action="{% url 'workouts:workout' %}" method="post">
{% csrf_token %}
<div class="weight">
<h4>WEIGHT (kgs):</h4>
<button type="button" class="weight-dec">-</button>
<input type="text" value="0" class="weight-qty-box" readonly="" name="one">
<button type="button" class="weight-inc">+</button>
</div>
<div class="reps">
<h4>REPS:</h4>
<button type="button" class="rep-dec">-</button>
<input type="text" value="0" class="rep-qty-box" readonly="" name="two">
<button type="button" class="rep-inc">+</button>
</div>
<input type="submit" value="Save" name="submit_workout">
<input type="reset" value="Clear">
</form>
{% if exercise.workout_set.all %}
{% for w in exercise.workout_set.all %}
{{ w.content }}
{% endfor %}
{% endif %}
I have given the form above an action attribute for a url which maps to a view, and each of the inputs has a name in order to access their values in the view. I also have written this form in forms.py:
class WorkoutModelForm(forms.ModelForm):
class Meta:
model = Workout
fields = ['content']
And for context, here is my model:
class Workout(models.Model):
content = models.CharField(max_length=50)
created = models.DateField(auto_now_add=True)
updated = models.DateField(auto_now=True)
exercise = models.ForeignKey(Exercise, on_delete=models.CASCADE, default=None)
class Meta:
ordering = ('created',)
My problem from here is that I have no idea how to actually incorporate my model form in my template, or how to write a view that will do what I want it to. I am still new to this and have been searching for an answer for sometime, but so far have not found one. Please help.
This is able to help you, you should first have a look at the django Class-Based Views , more specifically the FormView, django already has generic views capable of handling data posted on forms. Your code would look like this:
# forms.py
# imports ...
class WorkoutModelForm(forms.ModelForm):
class Meta:
model = Workout
fields = ['content']
# urls.py
from django.urls import path
from . import views
app_name = 'myapp'
urlpatterns = [
path("test-form/", views.TesteFormView.as_view(), name='test-form'),
]
# views.py
from django.views.generic import FormView
from myapp import forms
from django.contrib import messages
class TesteFormView(FormView):
template_name = "myapp/index.html"
success_url = reverse_lazy('myapp:test-form')
form_class = forms.WorkoutModelForm
def get(self, request, *args, **kwargs):
return super(TesteFormView, self).get(request, *args, **kwargs)
def form_valid(self, form):
print(f"POST DATA = {self.request.POST}") # debug
content = form.cleaned_data.get('content')
# fieldx= form.cleaned_data.get('fieldx')
# do something whit this fields like :
Workout.object.create(content=content)
messages.success(self.request,"New workout object created")
return super(TesteFormView, self).form_valid(form=self.get_form())
def form_invalid(self, form):
print(f"POST DATA = {self.request.POST}") # debug
for key in form.errors:
messages.error(self.request, form.errors[key])
return super(TesteFormView, self).form_invalid(form=self.get_form())
And your template would look like:
# myapp/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>TestForm</title>
</head>
<body>
<form method="post">
{% csrf_token %}
{{ form }}
<button type="submit">submit</button>
</form>
</body>
</html>
I am trying to create a student register page that allows the student to upload a profile photo. I am using Django User model and a StudentProfile model that has a OneToOne relation with User. Here are my codes:
student\models.py:
from django.db import models
from django.contrib.auth.models import User
class StudentProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE,)
avatar = models.ImageField(upload_to='student_profile/', null=True, blank=True)
def __str__(self):
return self.user.username
students/form.py:
from django import forms
class ImageUploadForm(forms.Form):
profile_photo = forms.ImageField()
eLearning/views.py:
from django.contrib.auth import authenticate, login, get_user_model
from django.http import HttpResponse
from django.shortcuts import render, redirect
from .forms import LoginForm, RegisterForm
from students.forms import ImageUploadForm
from students.models import StudentProfile
User = get_user_model()
def register_page(request):
register_form = RegisterForm(request.POST or None)
photo_upload_form = ImageUploadForm(request.POST, request.FILES)
context = {
"register_form": register_form,
"photo_upload form": photo_upload_form
}
if register_form.is_valid():
# print(register_form.cleaned_data)
username = register_form.cleaned_data.get("username")
first_name = register_form.cleaned_data.get("first_name")
last_name = register_form.cleaned_data.get("last_name")
email = register_form.cleaned_data.get("email")
password = register_form.cleaned_data.get("password")
new_user = User.objects.create_user(
username, email, password,
first_name=first_name,
last_name=last_name,
)
if photo_upload_form.is_valid():
user = username
avatar = photo_upload_form.cleaned_data.get("profile_photo")
new_user_profile = StudentProfile.objects.create(user, avatar)
print(new_user)
return render(request, "auth/register.html", context)
auth/register.html:
{% extends "base.html" %}
{% load static %}
{% block content %}
{% load crispy_forms_tags %}
<div class="container">
<div class="row my-4">
<div class="col-5">
<form action="" method="post" class="form-control">
{% csrf_token %}
{{ register_form|crispy }}
<input type="submit" class="btn btn-default" value="Submit">
</form>
</div>
<div class="col-5">
<form method="post" enctype="multipart/form-data" class="form-control">
{% csrf_token %}
<input id="id_image" type="file" class="my-2" name="image">
{{ photo_upload_form|crispy }}
</form>
</div>
</div>
</div>
{% endblock %}
I am facing 2 problems:
1) The ImageUploadForm is not rendering on to register.html
2) A StudentProfile is not being created. User is being created fine.
I also tried replacing form with ModelForm for ImageUploadForm but I get a NULL constraint for student_user since Django doesn't what user for StudentProfile is.
I have been looking through Stack Overflow. All solutions are about how to upload a user image to Django admin but I haven't found anything that shows how to associate the uploaded image to User model during registration. Forgive me if this is a repeated question. Thanks.
In your eLearning/views.py:
the context you are passing to the html page the _ is missing
context = {
"register_form": register_form,
"photo_upload form": photo_upload_form
}
This will be the reason for the ImageUploadForm is not rendering on to register.html
It's should be like
context = {
"register_form": register_form,
"photo_upload_form": photo_upload_form
}
So I figured it out. The real issue was with the register.html code. The submit button only worked for the register_form so the photo upload form was not validating, hence student profile entry was not being created. Here's the updated code:
eLearning/views.py:
from students.forms import ImageUploadForm
from students.views import upload_pic
def register_page(request):
register_form = RegisterForm(request.POST or None)
photo_upload_form = ImageUploadForm(request.POST, request.FILES)
context = {
"register_form": register_form,
"photo_upload_form": photo_upload_form
}
if register_form.is_valid():
username = register_form.cleaned_data.get("username")
first_name = register_form.cleaned_data.get("first_name")
last_name = register_form.cleaned_data.get("last_name")
email = register_form.cleaned_data.get("email")
password = register_form.cleaned_data.get("password")
new_user = User.objects.create_user(
username, email, password,
first_name=first_name,
last_name=last_name,
)
upload_pic(request, photo_upload_form, username=username)
return render(request, "auth/register.html", context)
students/views.py:
from django.contrib.auth import get_user_model
from django.http import HttpResponseRedirect
from django.shortcuts import render, redirect, HttpResponse
from .models import StudentProfile
from .forms import ImageUploadForm
def upload_pic(request, form, username):
if request.method == 'POST':
if form.is_valid():
User = get_user_model()
user = User.objects.get(username=username)
avatar = form.cleaned_data.get('profile_photo')
new_user_profile = StudentProfile.objects.create(user=user, avatar=avatar)
new_user_profile.save()
register.html:
{% extends "base.html" %}
{% load static %}
{% block content %}
{% load crispy_forms_tags %}
<div class="container">
<div class="row my-4">
<div class="col-5">
<form action="" method="post" enctype="multipart/form-data" class="form-control">
{% csrf_token %}
{{ register_form|crispy }}
{{ photo_upload_form|crispy }}
<input type="submit" class="btn btn-default" value="Submit">
</form>
</div>
</div>
</div>
{% endblock %}
You have to make sure enctype="multipart/form-data" is inside your tags or the image upload form will not get validated. I would also recommend adding an image validation method to your form.py. Something Sachin pointed out earlier: image form and validation. Hope this helps.
My problem is, when I validate forms for errors, some text with warning would show up, But id does not. I was searching for some good answers and I tried also everything.
I was trying to implement validation in my register subpage so....
First is my model.py for registration
from django.db import models
class User(models.Model):
name = models.CharField(max_length=30)
email = models.EmailField(max_length=30)
password = models.CharField(max_length=30)
def __str__(self):
return "Login: " + self.name + \
" | e-mail: " + self.email + \
" | password: " + self.password
Second is my inputForms.py with simple validation
from django import forms
from django.contrib.auth.models import User
from django.contrib import messages
from .models import User
class NewUser(forms.Form):
name = forms.CharField(required=True)
email = forms.EmailField(required=True)
password = forms.CharField(widget=forms.PasswordInput, required=True)
pic1 = forms.CharField(required=True)
pic2 = forms.CharField(required=True)
pic3 = forms.CharField(required=True)
pic4 = forms.CharField(required=True)
pic5 = forms.CharField(required=True)
class Meta:
model = User
fields = ('name', 'email', 'password')
def clean_email(self):
email_passed = self.cleaned_data.get('email')
email_req = "yourdomain.com"
if not email_req in email_passed:
raise forms.ValidationError("Not a valid email. Please try again")
return email_passed
Third is my view.py
from django.http import HttpResponseRedirect
from django.shortcuts import render
from definitions import SITE_ROOT
from .models import User
from . import inputForms
from threading import Thread
import base64
import re
import os
def index(request):
if request.method == 'GET':
return render(request, 'register.html', {'NewUser': inputForms.NewUser})
else:
return HttpResponseRedirect('/Kniznica')
def new_user(request):
if request.method == 'POST':
form = inputForms.NewUser(request.POST)
if form.is_valid():
user_name = form.cleaned_data['name']
user_email = form.cleaned_data['email']
user_password = form.cleaned_data['password']
thread = Thread(target=save_user, args=(form, user_name, user_email, user_password, ))
thread.start()
return HttpResponseRedirect('/Kniznica')
else:
return render(request, "register.html", {'NewUser': inputForms.NewUser})
def save_user(form, user_name, user_email, user_password):
base_to_png(form.cleaned_data['pic1'], user_name, "face1.png")
base_to_png(form.cleaned_data['pic2'], user_name, "face2.png")
base_to_png(form.cleaned_data['pic3'], user_name, "face3.png")
base_to_png(form.cleaned_data['pic4'], user_name, "face4.png")
base_to_png(form.cleaned_data['pic5'], user_name, "face5.png")
user_instance = User.objects.create(name=user_name, email=user_email, password=user_password)
user_instance.save()
def base_to_png(base64_string, name, image_name):
string_without_header = re.sub('^data:image/.+;base64,', '', base64_string)
img_data = base64.b64decode(string_without_header)
if not os.path.exists(SITE_ROOT + "/faceId/" + name):
os.makedirs(SITE_ROOT + "/faceId/" + name)
filename = SITE_ROOT + "/faceId/" + name + "/" + image_name
with open(filename, 'wb') as f:
f.write(img_data)
os.chdir(SITE_ROOT + "\static\scripts")
os.system("node face-detection.js " + name + " " + image_name)
And fourth is my template.html for registration
<div>
<form action="newUser" method="post" novalidate>
{% csrf_token %}
{{ form.non_field_errors }}
{{ form.username.errors }}
{% if form.errors %}
{% for field in form %}
{% for error in field.errors %}
<p> {{ errors }} </p>
{% endfor %}
{% endfor %}
{% endif %}
<div style="display: inline-block">
Meno:{{ NewUser.name }}
</div>
<div style="display: inline-block">
Email:{{ NewUser.email }}
</div>
<div style="display: inline-block">
Heslo:{{ NewUser.password }}
</div>
<div hidden>
{{ NewUser.pic1 }}
{{ NewUser.pic2 }}
{{ NewUser.pic3 }}
{{ NewUser.pic4 }}
{{ NewUser.pic5 }}
</div>
<div>
<video id="video" width="300" height="300" autoplay></video>
</div>
<div>
<p id="counter"></p>
<button type="button" id="snap">Snap Photo</button>
<button type="submit" id="save" name="register">Registrácia</button>
</div>
<canvas hidden id="canvas" width="640" height="480"></canvas>
</form>
</div>
You have an unusual view structure here - normally you would use the same view for displaying the initial form as you would for processing the submission and displaying errors.
But nevertheless, you do have a couple of obvious issues. Firstly, in your new_user view, when the form is not valid you don't send that invalid form back, but instead send the form class itself. You should always send an instance of the form anyway, and in this case you should send back the same instance you have already validated, because that's the thing with the errors:
return render(request, "register.html", {'NewUser': form})
Secondly, in your template, you are inconsistent about what you call the form. When you render the fields, you access it via NewUser. But in trying to display the errors, for some reason you call it form. As you have used the name NewUser when you send it from the view, you should use that to display the errors:
{{ NewUser.errors }}