Django: AttributeError form has no attribute 'is_valid' - python

I'm having an issue saving comments for a blog app I'm writing in Django. The error is: AttributeError at /blog/123456/ 'comment' object has no attribute 'is_valid'
My models.py:
from django.db import models
class comment(models.Model):
comID = models.CharField(max_length=10, primary_key=True)
postID = models.ForeignKey(post)
user = models.CharField(max_length=100)
comment = models.TextField()
pub_date = models.DateTimeField(auto_now=True)
views.py:
from django.http import HttpResponse
from django.shortcuts import render
from django.template import RequestContext, loader
from django.db.models import Count
from blog.models import post, comment
from site.helpers import helpers
def detail(request, post_id):
if request.method == 'POST':
form = comment(request.POST)
if form.is_valid():
com = form.save(commit=False)
com.postID = post_id
com.comID = helpers.id_generator()
com.user = request.user.username
com.save()
return HttpResponseRedirect('/blog/'+post_id+"/")
else:
blog_post = post.objects.get(postID__exact=post_id)
comments = comment.objects.filter(postID__exact=post_id)
form = comment()
context = RequestContext(request, {
'post': blog_post,
'comments': comments,
'form': form,
})
return render(request, 'blog/post.html', context)
I'm not sure what the issue is, from the tutorials/examples I've been looking at, form should have the attribute is_valid(). Could someone help me understand what I'm doing wrong?

comment is a Model. is_valid method are present in forms. I think what you wnat to do is create a ModelForm for comment like this:
from django import forms
from blog.models import comment
class CommentForm(forms.ModelForm):
class Meta:
model=comment
And use CommentForm as IO interface to comment class.
You can learn more about ModelForms at the docs
Hope this helps!

Related

How to edit my views.py so that unauthorized users can see posts made public?

I have added a 'public' attribute to my models.py to allow users to make their posts public. I am trying to modify my views.py so that public posts are visible to unauthorised users.
Here is my code:
views.py
from django.shortcuts import render, redirect, get_object_or_404
from django.contrib.auth.decorators import login_required
from django.http import Http404
from .models import BlogPost
from .forms import BlogPostForm
def check_post_owner(request, post):
if post.owner != request.user:
raise Http404
#login_required()
def index(request):
"""Home Page for blogs"""
posts = BlogPost.objects.filter(owner=request.user).order_by('date_added')
context = {'posts': posts}
return render(request, 'blogs/index.html', context)
models.py
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class BlogPost(models.Model):
"""A blog post"""
title = models.CharField(max_length=30)
text = models.TextField()
date_added = models.DateTimeField(auto_now_add=True)
owner = models.ForeignKey(User, on_delete=models.CASCADE)
public = models.BooleanField(default=False)
def __str__(self):
return self.title
remove the login required decorator and try this way
def index(request):
"""Home Page for blogs"""
if request.user.is_authenticated:
posts = BlogPost.objects.filter(owner=request.user).order_by('date_added')
else:
posts = BlogPost.objects.filter(public=True).order_by('date_added')
return render(request, 'blogs/index.html', {'posts': posts})
you can filter the BlogPost by (public=True) that should work. so it should be like
posts = BlogPost.objects.filter(owner=request.user, public=True).order_by('date_added')

AttributeError: 'ModelFormOptions' object has no attribute 'private_fields' error message

