I am getting the error:
AttributeError: 'User' object has no attribute 'zipcode'
I get this error when the user fills out a form to sell an item.
Here are my views:
def get_entry(request):
if request.method == 'POST':
f = SellForm(request.POST)
if f.is_valid():
form=f.save(commit=False)
form.author = request.user
form.zipcode = request.user.zipcode
form.pubdate = datetime.datetime.now
form.save()
else:
f = SellForm()
return render(request, 'sell.html', {'form': f})
Here are my models:
from django.db import models
from django.contrib.auth.models import User
from django.utils.translation import ugettext as _
from userena.models import UserenaBaseProfile
from django.conf import settings
class MyProfile(UserenaBaseProfile):
user = models.OneToOneField(User,
unique=True,
verbose_name=_('user'),
related_name='my_profile')
city = models.TextField(null=True, blank=True)
state = models.TextField(null=True, blank=True)
zipcode = models.IntegerField(_('zipcode'),
max_length=5, null=True, blank=True)
coverpic = models.ImageField(upload_to="/site_media/media/covers/", null=True, blank=True)
class Entry(models.Model):
headline= models.CharField(max_length=200,)
body_text = models.TextField()
author=models.ForeignKey(settings.AUTH_USER_MODEL, related_name='entryauthors')
pub_date=models.IntegerField(max_length=8)
zipcode =models.ForeignKey(settings.AUTH_USER_MODEL, related_name='entryzipcodes')
price1 = models.TextField()
price2 = models.TextField()
item_picture = models.ImageField(upload_to="/site_media/media/items/", null=True, blank=True)
Here is my form:
class SellForm(ModelForm):
class Meta:
model = Entry
fields = ['headline', 'body_text', 'author', 'pub_date', 'zipcode', 'price1', 'price2', 'item_picture']
Am I doing anything wrong with the models?
As you are aware, and even reiterate in your comment, zipcode is an attribute of MyProfile, not of User. So why are you trying to access it on the user? You need to follow the relationship to the profile:
form.zipcode = request.user.my_profile.zipcode
(Note that "form" is a very bad name for the variable there: what you have is an instance of Entry, so perhaps you should name it accordingly.)
Related
I have a model form to list an item and I am trying to get the form to fill in the user id from the user that is submitting the form. Currently, the form is submitted successfully but it always uses the first user in the database's id for every item.
models.py
class Item(models.Model):
id = models.UUIDField( primary_key=True, default=uuid.uuid4, editable=False )
creator = models.ForeignKey( get_user_model(), on_delete=models.CASCADE, default=2)
item_name = models.CharField(max_length=40)
price = models.DecimalField(max_digits = 6, decimal_places=2)
description = models.CharField(max_length= 500)
main_image = models.ImageField(upload_to=path_and_rename , max_length=255, null=True, blank=True)
image_2 = models.ImageField(upload_to='items/', blank=True)
image_3= models.ImageField(upload_to='items/', blank=True)
image_4= models.ImageField(upload_to='items/', blank=True)
image_5= models.ImageField(upload_to='items/', blank=True)
quantity = models.IntegerField(default=1, validators=[ MaxValueValidator(100),MinValueValidator(1)])
created_on = models.DateTimeField(auto_now_add=True)
updated_on = models.DateTimeField(auto_now=True)
def __str__(self):
return self.item_name
def get_absolute_url(self):
return reverse("item_detail_view", args=[str(self.id)])
forms.py
from django.forms import ModelForm, forms
from .models import Item
class List_Item_Form(ModelForm):
forms.ModelChoiceField(queryset=Item.objects.filter(user=user))
class Meta:
model = Item
def __init__(self, *args, **kwargs):
user = kwargs.pop("user", None)
super().__init__(*args, **kwargs)
views.py
class AddListing( generic.CreateView):
template_name = 'store/add_listing.html'
fields = ('item_name','price','description','main_image','quantity')
model = Item
def form_valid(self, form):
self.object = form.save(commit=False)
self.object.user = self.request.user
self.object.save()
return super().form_valid(form)
It can be done using function based view too because there we get current user more easily.
Try this:
models.py
from django.db import models
from django.contrib.auth.models import User
class Item(models.Model):
creator = models.ForeignKey(User, on_delete=models.CASCADE)
item_name = models.CharField(max_length=40)
price = models.DecimalField(max_digits=6, decimal_places=2)
description = models.CharField(max_length=500)
main_image = models.ImageField(
upload_to=path_and_rename, max_length=255, null=True, blank=True)
image_2 = models.ImageField(upload_to='items/', blank=True)
image_3 = models.ImageField(upload_to='items/', blank=True)
image_4 = models.ImageField(upload_to='items/', blank=True)
image_5 = models.ImageField(upload_to='items/', blank=True)
quantity = models.PositiveIntegerField(default=1)
created_on = models.DateTimeField(auto_now_add=True)
updated_on = models.DateTimeField(auto_now=True)
def __str__(self):
return self.item_name
admin.py
from django.contrib import admin
from home.models import Item
#admin.register(Item)
class ItemRegister(admin.ModelAdmin):
lis_display = ['id', 'creator', 'item_name', 'price', 'description']
urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.list, name='home'),
path('success/', views.success, name='success')
]
forms.py
from django.forms import ModelForm, forms
from .models import Item
class ListItemForm(ModelForm):
class Meta:
model = Item
fields = ['item_name', 'price', 'main_image'
'description', 'quantity']
views.py
from django.http import HttpResponseRedirect
from django.shortcuts import render
from .models import Item
from .forms import ListItemForm
def list(request):
if request.method == 'POST':
form = ListItemForm(request.POST)
if form.is_valid():
itemName = form.cleaned_data['item_name']
price = form.cleaned_data['price']
desc = form.cleaned_data['description']
quan = form.cleaned_data['quantity']
main_img = form.cleaned_data['main_image']
current_user = request.user
model_instance = Item(creator=current_user, item_name=itemName, price=price,
description=desc, quantity=quan, main_image=main_img)
model_instance.save()
return HttpResponseRedirect('/success/')
else:
form = ListItemForm()
return render(request, 'store/add_listing.html', {'form': form})
def success(request):
return render(request, 'store/success.html')
Rest of the fields of models you can customize very easily in the view.
When i try to create a new by post by posting the following Json:
{
"title": "This is serialzer title",
"content": "This is serialzer content",
}
I get the following error:
NOT NULL constraint failed: blog_post.views
Models.py
from django.db import models
from django.contrib.auth.models import User
from django.utils.timezone import now
# Create your models here.
class Post(models.Model):
sno = models.AutoField(primary_key=True)
title = models.CharField(max_length=255)
content = models.TextField()
author = models.ForeignKey(User, on_delete=models.CASCADE, blank=True, null=True)
views = models.IntegerField()
slug = models.CharField(max_length=100)
timeStamp = models.DateTimeField(default=now)
def __str__(self):
# return self.title + ' by ' + self.author
return self.title + ' by ' + self.author.username
class BlogComment(models.Model):
sno = models.AutoField(primary_key=True)
comment = models.TextField()
user = models.ForeignKey(User, on_delete=models.CASCADE)
post = models.ForeignKey(Post, on_delete=models.CASCADE)
parent = models.ForeignKey('self', on_delete=models.CASCADE, null=True)
timeStamp = models.DateTimeField(default=now)
def __str__(self):
return self.comment[0:13] + "..." + " by " + self.user.username
views.py
#api_view(['POST'])
def api_create_blog_view(request):
user = User.objects.get(pk=1)
blog_post = Post(author=user)
if request.method == "POST":
serializer = PostSerializer(blog_post, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
serializer.py
from blog.models import Post
from rest_framework import serializers
class PostSerializer(serializers.ModelSerializer):
class Meta:
model = Post
fields = ['title', 'content']
I don't know how to solve this please help me to solve this error.DB has already been cleared. Locations have been created by using the admin interface. I know that the issue is something trivial, but I just can't get it to work.
You need to set a value for the views. You can do so by specifying a default value:
from django.conf import settings
class Post(models.Model):
sno = models.AutoField(primary_key=True)
title = models.CharField(max_length=255)
content = models.TextField()
author = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
blank=True,
null=True
)
views = models.IntegerField(default=0)
slug = models.CharField(max_length=100)
timeStamp = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.title + ' by ' + self.author.username
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: According to the PEP-8 Style Guide, the classes should be written in PerlCase, and the fields in snake_case.
I am trying to save the owner_id that is the same as the Logged In user/Authenticated user. But after I save the AddressBook form,the database saves the owner id with 'Null' value. Can someone help me knowing where am I going wrong.
models.py
class UserProfile(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="profile")
mobiles = models.ManyToManyField(Product, blank=True)
class AddressBook(models.Model):
name = models.CharField(max_length=50)
owner = models.ForeignKey(UserProfile, on_delete=models.SET_NULL, null=True)
phone_regex = RegexValidator(regex=r'^\+?1?\d{9,15}$', message="Phone number must be entered in the format: '+999999999'. Up to 15 digits allowed.")
phone_number = models.CharField(validators=[phone_regex], max_length=17) # validators should be a list
line1 = models.CharField(max_length=100)
line2 = models.CharField(max_length=100, blank=True)
city = models.CharField(max_length=25)
state = models.CharField(max_length=25)
postcode = models.CharField(max_length=8)
country = models.CharField(max_length=25)
views.py
#login_required
def address(request):
existing_order = get_user_pending_order(request)
form = AddressBookForm()
context = {
'addressbook': AddressBook.objects.all(),
'form' : form,
'order' : existing_order,
}
return render(request, 'cart/user_address.html', context)
#login_required
def process_payment(request, order_id):
if request.method == 'POST':
form = AddressBookForm(request.POST)
if form.is_valid():
form.save()
return redirect (reverse('update-records', kwargs={'order_id': order_id}))
forms.py
from django import forms
from .models import AddressBook
class AddressBookForm(forms.ModelForm):
ADDRESS_TYPE = (
('Home', 'Home'),
('Work', 'Work'),
)
address_type = forms.ChoiceField(choices=ADDRESS_TYPE, widget=forms.RadioSelect)
class Meta:
model = AddressBook
fields = ['name', 'phone_number', 'line1', 'line2', 'city', 'state', 'postcode', 'country','address_type']
Database
You can save the form with commit=False, set the owner, and then save to the database:
if request.method == 'POST':
form = AddressBookForm(request.POST)
if form.is_valid():
address = form.save(commit=False)
address.owner = request.user.profile
address.save()
I am working on a project that requires use of form wizard to populate three related models. The first model - Listing - has general data which has a OneToOneField relationship with the second model (Property). The Listing model also has a many to many relationships with the third model (ListingImages). In general, I am using 4 forms in the wizard. Here is the models definition
models.py
class Listing(models.Model):
listing_type_choices = [('P', 'Property'), ('V', 'Vehicle'), ('B', 'Business/Service'), ('E', 'Events')]
listing_title = models.CharField(max_length=255)
listing_type = models.CharField(choices=listing_type_choices, max_length=1, default='P')
status = models.BooleanField(default=False)
featured = models.BooleanField(default=False)
city = models.CharField(max_length=255, blank=True)
location = PlainLocationField(based_fields=['city'], zoom=7, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
expires_on = models.DateTimeField(auto_now=True)
created_by = models.ForeignKey(User,
on_delete=models.CASCADE, editable=False, null=True, blank=True
)
listing_owner = models.ForeignKey(User,
on_delete=models.CASCADE, related_name='list_owner'
)
def __str__(self):
return self.listing_title
def get_image_filename(instance, filename):
title = instance.listing.listing_title
slug = slugify(title)
return "listings_pics/%s-%s" % (slug, filename)
class ListingImages(models.Model):
listing = models.ForeignKey(Listing, on_delete=models.CASCADE)
image_url = models.ImageField(upload_to=get_image_filename,
verbose_name='Listing Images')
main_image = models.BooleanField(default=False)
class Meta:
verbose_name_plural = "Listing Images"
def __str__(self):
return f'{self.listing.listing_title} Image'
class Property(models.Model):
sale_hire_choices = [('S', 'Sale'), ('R', 'Rent')]
fully_furnished_choices = [('Y', 'Yes'), ('N', 'No')]
listing = models.OneToOneField(Listing, on_delete=models.CASCADE)
sub_category = models.ForeignKey(PropertySubCategory, on_delete=models.CASCADE)
for_sale_rent = models.CharField(choices=sale_hire_choices, max_length=1, default=None)
bedrooms = models.PositiveIntegerField(default=0)
bathrooms = models.PositiveIntegerField(default=0)
rooms = models.PositiveIntegerField(default=0)
land_size = models.DecimalField(max_digits=10, decimal_places=2)
available_from = models.DateField()
car_spaces = models.PositiveIntegerField(default=0)
fully_furnished = models.CharField(choices=fully_furnished_choices, max_length=1, default=None)
desc = models.TextField()
property_features = models.ManyToManyField(PropertyFeatures)
price = models.DecimalField(max_digits=15, decimal_places=2)
currency = models.ForeignKey(Currency, on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
Here is the forms.py
from django import forms
from .models import Listing, Property, Vehicle, Business, ListingImages
from django.forms import modelformset_factory
class ListingDetails(forms.ModelForm):
class Meta:
model = Listing
fields = ['listing_title', 'city', 'location']
class PropertyDetails1(forms.ModelForm):
class Meta:
model = Property
fields = ['sub_category', 'for_sale_rent', 'bedrooms', 'bathrooms',
'rooms', 'land_size', 'available_from', 'car_spaces', 'fully_furnished',
'desc', 'currency', 'price'
]
class PropertyDetails2(forms.ModelForm):
class Meta:
model = Property
fields = ['property_features']
class ListingImagesForm(forms.ModelForm):
image_url = forms.ImageField(label='Listing Image',
widget=forms.ClearableFileInput(attrs={'multiple': True}),
required=False
)
class Meta:
model = ListingImages
fields = ['image_url']
ImageFormSet = modelformset_factory(ListingImages, form=ListingImagesForm, extra=3)
views.py
from django.shortcuts import render, redirect
import os
from .forms import ListingDetails, PropertyDetails1, PropertyDetails2, ListingImagesForm
from .models import ListingImages, Listing, Property
from formtools.wizard.views import SessionWizardView
from django.conf import settings
from django.core.files.storage import FileSystemStorage
from django.forms import modelformset_factory
from django.contrib import messages
from django.http import HttpResponseRedirect, HttpResponse
from django.forms.models import construct_instance
class PropertyView(SessionWizardView):
# formset = ImageFormSet(queryset=Images.objects.none())
template_name = "listings/create_property.html"
form_list = [ListingDetails, PropertyDetails1, PropertyDetails2, ListingImagesForm]
file_storage = FileSystemStorage(location=os.path.join(settings.MEDIA_ROOT, 'media'))
def done(self, form_list, **kwargs):
listing_instance = Listing()
property_instance = Property()
listing_instance.created_by = self.request.user
listing_instance.listing_owner = self.request.user
listing_instance.listing_type = 'P'
for form in form_list:
listing_instance = construct_instance(form, listing_instance, form._meta.fields, form._meta.exclude)
property_instance = construct_instance(form, property_instance, form._meta.fields, form._meta.exclude)
listing = listing_instance.save()
property_instance.listing = listing
property_instance.save()
return HttpResponse('data saved successfully')
The problem that I am facing is that I am able to save the Listing model, but getting its primary id and using it to save the Property model is the problem. Again, the ListingImages model stores images related to the Listing model. How do I save these models to database considering that they are multiple?
What's wrong is that as described here, model.save() does not return the saved object, but None.
So the last few lines of the above code should be
listing_instance.save()
property_instance.listing = listing_instance
property_instance.save()
return HttpResponse('data saved successfully')
Ditto saving a set of listing_images would be something like
for li_obj in listing_image_instances:
li_obj.listing = listing_instance # saved above
li_obj.save()
I have an update form, whem i press updated for the form to update the user profile it I get the error "'UserProfile' object has no attribute 'id'"
my models is:
from django.db import models
from django.db.models.signals import post_save
from django.dispatch import receiver
class UserProfile(models.Model):
user = models.OneToOneField(User, related_name="custom_user_profile", primary_key=True)
organization = models.CharField(max_length=100, default='', blank=True)
address_line_1 = models.CharField(max_length=100, default='', blank=True)
address_line_2 = models.CharField(max_length=100, default='', blank=True)
city = models.CharField(max_length=100, default='', blank=True)
state = models.CharField(max_length=100, default='', blank=True)
post_code = models.CharField(max_length=100, default='', blank=True)
country = models.CharField(max_length=100, default='', blank=True)
def __unicode__(self):
return self.user.username
#receiver(post_save, sender=User)
def create_profile(sender, instance, created, **kwargs):
if created:
profile, new = UserProfile.objects.get_or_create(user=instance)
and my views is:
from django.shortcuts import render_to_response
from django.shortcuts import HttpResponseRedirect
from django.template import RequestContext
from django.core.context_processors import csrf
from django.contrib.auth.decorators import login_required
from user_profile.models import UserProfile
from django.contrib.auth.models import User
from forms import UserProfileForm
from django.shortcuts import redirect
#login_required
def update_profile(request):
userProfile = UserProfile.objects.get(user=request.user)
form = UserProfileForm(initial={
'organization':userProfile.organization,
'address_line_1':userProfile.address_line_1,
'address_line_2':userProfile.address_line_2,
'city':userProfile.city,
'state':userProfile.state,
'post_code':userProfile.post_code,
'country':userProfile.country,
})
return render_to_response('user_profile/update_profile.html', {'form':form}, RequestContext(request))
#login_required
def profile(request, profile_id):
if profile_id == "0":
if request.user.is_authenticated:
userProfile = UserProfile.objects.get(user=request.user)
else:
userProfile = UserProfile.objects.get(pk=profile_id)
return render_to_response('user_profile/profile.html', {'userProfile':userProfile}, RequestContext(request))
#login_required
def send_update_profile(request):
if request.method == 'POST':
form = UserProfileForm(request.POST)
if form.is_valid():
userProfile = UserProfile.objects.get(user=request.user)
organization = form.cleaned_data['organization']
userProfile.organization = organization
address_line_1 = form.cleaned_data['address_line_1']
userProfile.address_line_1 = address_line_1
address_line_2 = form.cleaned_data['address_line_2']
userProfile.address_line_2 = address_line_2
city = form.cleaned_data['city']
userProfile.city = city
state = form.cleaned_data['state']
userProfile.state = state
post_code = form.cleaned_data['post_code']
userProfile.post_code = post_code
country = form.cleaned_data['country']
userProfile.country = country
userProfile.save()
return redirect('/user/profile/' + str(userProfile.id))
else:
form = UserProfileForm()
return redirect('/user/send_update_profile/')
I can not work out why. One thing is that in admin.py, if i try to add 'id' as list display. An error occurs saying that there is no id in the user profile I am creating. Though, i thought an id field is automatically created when a model is created.
Any suggestions?
Django gives each model an automatic primary key field named id, unless you specify a primary key yourself. In your case, your model does not have an id field, because you have made user the primary key.
class UserProfile(models.Model):
user = models.OneToOneField(User, related_name="custom_user_profile", primary_key=True)
You could change the code to use the userProfile.user_id. Another option is to use the pk shortcut to access the primary key.
return redirect('/user/profile/' + str(userProfile.pk))