why Django form.is_valid() always false - python

I'm writing a login code.
but form.is_valid() always false
I don't know why?
model.py
class User(models.Model):
Man = 'M'
Woman = 'W'
GENDER_CHOICES=(
(Man, 'M'),
(Woman, 'W'),
)
user_no = models.AutoField(primary_key=True)
user_email = models.EmailField(max_length=254)
user_pw = models.CharField(max_length=50)
user_gender = models.CharField(
max_length=1,
choices=GENDER_CHOICES,
default=Man,
)
user_birthday = models.DateField(blank=True)
user_jdate = models.DateTimeField(auto_now_add=True)
signin.html
<form method="post" action="{% url 'signin' %}">
{% csrf_token %}
<h3>ID : {{form.user_email}} </h3>
<h3>PASSWORD : {{form.user_pw}} </h3>
<input type="submit" class="btn_submit" value="로그인" />
views.py
def signin(request):
if request.method == 'POST':
form = Form(request.POST)
if form.is_valid():
print("success")
else:
print("false")
else:
form = Form()
return render(request,'signin.html',{'form':form})
1) What's wrong?
2)The other signups are true because the signup_bails are true, but why is the signin always false?
3)How do I fix it?

I'd suggest a couple of things. First of, you need to define your Form Object first. If you did and you are importing this form, then please submit it here to review.
If you're interested in creating your own User Model, why don't you extend Django's User model. It already comes with all features like login, groups and permissions. Maybe you'd like other properties besides the Django User's Model. You can add this attributes within your extended model.
app/models.py
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin, UserManager, AbstractUser
class User(AbstractUser):
def __init__(self, *args, **kwargs):
super(User, self).__init__(*args, **kwargs)
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
is_staff = models.BooleanField(default=False)
def get_short_name(self):
return self.username
def __str__(self):
if self.first_name and self.last_name:
name = self.first_name + " " + self.last_name
else:
name = self.username
return name
def __unicode__(self):
return self.email
In this example you can see I've extended my custom 'User' Model to AbstractUser from django.contrib.auth.models, this means I can use all attributes from Django's User model but also I added three more fields (is_active, is_admin, is_staff).
Dont forget to register this new extended Model to settings.py
settings.py
AUTH_USER_MODEL = 'app.User'
Now let say you'd like to update User instances from your User Model. Let's use a Form that its based on this User model.
app/forms.py
from django import forms
from .models import User
class UpdateUserForm(forms.ModelForm):
class Meta():
model = User
Now to lets use this form in your views.py
app/views.py
from .models import User
from .forms import UpdateUserForm
from django.shortcuts import get_object_or_404
def update_user(request, id):
_user = get_object_or_404(User, id=id)
form = UpdateUserForm(instance=_user)
template = 'app/template.html'
if request.method == 'POST':
form = UpdateUserForm(request.POST, instance=_user)
if form.is_valid():
form.save()
context = {
'form':form
}
return render(request, template, context)

Related

How to use Django sessions

