Cannot assign "Note.user" must be a "User" instance. Django - django

I am getting the following error on running my django code. I am an absolute beginner and I was following a tutorial to create a crud app.
On typing the information in my html form I get the following error
ValueError: Cannot assign django.contrib.auth.models.AnonymousUser object at 0x00000288775D3EF0: "Note.user" must be a "User" instance
from form.instance.user = request.user in my views.py
views.py
from django.shortcuts import render
from django.shortcuts import render, redirect
from .models import Note
# Create your views here.
from .forms import NoteModelForm
# CRUD - create update retrieve and delete
def createView(request):
form = NoteModelForm(request.POST or None, request.FILES or None)
if form.is_valid():
form.instance.user = request.user
form.save()
return redirect('/')
context = {
'form': form
}
return render(request, "create.html", context)
forms.py
from django import forms
from .models import Note
class NoteModelForm(forms.ModelForm):
class Meta:
model = Note
fields = ['title','url','image']
create.html
<!DOCTYPE html>
<html>
<head>
<title>CRUD APP</title>
</head>
<body>
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" name="submit">
</form>
</body>
</html>

If the user is not logged in, request.user gives AnonymousUser, which can't be assigned to the form instance.
To avoid this situation, you may add a condition before accessing the view. For this, you may use login_required decorator, as shown below
from django.contrib.auth.decorators import login_required
#login_required
def createView(request):
....

Related

Using Default UserCreationForm does not show error if the passwords do not match

Using Default UserCreationForm from django.contrib.auth.forms does not show error if the passwords do not match. I do not want to create a custom model.
Here is the code from my views.py file
from django.contrib.auth.forms import UserCreationForm
from django.shortcuts import render
# Create your views here.
def register(response):
if response.method == "POST":
print(response.POST)
form = UserCreationForm(response.POST)
if form.is_valid():
form.save()
else:
print(form.errors)
form = UserCreationForm()
return render(response,"register/register.html",{"form":form})
register.html code
<html>
<head>
<title>Register </title>
</head>
<body>
<h1>This is the Registration page</h1>
<form method="post">
{% csrf_token %}
{{form.as_p}}
<button type="submit">Submit</button>
</form>
</body>
</html>
I thought the message would be automatically displayed. Am I missing something?
Edit: None of the error message are being displayed like password length < 8, all numeric passwords, etc.
You each time create a new form, you should render the one that is invalid:
from django.shortcuts import redirect
def register(response):
if response.method == 'POST':
form = UserCreationForm(response.POST)
if form.is_valid():
form.save()
return redirect('name-of-some-view')
else:
form = UserCreationForm() # šŸ–˜ only for a GET request
return render(response, 'register/register.html', {'form': form})
Note: In case of a successful POST request, you should make a redirect
[Django-doc]
to implement the Post/Redirect/Get patternĀ [wiki].
This avoids that you make the same POST request when the user refreshes the
browser.

Django form won't render (modelForm)

I have an existing site, and I'm trying to render a form to it
I tried looping trough the form and rendering it field by field, but no luck. I think i might screwed up something in my views, im a beginner to django
HTML:
{%block wform%}
<form method="POST" class="form">
{% csrf_token %}
{{ form.as_p }}
<div class="form__group">
{%if user.is_authenticated%}
<input type="submit" class="submit" value="Submit Your Data">
{%else%}
Submit Your Data
{%endif%}
</div>
</form>
{%endblock wform%}
Forms.py
from django.forms import ModelForm
from users.models import Profile
class WeightForm(ModelForm):
class Meta:
model = Profile
fields = ['weight','height','goal']
Views.py
from django.shortcuts import render
from django.contrib import messages
from users import models
from users.models import Profile
from .forms import WeightForm
# Create your views here.
def home(request):
return render(request, 'Landing/index.html')
def formsave(request):
form = WeightForm()
return render(request, 'Landing/index.html', {'form': form})
from django.shortcuts import render
from django.contrib import messages
from users import models
from users.models import Profile
from .forms import WeightForm
# Create your views here.
def home(request):
form = WeightForm()
return render(request, 'Landing/index.html', {'form': form})

