Django Error: 'function' object has no attribute 'save' - python

Can someone please tell me what i am doing wrong?
Model.py
class Cattest(models.Model):
category = models.ForeignKey(Category)
info = models.CharField(max_length=35, blank=True)
form.py
class CattestForm(forms.Form):
autocomplete = forms.CharField(
label='Type the name of a category (AutoCompleteWidget)',
widget=selectable.AutoCompleteWidget(CategoryLookup),
required=False,
)
info = forms.CharField(max_length=35, label="Information")
view.py
def cattest(request):
if request.method == 'POST':
form = CattestForm(request.POST)
if form.is_valid():
cattest.save()
else:
if request.GET:
form = CattestForm(initial=request.GET)
else:
form = CattestForm()
return render_to_response('bsmain/form.html', {'form': form}, context_instance=RequestContext(request))
Traceback:
AttributeError at /bsmain/cattest/
'function' object has no attribute 'save'
Request Method: POST
Request URL: http://127.0.0.1:8000/bsmain/cattest/
Django Version: 1.3.1
Exception Type: AttributeError
Exception Value:
'function' object has no attribute 'save'
Exception Location: /home/bill/workspace/boatsite/../boatsite/bsmain/views.py in cattest, line 50
Python Executable: /usr/bin/python
Python Version: 2.6.5

You have a type-o in your view.
you are calling save() on the function you are in cattest.save()
I think this should be on the form?? You might want to look at ModelForm it provides a form that maps directly to your model, which it looks like you are doing.
https://docs.djangoproject.com/en/dev/topics/forms/modelforms/#django.forms.ModelForm
The form you are using is just a normal form and doesn't have a save method. After subclassing ModelForm you can then call save on a form instance.
if your_form.is_valid():
your_form.save()

You are calling save method on function itself. That is the reason behind the error. if you are looking for form to save then:
if form.is_valid():
form.save()

class CattestForm(forms.Form): should be class CattestForm(forms.ModelForm):

Related

How to create an instance object of a Model in Django that was created by a ManyToManyField

I'm facing difficulties in creating an instance of a model created by a ManyToManyField.
This is what I have in models.py:
class Attendee(models.Model):
student = models.ForeignKey(User, related_name="attendee")
class Activity(models.Model):
attendee = models.ManyToManyField(Attendee, related_name="attendees",null=True, blank=True)
I've tried this function in views.py but it doesnt work:
def registerAttende(request,pk):
act = Activity.objects.get(pk=pk)
act.save()
act.attendee.add(student=request.user.pk) # This is the line causing the error
return render(request, 'dashboard.html')
I get the following error:
"TypeError at /5
add() got an unexpected keyword argument 'student' "
for manyto many try it:
def registerAttende(request,pk):
act = Activity.objects.get(pk=pk)
act.save()
# Get Attendee or create it, in the '_' boolvalue created, don need now
attendee, _ = Attendee.objects.get_or_create(student=request.user)
act.attendee.add(attendee)
return render(request, 'dashboard.html')
for more details read the get-or-create and many2many
you are passing activity.id in get but trying to retrieve by request.post
use<input type='hidden' name='id' value='{{activity.id}}' /> in form

How to Append to Array Field in Python Django