I'm new to Django and i'm trying to build a Todo app with user authentication but i want to add sessions to it whereby everyone can have different tasks attached to their accounts but i don't know how to go about it. I've checked the Django documentation on it but i still don't get it.
Here's my models.py
from django.db import models
from django.contrib.auth.models import AbstractUser
# Create your models here.
class Task(models.Model):
name = models.CharField(max_length=15)
completed = models.BooleanField(default=False)
def __str__(self):
return self.name
class User(AbstractUser):
name = models.CharField(max_length=200, null=True)
email = models.EmailField(unique=True, null=True)
bio = models.TextField(null=True, blank=True)
USERNAME_FIELDS = "email"
REQUIRED_FIELDS = []
Then here's my view.py
from django.shortcuts import render, redirect
from .models import Task, User
from .forms import AddTaskForm
#login_required(login_url="loginPage")
def home(request):
tasks = Task.objects.all()
context = {"tasks": tasks, }
return render(request, "task/home.html", context)
# Add task view
# login_required(login_url="loginPage")
def addTask(request):
addTaskForm = AddTaskForm()
if request.method == "POST":
addTaskForm = AddTaskForm(request.POST)
if addTaskForm.is_valid():
addTaskForm.save()
return redirect('home')
context = {"addTaskForm": addTaskForm}
return render(request, "task/addtask.html", context)
# Update task view
#login_required(login_url="loginPage")
def update(request, pk):
updateTask = Task.objects.get(id=pk)
updateTaskForm = AddTaskForm(instance=updateTask)
if request.method == "POST":
updateTaskForm = AddTaskForm(request.POST, instance=updateTask)
if updateTaskForm.is_valid():
updateTaskForm.save()
return redirect('home')
context = {"updateTaskForm": updateTaskForm}
return render(request, "task/update-task.html", context)
# Delete task view
# login_required(login_url="loginPage")
def delete(request, pk):
deleteTask = Task.objects.get(id=pk)
if request.method == 'POST':
deleteTask.delete()
return redirect("home")
context = {"deleteTask": deleteTask}
return render(request, "task/delete-task.html", context)
Don't need to go with sessions. You need to improve model using Django ORM.
Like:
#models.py
class User(AbstractUser):
name = models.CharField(max_length=200, null=True)
email = models.EmailField(unique=True, null=True)
bio = models.TextField(null=True, blank=True)
USERNAME_FIELDS = "email"
REQUIRED_FIELDS = []
class Task(models.Model):
user = models.ForeignKey(User,on_delete=models.CASADE)
name = models.CharField(max_length=15)
completed = models.BooleanField(default=False)
def __str__(self):
return self.name
While saving tasks in Task model, provide the id of the user in the user field.
check this simple use of sessions in django :
from django.http import HttpResponseRedirect
from django.shortcuts import render
from django import forms
from django.urls import reverse
class NewTaskForm(forms.Form) :
task = forms.CharField(label="Add Task ")
# Create your views here.
Tasks = []
def index(request) :
if "Tasks" not in request.session :
request.session["Tasks"] = []
return render(request , "tasks/index.html",{
"tasks" : request.session["Tasks"]
})
def add(request) :
if request.method == "POST" :
form = NewTaskForm(request.POST)
if form.is_valid() :
task = form.cleaned_data["task"]
request.session["Tasks"] += [task]
return HttpResponseRedirect(reverse("index"))
else :
return render(request , "tasks/add.html" , {
"form" : form
})
return render(request , "tasks/add.html" ,{
"form" : NewTaskForm()
})
with this method each user views their own task lists, i have a project same as what you looking for, here

How can I do username in reviews on django?