Django is_valid() always returns false error

I am beginner of Django. When i submit in the html page, is_valid funtion in my views.py always returns false. users.html is my template. I obviously filled things correctly but it still returns false.
Any help would be welcome.
this is my models.py file
from django.db import models
# Create your models here.
class User(models.Model):
first_name = models.CharField(max_length=264, )
last_name = models.CharField(max_length=264, )
email = models.EmailField(max_length=255,)
def __str__(self):
return self.first_name + self.last_name
this is my forms.py file
from django import forms
from first_app.models import User
from django.forms import ModelForm
class User_form(ModelForm):
class Meta:
model = User
fields = ['first_name','last_name','email']
this is my views.py file
from django.shortcuts import render
from django.http import HttpResponse
from . import forms
from first_app.models import User
# Create your views here.
def index(request):
return render(request,'index.html')
def user_form_view(request):
form = forms.User_form()
if request.method == 'POST':
if form.is_valid():
form = forms.User_form(request.post)
form.save()
return index(request)
else:
print(form)
return user_show(request)
return render(request,'first_app/users.html',{'form':form})
and this is my users.html
<!DOCTYPE html>
{% load static %}
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>Users</title>
</head>
<body>
<h1>Hello! please type in your information</h1>
<div class="container">
<form class="" method="POST">
{{form.as_p}}
{% csrf_token %}
<input type="submit" class="btn btn-primary" value="submit">
</form>
</div>
</body>
</html>
In order for a form to be valid, it needs to be "bounded" (you can check this with .is_bounded [Django-doc]). Bounded means that you passed data to it, for example with request.POST (or request.GET, or another dictionary-like container):
def user_form_view(request):
if request.method == 'POST':
form = forms.User_form(request.POST)
if form.is_valid():
form.save()
return index(request)
else:
print(form)
return user_show(request)
else:
form = forms.User_form()
return render(request,'first_app/users.html',{'form':form})
Note: the names of classes are typically written in PerlCase, not snake_case, so you probably should rename User_form to UserForm.

CSRF verification failed in Django project update, and RequestContext solution not working

