Working with tutorial tango with django(fun with forms) ,error is showing 'CategoryForm' object has no attribute 'save' pls help
The project tango_withDjango has a app rango in it p.s. identation are correct in my program unlike here...and using ModelForm will show error
views.py is
from django.http import HttpResponse
from django.template import RequestContext
from django.shortcuts import render_to_response
from rango.models import Category
from rango.models import Page
from rango.forms import CategoryForm
def add_category(request):
# Get the context from the request.
context = RequestContext(request)
# A HTTP POST?
if request.method == 'POST':
form = CategoryForm(request.POST)
# Have we been provided with a valid form?
if form.is_valid():
# Save the new category to the database.
form.save()
# Now call the index() view.
# The user will be shown the homepage.
#return index(request)
else:
# The supplied form contained errors - just print them to the terminal.
print form.errors
else:
# If the request was not a POST, display the form to enter details.
form = CategoryForm()
# Bad form (or form details), no form supplied...
# Render the form with error messages (if any).
return render_to_response('rango/add_category.html', {'form': form}, context)
models.py`
from django.db import models
class Category(models.Model):
name=models.CharField(max_length=128,unique=True)
def __unicode__(self):
return self.name
class Page(models.Model):
category=models.ForeignKey(Category)
title=models.CharField(max_length=128)
url=models.URLField()
views=models.IntegerField(default=0)
def __unicode__(self):
return self.title
forms.py
from django import forms
from rango.models import Page,Category
class CategoryForm(forms.Form):
name=forms.CharField(max_length=128,help_text="Please enter Category name")
views=forms.IntegerField(widget=forms.HiddenInput(),initial=0)
likes=forms.IntegerField(widget=forms.HiddenInput(),initial=0)
class Meta:
model=Category
class PageForm(forms.ModelForm) :
title=forms.CharField(max_length=128,help_text="Please enter title of the Pages")
url=forms.URLField(max_length=200,help_text="please enter url of the page")
views=forms.IntegerField(widget=forms.HiddenInput(),initial=0)
class Meta :
model=Page
fields=('title','url','views')
CategoryForm should extend the ModelForm, not the Form.
And btw, class Meta does not exist for Form
Related
I am having trouble displaying items owned only by specific users, rather than each user getting to see all items in my database. Below is an example of a non-superuser who has access to all items in my database when this user should only have access to the ones they created
image of dropdown menu with all items instead of just some
Below are the Form, View, and Models I have created in attempt to do this.
forms.py
class RoutineForm(forms.ModelForm):
"""creates a form for a routine"""
class Meta:
model = Routine
fields = ['workout']
labels = {'workout': 'Workout'}
Here is the views.py
from django.shortcuts import render, redirect
from django.http import HttpResponseRedirect, Http404
from django.urls import reverse
from django.contrib.auth.decorators import login_required
#login_required
def routine(request):
"""display a dropdown of all workouts for a user"""
if request.method != 'POST':
form = RoutineForm()
else:
form = RoutineForm(data=request.POST)
if form.is_valid():
new_routine = form.save(commit=False)
new_routine.save()
return redirect('index')
context = {'workouts':workouts, 'form':form}
return render(request, 'routine_workouts_app/routine.html', context)
and finally, the models.py file
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class Workout(models.Model):
"""A workout group the user will use to workout"""
text = models.CharField(max_length=200) #titles should not be too long
owner = models.ForeignKey(User, on_delete=models.CASCADE)
def __str__(self):
"""Return a string representation of the model"""
return self.text
class Routine(models.Model):
"""Shows a routine"""
workout = models.ForeignKey(Workout, on_delete=models.CASCADE)
owner = models.ForeignKey(User, on_delete=models.CASCADE)
def __str__(self):
return 'this is a routine'
Am I missing some sort of filter? Something Fundamental? I have been able to filter some other views that I have made. For example:
#login_required
def workouts(request):
"""This is the page that will display all the workout groups"""
workouts = Workout.objects.filter(owner=request.user).order_by('text') #filter by user ownership
context = {'workouts': workouts}
return render(request, 'routine_workouts_app/workouts.html', context)
on line 4 of this snippet, I have successfully filtered items that only belong to a specific user. But this is not a form, just a display on an html file. I have tried to put a similar line in the routine view function but it did not work. Any suggestions?
You can add a parameter to the constructor of the RoutineForm, that will filter the queryset specified to link to a Workout. This thus means that the form looks like:
class RoutineForm(forms.ModelForm):
"""creates a form for a routine"""
def __init__(self, *args, user=None, **kwargs):
super().__init__(*args, **kwargs)
self.fields['workout'].queryset = Workout.objects.filter(owner=user)
class Meta:
model = Routine
fields = ['workout']
labels = {'workout': 'Workout'}
In the view, we then can construct a Form where we pass the logged in user to the constructor of the form:
from django.shortcuts import render, redirect
from django.http import HttpResponseRedirect, Http404
from django.urls import reverse
from django.contrib.auth.decorators import login_required
#login_required
def routine(request):
"""display a dropdown of all workouts for a user"""
if request.method != 'POST':
form = RoutineForm(user=request.user)
else:
form = RoutineForm(data=request.POST, user=request.user)
if form.is_valid():
form.instance.owner = request.user
new_routine = form.save()
return redirect('index')
context = {'workouts':workouts, 'form':form}
return render(request, 'routine_workouts_app/routine.html', context)
How should I display the error messages on the HTML template, for Example I write a condition in the forms.py that if username already exist in the database, it should display the message on the HTML page, How should I do this?
Following is my code:
View.py
from django.shortcuts import render,redirect
from django.views.generic import View,TemplateView
from .forms import Registration_Form
from .models import User_Registration
from django.contrib import messages
# Create your views here.
class MainPageView(TemplateView):
template_name='main.html'
class LoginView(TemplateView):
template_name='login.html'
def RegistrationView(request):
form=Registration_Form()
if request.method=='POST':
form=Registration_Form(request.POST)
if form.is_valid():
user_name=form.cleaned_data['username']
print(User_Registration.objects.filter(username=user_name))
form.save()
return redirect('login_view')
else:
# messages.error(request,"Form is Invalid!")
return redirect('registration_view')
else:
return render(request,'registration.html',{'form':form})
# template_name='registration.html'
forms.py
from django import forms
from .models import User_Registration
class Registration_Form(forms.ModelForm):
class Meta:
model=User_Registration
fields=('company_name','username','password','email')
widgets={
'company_name':forms.TextInput(attrs={'class':'form-control input-sm'}),
'username':forms.TextInput(attrs={'class':'form-control'}),
'password':forms.PasswordInput(attrs={'class':'form-control'}),
'email':forms.EmailInput(attrs={'class':'form-control'}),
}
def clean(self):
user_name=self.cleaned_data['username']
if User_Registration.objects.filter(username=user_name).exists():
raise forms.ValidationError("Username Already Exist")
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.
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'.
In my Django project, I have to take the input from forms and pass it as an argument for a function that is in views.py. How do I do it?
My views.py code
from django.shortcuts import render,render_to_response
from django.http import Http404, HttpResponse, HttpResponseRedirect
from search_engine import query
from .forms import SearchForm
def query_input(request):
if request.method == "POST":
form = SearchForm(request.POST)
else:
form = SearchForm()
return render(request, 'search.html', {'form': form})
def search_results(request):
search_results = query.results(# text input from forms)
a = "<br /><br />".join(word for word in search_results)
return HttpResponse(a)
My forms.py code
from django import forms
class SearchForm(forms.Form):
your_query = forms.CharField(max_length=100)
After you checked that the request method is a POST you can validate the form and then access its attributes like this
In views.py:
if request.method = "POST":
form = SearchForm(request.POST)
if form.is_valid():
search_text = form.cleaned_data['search_text']
# code from search_results function to return HTTP Response
Check out the documentation on forms and view here for more information.