I am making an E commerce site, I want to store Cart elements in an integer Array Field. I am using PostGreSql as my database.
I have created model for cart by extending Django User model. Here is my models
class UserCart(models.Model):
user=models.OneToOneField(User,on_delete=models.CASCADE)
user_product=models.IntegerField(blank=True, null=True)
cart_products = ArrayField(
models.IntegerField(blank=True),
default = list
)
User.profile = property(lambda u:UserCart.objects.get_or_create(user=u)[0])
Below is my Form.py. I have created only basic form
from django import forms
from .models import UserCart
from django.db import models
from django.contrib.postgres.fields import ArrayField
class UserCartForm (forms.ModelForm):
class Meta:
model= UserCart
fields = ('user_product',)
I have searched alot on internet but was unable to find the relevant answer.I want that whenever user clicks on Add to Cart button, that product_id gets stored in cart_products array.I read somewhere that ArrayFields behave as list in Django, so here is my views.py
#login_required
def user_cart(request):
if request.method=='POST':
form=UserCartForm(request.POST , instance=request.user.profile)
if form.is_valid():
post = form.save(commit=False)
post.cart_products.append(99)
post.save()
return HttpResponseRedirect('/user_login/loggedin')
else:
HttpResponse("Error")
else:
user=request.user
profile=user.profile
form= UserCartForm(instance=profile)
args={}
args.update(csrf(request))
args['form']=form
return render_to_response('cartapi.html' ,args)
Its giving me Error that
AttributeError at /cart/ac/
'NoneType' object has no attribute 'append'
Request Method: POST
Request URL: http://localhost:8000/cart/ac/
Django Version: 1.11.2
Exception Type: AttributeError
Exception Value:
'NoneType' object has no attribute 'append'
Exception Location: C:\Users\Muhammad
Jawad\AppData\Local\Programs\Python\Python36-32\mysite\cart\views.py in
user_cart, line 19
Python Executable: C:\Users\Muhammad
Jawad\AppData\Local\Programs\Python\Python36-32\python.exe
And if i save cart_products this way
post.cart_products=99
Then it throws this error
column "cart_products" is of type int4range but expression is of type integer
LINE 1: ...er_id" = 1, "user_cart" = 3000, "cart_products" = 99 WHERE "...
^
HINT: You will need to rewrite or cast the expression.
Request Method: POST
Request URL: http://localhost:8000/cart/ac/
Django Version: 1.11.2
Exception Type: ProgrammingError
Exception Value:
column "cart_products" is of type int4range but expression is of type integer
LINE 1: ...er_id" = 1, "user_cart" = 3000, "cart_products" = 99 WHERE "...
^
HINT: You will need to rewrite or cast the expression.
Kindly Help me in this matter.Summarizing my Question:
How can i get user_product as id and save it in cart_products
change yor views like this
views.py
#login_required
def user_cart(request):
if request.method=='POST':
form=UserCartForm(request.POST , instance=request.user.profile)
if form.is_valid():
post = form.save(commit=False)
if post.cart_products:
post.cart_products.append(99)
else:
post.cart_products = [99]
post.save()
return HttpResponseRedirect('/user_login/loggedin')
else:
HttpResponse("Error")
else:
user=request.user
profile=user.profile
form= UserCartForm(instance=profile)
args={}
args.update(csrf(request))
args['form']=form
return render_to_response('cartapi.html' ,args)
Your database is messed up. Drop it and remigrate (or craft a custom migration if you have data to preserve: basically, you just have to expand existing ranges into the full array).
See https://docs.djangoproject.com/en/2.1/_modules/django/contrib/postgres/fields/ranges/#IntegerRangeField
The int4range is the db type associated with the IntegerRangeField. This indicates either problem with your migrations (try running ./manage.py makemigrations) or that your database is out-of-sync with your DB (try running ./manage.py migrate).
It's hard to say what exactly the problem is without looking at your migrations and the current table definition in the database, but this should get you started.
keyword_from_user="My name is John Doe"
I have Django 3.1.7 and this method has worked for me.
models.py
class Keys(models.Model):
keys = ArrayField(models.CharField(max_length=50, blank=True),size=5,blank=True)
docfile = models.FileField(upload_to='documents/%Y/%m/%d', blank=True, null=True)
views.py create object
new_document_object = Keys.objects.create(keys= keyword_from_user.split(), docfile =file)
views.py create object
new_document_object = Keys.objects.create(keys= keyword_from_user.split(), docfile =file)
views.py update object
keys = Keys.objects.get(id=id_from_user)
keys.keys=user_data['keyword_update_list']
keys.save()
You can save your cart_products into a python list then modify that list using the append method. Thereafter, you can save the new value of the list into the ArrayField
#login_required
def user_cart(request):
if request.method=='POST':
form=UserCartForm(request.POST , instance=request.user.profile)
if form.is_valid():
post = form.save(commit=False)
# copy the existing cart_products to a temp variable
temp_cart = post.cart_products
# append your new product code to the temp_cart
temp_cart.append(99)
# save the new value of temp_cart to the cart_products field
post.cart_products = temp_cart
# save the post
post.save()
return HttpResponseRedirect('/user_login/loggedin')
else:
HttpResponse("Error")
else:
user=request.user
profile=user.profile
form= UserCartForm(instance=profile)
args={}
args.update(csrf(request))
args['form']=form
return render_to_response('cartapi.html' ,args)

Get saved object of a model form in Django?

I just want to access model details just after posting it with model form in Django. This guy also had asked the same thing but when i try the
accepted answer, it returns none type value.
Here is my code in 'views.py':
if request.method == 'POST':
if request.user.is_authenticated():
form = PostStoryForm(request.POST)
if form.is_valid():
obj = form.save(commit=False)
obj.author = request.user
new_post = obj.save()
print(new_post)
The Code above saves the form to the database successfully but 'new_post' variable is 'None'. For example when i tried to access 'new_post.title' which is a field in my model, it returns 'AttributeError' which says 'NoneType' object has no attribute 'title'
what am i doing wrong?
The models save() method does not return the instance
obj.author = request.user
obj.save() # this does not return anything. It just saves the instance it is called on.
Your instance already has the author set.
To access auto populated fields that haven't been set yet, you will have to fetch it from the database again after saving. This is the case, when the instance you called save() on did not already exist before.
new_obj = MyModel.objects.get(id=obj.id)

RemovedInDjango18Warning: Creating a ModelForm without either the 'fields' attribute or the 'exclude' attribute is deprecated