I don't understand what this error means. It appears that I did everything correctly.
forms.py:
from django import forms
from django.forms import ModelForm
from .models import SignUpForm
class SignUpForm(forms.ModelForm):
class Meta:
model = SignUpForm
fields = ['name', 'company', 'city', 'country', 'email', 'password']
widgets = {
'password': forms.PasswordInput(),
}
This will throw:
AttributeError: 'ModelFormOptions' object has no attribute 'private_fields'
This is my views.py
from django.shortcuts import render
# Create your views here.
from django.http import HttpResponse
from .forms import signup
from django.utils.html import format_html
from django.contrib import messages
from .models import signup
def index(request):
return render(request, 'myapp/index.html')
def signup(request):
if request.method == 'POST':
register_form = signup(request.POST)
if register_form.is_valid():
post = register_form.save()
message = format_html("Hi {0}, Thank you for signing up with us! See your profile <a href=''>{1}</a>".format(register_form.cleaned_data['name'], "here"))
form = signup()
return render(request, 'myapp/register.html', {'signup':NewForm, 'message': message})
else:
message = register_form.errors
form = signup()
return render(request, 'myapp/register.html', {'signup':form, 'message': message})
else:
form = signup()
return render(request, 'myapp/register.html', {'signup':form})
Having a model named SignUpForm is a really bad idea for a multitude of reasons. Generally a class ending in Form should be a form class, not a model class. More importantly, it is most likely the cause of your error.
In your views.py you are probably doing something like this:
from .models import SignUpForm
from .forms import SignUpForm
def some_view(request):
if request.POST:
form = SignUpForm(request.POST)
else:
form = SignUpForm(instance=SignUpForm(col1='foo', col2='bar'))
Guess what? You just passed an instance of the SignUpForm form class to your SignUpForm, not the SignUpForm model!
Change the name of your SignUpForm model, and you most likely won't get errors.
If this didn't help please show me your views.py for this form.

How do I make a function in django to add comments to my reviews

I have a website made on Django and the users able to leave a review and Ive tried to make it so they can add comments, however they add a comment it just saves it to the database rather then adding it to the post. If anyone knows how I could change my code so that it instead adds the comments to the review that they message on rather then them not appearing on the website at all.
views.py:
from django.shortcuts import render, redirect #Render is used to show the HTML, and redirect is used when the user needs to be sent to a different page automatically.
from .models import Review #This imports the Review database.
from .forms import ReviewForm, CommentForm #This imports the comments and review form.
from django.utils import timezone
from django.contrib.auth.decorators import login_required #This requires the user to be logged in.
def review(request):
return render(request, 'review/review.html')
#login_required(login_url='/accounts/login/')
def review_new(request):
if request.method == "POST":
form = ReviewForm(request.POST)
if form.is_valid():
post = form.save(commit=False)
post.date = timezone.now()
post.author = request.user
post.save()
return redirect('/review')
else:
form=ReviewForm()
return render(request, 'review/post_edit.html', {'form': form})
def add_comment_to_post(request):
if request.method == "POST":
form = CommentForm(request.POST)
comment = form.save(commit=False)
comment.Review = review
comment.save() #This will save the comment to the database.
return redirect('reivew': review)
else:
form = CommentForm()
return render(request, 'review/add_comment_to_post.html', {'form': form})
models.py:
from django.db import models
from django.conf import settings
from django.utils import timezone
class Review(models.Model):
title = models.CharField(max_length=140)
body = models.TextField(max_length=3000)
date = models.DateTimeField()
author=models.ForeignKey(settings.AUTH_USER_MODEL, `on_delete=models.CASCADE, null=True)`
class comment(models.Model):
review = models.ForeignKey('review.Review', on_delete=models.CASCADE, related_name='comments', null=True)
author=models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, null=True)
text = models.TextField(max_length=3000)
created_date = models.DateTimeField(default=timezone.now)
def __str__(self):
return self.text
urls.py:
from django.urls import path, include, re_path
from django.views.generic import ListView, DetailView
from review.models import Review
from . import views
urlpatterns = [
path('', ListView.as_view(
queryset=Review.objects.all().order_by("-date")[:25],
template_name="review/review.html")),
re_path('(?P<pk>(\d+))',DetailView.as_view(model=Review, template_name="review/post.html")),
path('new/', views.review_new, name='review_new'),
path('new/comment', views.add_comment_to_post, name='add_comment_to_post'),
]
I can see that you should change comment.Review = review to something like comment.review = Review.objects.get(id=review_id) where review_id is an id passed from the form. Also notice that your Comment model allows the review to be null, which means currently you are adding comments without linking them correctly to the original post/review they should be related to.