I'm doing reviews on django, but I want the user to not be able to enter any name. I want the username in the reviews to match the username of his profile
models.py
class Reviews(models.Model):
name = models.CharField('Имя', max_length=100)
text = models.TextField('Отзыв', max_length=3400)
parent = models.ForeignKey('self', verbose_name='Родитель', on_delete=models.SET_NULL, null=True, blank=True)
book = models.ForeignKey(BookModel, verbose_name='книга', on_delete=models.CASCADE)
name_user = models.ForeignKey(User, on_delete=models.CASCADE, null=True)
views.py
class MoreInfoView(View):
""" """
def get(self, request, id):
book_info = BookModel.objects.filter(id=id).first()
stuff = get_object_or_404(BookModel, id=self.kwargs['id'])
total_likes = stuff.total_likes()
return render(request, 'bookapp/more_info.html', context={
'id': id,
'book_info': book_info,
'book': BookModel.objects.all(),
'total_likes': total_likes,
})
class AddReview(View):
"""Add Review"""
def post(self, request, pk):
form = ReviewForm(request.POST)
book = BookModel.objects.get(id=pk)
if form.is_valid():
form = form.save(commit=False)
form.book = book
form.save()
return HttpResponseRedirect(reverse('more_info', args=[pk]))
forms
class ReviewForm(forms.ModelForm):
class Meta:
model = Reviews
fields = ("name", "text", 'name_user')
You can add user manually after validating ReviewForm
I also added some changes(suggestions)
models.py
class Reviews(models.Model):
name = models.CharField('Имя', max_length=100)
text = models.TextField('Отзыв', max_length=3400)
parent = models.ForeignKey('self', verbose_name='Родитель', on_delete=models.SET_NULL, null=True, blank=True)
book = models.ForeignKey(BookModel, verbose_name='книга', on_delete=models.CASCADE, blank=True)
user = models.ForeignKey(User, on_delete=models.CASCADE, blank=True)
Setting blank=True makes the field optional.
views.py
class MoreInfoView(View):
""" """
def get(self, request, id):
book_info = BookModel.objects.filter(id=id).first()
stuff = get_object_or_404(BookModel, id=self.kwargs['id'])
total_likes = stuff.total_likes()
return render(request, 'bookapp/more_info.html', context={
'id': id,
'book_info': book_info,
'book': BookModel.objects.all(),
'total_likes': total_likes,
})
class AddReview(View):
"""Add Review"""
def post(self, request, pk):
user = request.user
# User has to be authenticated to create a review. And backend must
# validate it. You should raise PermissionDenied as response or
# redirect user to the login page, or something similar.
if not request.user.is_authenticated:
raise PermissionDenied()
form = ReviewForm(request.POST)
book = BookModel.objects.get(id=pk)
if form.is_valid():
form = form.save(commit=False)
form.book = book
form.user = user
form.save()
return HttpResponseRedirect(reverse('more_info', args=[pk]))
forms.py
class ReviewForm(forms.ModelForm):
class Meta:
model = Reviews
fields = ("name", "text")
I would advise to work with a CreateView [Django-doc] that will simplify a lot of the logic. You can implement this as:
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic import CreateView
class AddReviewView(LoginRequiredMixin, CreateView):
form_class = ReviewForm
def get_success_url(self):
return reverse('more_info', args=[self.kwargs['pk']])
def form_valid(self, form):
form.instance.book_id = self.kwargs['pk']
form.name_user = self.request.user
return super().form_valid(form)
In your ReviewForm you thus remove the name_user as fields element.
Note: It is normally better to make use of the settings.AUTH_USER_MODEL [Django-doc] to refer to the user model, than to use the User model [Django-doc] directly. For more information you can see the referencing the User model section of the documentation.
Note: You can limit views to a class-based view to authenticated users with the
LoginRequiredMixin mixin [Django-doc].
Note: normally a Django model is given a singular name, so Review instead of Reviews.
Note: Models normally have no …Model suffix. Therefore it might be better to rename BookModel to Book.

Django get form with data from the database

I am trying to create a form that allows users to edit their profile data. As such I want to have the most recent data from the database be displayed when the user goes to edit the form. Heres what I have so far:
# models.py
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
location = models.CharField(max_length=30, blank=True)
birthdate = models.DateField(null=True, blank=True)
def __str__(self):
return self.user.username
# forms.py
class EditProfileForm(forms.ModelForm):
class Meta:
model = Profile
fields = ['location', 'birthdate']
# views.py
class EditProfileFormView(View):
form_class = EditProfileForm
template_name = 'forums/edit-profile.html'
def get(self, request, username):
try:
user = User.objects.get(username=username)
except User.DoesNotExist:
raise Http404('The User "' + username + '" could not be found.')
if (not request.user.is_authenticated):
return HttpResponseForbidden()
elif (user.id is not request.user.id):
return HttpResponseForbidden()
form = self.form_class(None)
return render(request, self.template_name, {'form': form})
Setting the form to form_class(None) is what gives me an empty form, however dropping user.profile in the same spot gives me an error 'Profile' object has no attribute 'get'
Try populating the form with an instance
form = self.form_class(instance=user.profile)
Note: this would probably be easier with a standard UpdateView

How can I set a default value to the model in Django?