I am doing a Django project and when I tried to access 127.0.0.1:8000/articles/create, I got the following error in my Ubuntu terminal:
/home/(my name)/django_test/article/forms.py:4: RemovedInDjango18Warning: Creating a ModelForm without either the 'fields' attribute or the 'exclude' attribute is deprecated - form ArticleForm needs updating
class ArticleForm(forms.ModelForm):
In addition, I also got the following error when visiting my actual localhost site:
ValueError at /articles/create/
The view article.views.create didn't return an HttpResponse object. It returned None instead.
Here is my forms.py file:
from django import forms
from models import Article
class ArticleForm(forms.ModelForm):
class Meta:
model = Article
And here is my views.py file:
from django.shortcuts import render_to_response
from article.models import Article
from django.http import HttpResponse
from forms import ArticleForm
from django.http import HttpResponseRedirect
from django.core.context_processors import csrf
#import pdb; pdb.set_trace()
# Create your views here.
def articles(request):
language = 'en-us'
session_language = 'en-us'
if 'lang' in request.COOKIES:
language = request.COOKIES['lang']
if 'lang' in request.session:
session_language = request.session['lang']
return render_to_response('articles.html',
{'articles':
Article.objects.all(), 'language' : language,
'session_language' : session_language})
def article(request, article_id=1):
return render_to_response('article.html', {'article':
Article.objects.get(id=article_id) })
def language(request, language='en-us'):
response = HttpResponse("setting language to %s" %
language)
response.set_cookie('lang', language)
response.session['lang'] = language
return response
def create(request):
if request.POST:
form = ArticleForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('/articles/all')
else:
form = ArticleForm()
args = {}
args.update(csrf(request))
args['form'] = form
return render_to_response('create_article.html', args)
I'm not sure how to fix this problem. I looked at the Django documentation but I couldn't find a solution to my problem so any help would be appreciated.
For your form, it's a warning, not an error, telling you that in django 1.8, you will need to change your form to
from django import forms
from models import Article
class ArticleForm(forms.ModelForm):
class Meta:
model = Article
fields = '__all__' # Or a list of the fields that you want to include in your form
Or add an exclude to list fields to exclude instead
Which wasn't required up till 1.8
https://docs.djangoproject.com/en/1.8/topics/forms/modelforms/#selecting-the-fields-to-use
As for the error with your views, your return is inside of an if statement: if request.POST: so when it receives a get request, nothing is returned.
def create(request):
if request.POST:
form = ArticleForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('/articles/all')
else:
form = ArticleForm()
args = {}
args.update(csrf(request))
args['form'] = form
return render_to_response('create_article.html', args)
Just dedent the else block so that it's applying to the correct if statement.
You just need...
from django import forms
from models import Article
class ArticleForm(forms.ModelForm):
class Meta:
model = Article
exclude = ()
...to fix your form. You'll need to post your view code to see what's up with that.
if you use fields = __all__ as Ngenator suggested, and if it's a project that might have to run under various versions of Django, the following conditional will be needed:
if django.VERSION >= (1, 6):
fields = '__all__' # eliminate RemovedInDjango18Warning
otherwise you get the error django.core.exceptions.FieldError: Unknown field(s) (a, l, _) specified for CrispyTestModel, as seen here: https://travis-ci.org/maraujop/django-crispy-forms/jobs/56996180
In your view, you don't return anything if the request is not a POST. You should move everything from the else statement onwards back one indent.

MutipleCheckBox saving to Database with Django

I'm trying to find some kind of canonical reference for this problem where I use the follow type model:
class MyPreferencesForm(forms.Form):
MyGenderPref = forms.MultipleChoiceField(choices=GENDER_CHOICES, widget=forms.CheckboxSelectMultiple())
and the view
def GoPreferences(request):
if request.method == "POST":
f = MyPreferencesForm(request.POST)
if f.is_valid():
model_instance = f.save(commit=False)
model_instance.save()
f.save_m2m()
return redirect('/')
else:
f = MyPreferencesForm()
return render(request, "mypreferences.html", {'form': f})
However I tried to follow what I thought was sensible and include the many to many. But I still cannot make this work. My error is the following:
Exception Type: AttributeError
Exception Value:
'MyPreferencesForm' object has no attribute 'save'
The error emanates from line containing model_instance = f.save(commit=False)
save is available only for forms inherited from ModelForm objects. Here, you are inheriting form forms.Form Hence the error.
Either inherit the form from forms.ModelForm and specify a Meta attribute
class MyPreferencesForm(forms.ModelForm):
MyGenderPref = forms.MultipleChoiceField(choices=GENDER_CHOICES, widget=forms.CheckboxSelectMultiple())
class Meta:
model = MyModel
You can read more on ModelForms here - You might have to modify your form slightly based on your specific requirements.
OR
model_instance = MyModel.objects.create(**form.cleaned_data) #manage manually
If your m2m tables in your models.py uses through then you'll need to manage the saving manually using object.create and you can't use save_m2m() or save()

Categories