NameError: name 'Video' is not defined

I have little problem, I tryed make video uploader but something go wrong
models.py
class Video(models.Model):
name= models.CharField(max_length=500)
videofile= models.FileField(upload_to='videos/', null=True, verbose_name="")
def __str__(self):
return self.name + ": " + str(self.videofile)
Forms.py
from django import forms
class VideoForm(forms.ModelForm):
class Meta:
model=Video
fields=["name", "videofile"]
views.py
from django.shortcuts import render
from .models import Video
from .forms import VideoForm
def showvideo(request):
lastvideo= Video.objects.last()
videofile= lastvideo.videofile
form= VideoForm(request.POST or None, request.FILES or None)
if form.is_valid():
form.save()
context= {'videofile': videofile,
'form': form
}
return render(request, 'Blog/videos.html', context)
And yes I made migrations but he telling me that name 'Video' is not defined
In your forms.py, you specify model = Video, but you forgot to import the Video class, hence in that file, the name Video is not defined.
You can import this like:
# forms.py
from django import forms
from .models import Video
class VideoForm(forms.ModelForm):
class Meta:
model = Video
fields = ["name", "videofile"]
Note that in your view, you should not write form= VideoForm(request.POST or None, request.FILES or None), since then the form becomes invalid if there are simply nor request.POST parameters. You should pass request.POST itself, not request.POST or None.

Conecting forms to admin page in django

I´m making my own portfolio and I wanna be able to see the messages that people sent me in the admin page but I don't seem to be able to make it so when someone submits the message it saves in the model and "broadcasts" in the admin page.
Models.py
from django.db import models
# Create your models here.
class Messages(models.Model):
name = models.CharField(max_length=100)
email = models.EmailField(max_length=50)
website = models.CharField(max_length=50)
text = models.CharField(max_length=500)
Forms.py
from django import forms
from django.core import validators
from django.forms import ModelForm
from .models import Messages
class Messages(forms.ModelForm):
name = forms.CharField(widget=forms.TextInput(attrs={'class' : 'name'}), required=True, label='', max_length=100)
email = forms.EmailField(widget=forms.TextInput(attrs={'class' : 'email'}), required=True, label='', max_length=50)
website = forms.CharField(widget=forms.TextInput(attrs={'class' : 'website'}),required=False, label='', max_length=50)
text = forms.CharField(widget=forms.TextInput(attrs={'class' : 'text'}), required=True, label='', max_length=500)
bot = forms.CharField(required=False, widget=forms.HiddenInput, validators=[validators.MaxLengthValidator(0)])
class Meta():
model = Messages
fields = '__all__'
Views.py
from django.shortcuts import render
from django.http import HttpResponse, HttpResponseNotFound
from django.template import Template, Context
from . import forms
# Create your views here.
def index(request):
return render(request, 'index.html')
def portfolio(request):
return render(request, 'portfolio.html')
def certificate(request):
return render(request, 'certificate.html')
def contact(request):
form = forms.Messages()
if request.method == 'post':
form = form.Messages(request.post)
if form.is_valid():
form.save(commit=True)
return thankyou(request)
else:
print('CONTACT ERROR')
return render(request, 'contact.html', {'form':form})
def thankyou(request):
return render(request, 'thankyou.html')
Admin.py
from django.contrib import admin
from toni.models import Messages
# Register your models here.
admin.site.register(Messages)
Python is case sensitive. The request.method will always be uppercase, and the post data is stored in request.POST. Change the code to:
if request.method == 'POST':
form = forms.Messages(request.POST)
You can debug problems like this by adding more print() lines. For example, you could have added print("in the post") after if request.method == 'post':. Then when you saw that the line was never printed, you could have added print(request.method). Hopefully you would then spot the mismatch between 'post' and 'POST'.

Categories

Resources