I have a Django project in which trying to 'update' (clicking on the button) causes the following error:
CSRF verification failed. Request aborted.
Help
Reason given for failure:
CSRF token missing or incorrect.
I have viewed various questions and answers that suggest that adding RequestContext is the solution, but I have tried something to that effect tailored to my code, and still am unable to get it working.
Original code views.py is below
#USERS (register) view.py
from django.shortcuts import render,redirect
from django.contrib.auth.forms import UserCreationForm
from django.contrib import messages #this allows us flash messages for testing
from django.contrib.auth.decorators import login_required
from .forms import UserRegisterForm
from .forms import UserUpdateForm
from .forms import ProfileUpdateForm
from django.contrib.auth.decorators import login_required
def register(request):
if request.method =='POST':
#this UserRegisterForm is created in forms.py and inherits from UserCreationForm (the ready made form)
form = UserRegisterForm(request.POST) #create a form that has the data that was in request.POST
if form.is_valid(): #is the form valid (do you have a username like this already, passwords match?
form.save()
username = form.cleaned_data.get('username')
messages.success(request,f'Account created for {username}, you can now login.')
return redirect('login')
else:
form =UserRegisterForm() #if the form input is invalid, render the empty form again
return render(request, 'users/register.html',{'form':form})
#login_required #this is a decorator (adds functionality to an existing function)
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'Your Account has been directed')
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)
As mentioned I also tried:
return render(request,'users/profile.html',context_instance=RequestContext(request))
I also tried adding the below to imports
from django.shortcuts import get_object_or_404, render,redirect
Note: I do not wish to try the 'remove middleware' alternative.
The profile.html file code is below and I have included the CSRF token correctly, as far as I know:
{% extends "socialmedia/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">Profile Information</legend>
{{u_form|crispy}}
{{p_form|crispy}}
</fieldset>
<div class="form-group">
<button class="btn btn-outline-info" type="submit">Update....</button>
</div>
</form>
</div>
{% endblock content %}
Finally, for context, here is forms.py
from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
from .models import Profile
class UserRegisterForm(UserCreationForm): #form that inherits from the usercreationform
email = forms.EmailField()
class Meta:
model = User
#when this form validates it creates a new user
#type the fields to be shown on your form, in that order.
fields = ['username','email','password1','password2']
class UserUpdateForm(forms.ModelForm):
email = forms.EmailField()
class Meta:
model = User
fields = ['username','email']
class ProfileUpdateForm(forms.ModelForm):
class Meta:
model= Profile
fields=['image']
Question: What is causing the error and what do I need to add/change in the code as it stands?
I also came across an answer on StackOverflow which said this "The problem is you are not returning the result. Remember that the view is a function. You need to return render_to_response(...) not just call it (which is also why by removing CSRF you got the didn't return an HttpResponse error)" ....can someone explain this in my context? I don't understand what it means or how to implement it either.
It looks like it should work, however I noticed you seem to be missing a quote at the end here
<form method="POST" enctype="multipart/form-data>

django modelformset create one object

I am creating an app that allows anonymous input of data, and have condensed my difficulties down to a simple Author example.
My problem is that each time I input a new author, the number of forms rendered after Submit is increased by N+1 author. (ie the first time used, there is 1 form, then 2, then 3). I only want one blank form to be displayed, and then will later use other apps to retrieve the data.
It seems there could be two ways to solve the problem. 1) Get formset.management_form to return the last form (eg slicing: '{% for form in formset[-1] %}', which does not work. 2) To have view.py only send one new form instead of the formset in render_to_response() - how to do this?
---models.py---
from django.db import models
from django.forms import ModelForm
class Author(models.Model):
first_name = models.CharField(max_length=50)
class AuthorForm(ModelForm):
class Meta:
model = Author
---/models.py---
---views.py---
django.http import HttpResponseRedirect
from django.shortcuts import render_to_response
from django.template import RequestContext
from django.forms.models import modelformset_factory
from author.models import Author , AuthorForm
def manage_authors(request):
AuthorFormSet = modelformset_factory(Author)
if request.method == 'POST':
formset = AuthorFormSet(request.POST)
if formset.is_valid():
formset.save()
else:
formset = AuthorFormSet()
return render_to_response("manage_authors.html",{"formset": formset,})
---/views.py---
---manage_authors.html---
<!DOCTYPE html>
<html lang="en"
<body>
<form action="" method="post">
<table>
{{ formset.management_form }}
{% for form in formset %}
{{ form }}
{% endfor %}
</table>
<button type="submit">Submit</button>
</form>
</body>
</html>
---/manage_authors.html---
---urls.py---
from django.conf.urls import patterns, include, url
from author.views import manage_authors
urlpatterns = patterns('',
url(r"^author/$", manage_authors),
)
---/urls.py---
UPDATE:
Thanks for the suggestions to use modelform. The django docs had only shown template interactions with modelformset. Using:
---views.py---
def manage_authors(request):
form = AuthorForm(request.POST)
if request.method == 'POST':
if form.is_valid():
form.save()
else:
form = AuthorForm()
return render_to_response("manage_authors.html",{"form": form,})
---/views.py
and only using the the tag {{ form }} in manage_authors.html, does what I need.
Try using max_num and extra fields while creating model formset as
AuthorFormSet = modelformset_factory(Author, max_num=1, extra=1)
This will try to show at most 1 form, if there isn't any existing.
However, you may want to think if you really have to use modelformset as #Daniel Roseman suggested.