I want to create a Invitation app which has a sender, receiver and message.
How can I set the current logged in user as a sender which is immutable?
In the model.py
class Invitation(models.Model):
from_user = models.CharField(max_length=100)
to_user = models.ForeignKey(User, related_name="invitations_received")
message = models.CharField(max_length=300)
timestap = models.DateTimeField(auto_now_add=True)
def __str__(self):
return "{} to {}: {}".format(self.from_user, self.to_user, self.message)
In the views.py
from django.shortcuts import render, redirect
from django.contrib.auth.decorators import login_required
from .models import Game
from .models import Invitation
from .forms import InvitationForm
#login_required
def new_invitation(request):
if request.method == 'POST':
form = InvitationForm(data=request.POST, from_user=request.user)
if form.is_valid():
form.save()
return redirect('profiles_home')
else:
form = InvitationForm()
return render(request, "arosis/new_invitation.html", {'form': form})
In the forms.py
from django.forms import ModelForm
from .models import Invitation
from django.shortcuts import render
class InvitationForm(ModelForm):
class Meta:
model = Invitation
You cannot simply default to the current user because Django ORM is not normally aware of Django authentication system. You should either:
1) Pass the request.user while creating the model instance, like:
invitation = Invitation(from_user=request.user)
or
2) Use a middleware that adds the current user to the model each time it is saved. You can try one of these packages: https://www.djangopackages.com/grids/g/model-audit/
I solved it easily for myself as below:
In the models.py:
class Invitation(models.Model):
from_user = models.ForeignKey(User, related_name="invitations_sent")
to_user = models.ForeignKey(User, related_name="invitations_received",
verbose_name="User to invite",
help_text="Please Select the user you want.")
message = models.CharField("Optional Message", max_length=300, blank=True,
help_text="Adding Friendly Message")
timestap = models.DateTimeField(auto_now_add=True)
def __str__(self):
return "{} to {}: {}".format(self.from_user, self.to_user, self.message)
In the views.py:
def new_invitation(request):
if request.method == 'POST':
invitation = Invitation(from_user=request.user)
form = InvitationForm(data=request.POST, instance=invitation)
if form.is_valid():
form.save()
return redirect('arosis_invite')
else:
form = InvitationForm(data=request.POST)
return render(request, "arosis/new_invitation.html", {'form': form})
In the forms.py:
class InvitationForm(ModelForm):
class Meta:
model = Invitation
exclude = ['from_user']
And in the template file:
I solved it really easy! by using:
{{ user.username }}

How to get value from Django authentication forms and use that value as input to another form?

I have a form used to create new posts in a blog, and one of the fields in that form is the owner, which means who is posting it, but that should be taken from login view when user provides his/her login information I don't want the user selecting who is the owner from a list, it should be automatically populated and fixed with his username. I tried different ways, fixing the value on my forms.py but didn't work, it doesn't recognizes the variable. This is my forms.py:
class UserForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput())
class Meta:
model = User
fields = ('username', 'email', 'password')
class UserProfileForm(forms.ModelForm):
class Meta:
model = UserProfile
fields = ('website', 'picture')
class CreatePostForm(forms.ModelForm):
class Meta:
model = Post
fields = ('title', 'body','datposted', 'category','owner')
Here is what I have on models:
class Post(models.Model):
title = models.CharField(max_length=100)
body = models.TextField()
datposted = models.DateTimeField('date posted')
category = models.ForeignKey('Category')
owner = models.ForeignKey('UserProfile')
def __str__(self):
return '%s' % self.title
This is my view:
def create_post(request):
if request.method == 'POST':
form = CreatePostForm(request.POST)
if form.is_valid():
post = form.save(commit=False)
post.datposted = datetime.datetime.now()
#post.owner = request.user()
post.save()
return HttpResponseRedirect('/posts/')
else:
return HttpResponse("Favor. Verifique os campos necessarios")
else:
form = CreatePostForm()
f = {'form' : form}
return render(request,'create_post.html',f)
Could you please help with more details?
I think you just have to remove the 'owner' field from the form and make sure that you handle populating the owner in your view
class CreatePostForm(forms.ModelForm):
class Meta:
model = Post
fields = ('title', 'body','datposted', 'category')
view
def create_post(request):
if request.method == 'POST':
form = CreatePostForm(request.POST)
if form.is_valid():
Posts = form.save(commit=False)
# replace below with however you get user profile
Posts.owner = get_user_profile_from_logged_in_user()
Posts.save()
return HttpResponseRedirect('/posts/')
else:
return HttpResponse("Favor. Verifique os campos necessarios")
else:
form = CreatePostForm()
f = {'form' : form}
return render(request,'create_post.html',f)
This case is covered in django docs:
https://docs.djangoproject.com/en/1.7/topics/forms/modelforms/#the-save-method

Categories