Django Sitemap -- 'str' object has no attribute 'get_absolute_url' Error - python

I'm getting the 'str' object has no attribute 'get_absolute_url' error on my django project on my sitemap page. Any help is appreciated.
Here is my traceback:
Traceback:
File "C:\Users\crstu\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\core\handlers\exception.py" in inner
35. response = get_response(request)
File "C:\Users\crstu\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\core\handlers\base.py" in _get_response
128. response = self.process_exception_by_middleware(e, request)
File "C:\Users\crstu\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\core\handlers\base.py" in _get_response
126. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\Users\crstu\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\contrib\sitemaps\views.py" in inner
16. response = func(request, *args, **kwargs)
File "C:\Users\crstu\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\contrib\sitemaps\views.py" in sitemap
71. protocol=req_protocol))
File "C:\Users\crstu\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\contrib\sitemaps\__init__.py" in get_urls
111. urls = self._urls(page, protocol, domain)
File "C:\Users\crstu\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\contrib\sitemaps\__init__.py" in _urls
120. loc = "%s://%s%s" % (protocol, domain, self.__get('location', item))
File "C:\Users\crstu\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\contrib\sitemaps\__init__.py" in __get
68. return attr(obj)
File "C:\Users\crstu\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\contrib\sitemaps\__init__.py" in location
75. return obj.get_absolute_url()
Exception Type: AttributeError at /sitemap.xml
Exception Value: 'str' object has no attribute 'get_absolute_url'
my sitemaps.py file
from django.contrib import sitemaps
from django.contrib.sitemaps import Sitemap
from django.urls import reverse
from deals.models import Deal
from blog.models import Post
class StaticViewSitemap(sitemaps.Sitemap):
priority = 1.0
changefreq = 'daily'
def items(self):
return ['about', 'contact', 'disclosure', 'terms', 'privacy', 'deals:deals', 'blog:blog']
class BlogSitemap(Sitemap):
changfreq = "daily"
priority = 1.0
location ='/blog'
def items(self):
return Post.objects.filter(status='Published')
def lastmod(self, obj):
return obj.created
class DealSitemap(Sitemap):
changfreq = "daily"
priority = 1.0
def items(self):
return Deal.objects.all()
def lastmod(self, obj):
return obj.date_added
and my two relevant models (Deal and Post) where i created a get_absolute_url methods since it had been generating an error on the sitemap prior:
class Deal(models.Model):
title = models.CharField(max_length=200)
slug = models.SlugField(max_length=140, unique=True)
description = RichTextUploadingField(default='')
retailer = models.ForeignKey(Retailer, on_delete=models.CASCADE)
image = VersatileImageField('deal image',
upload_to=deal_upload_path,
null=True,
blank=True)
link = models.URLField(max_length=2000, default='')
category = models.ForeignKey(Category, on_delete=models.CASCADE)
date_added = models.DateField(default=timezone.now)
date_expires = models.DateField(default=timezone.now)
price = models.CharField(max_length=140)
secondary_price = models.CharField(max_length=140, default='')
likes_total = models.IntegerField(default=1)
expired = models.BooleanField(default=False)
def __str__(self):
return "#{} ({})".format(self.title, self.retailer)
def _get_unique_slug(self):
slug = slugify(self.title)
unique_slug = slug
num = 1
while Deal.objects.filter(slug=unique_slug).exists():
unique_slug = '{}-{}'.format(slug, num)
num += 1
return unique_slug
def save(self, *args, **kwargs):
if not self.slug:
self.slug = self._get_unique_slug()
super().save()
def get_label(self):
if self.date_added > datetime.date.today() - datetime.timedelta(days=4):
return "<span class='"'notify-badge'"'>new</span>"
else:
return ''
def get_absolute_url(self):
return reverse('deals:deal_detail', kwargs={'slug': self.slug})
class Post(models.Model):
STATUS_CHOICES = (
('Published', 'Published'),
('Draft', 'Draft'),
)
title = models.CharField(max_length=100, unique=True)
body = RichTextUploadingField()
category = models.ForeignKey(BlogCategory, on_delete=models.CASCADE)
seo_title = models.CharField(max_length=60, blank=True, null=True)
seo_description = models.CharField(max_length=165, blank=True, null=True)
slug = models.SlugField(max_length=200, unique=True)
image = VersatileImageField('blog image',
upload_to='media/blog_images',
null=True,
blank=True)
created = models.DateTimeField(db_index=True, auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
status = models.CharField(max_length=10, default='Draft', choices=STATUS_CHOICES)
def get_absolute_url(self):
return reverse('blog:blog_post', kwargs={'slug': self.slug})
def save(self, *args, **kwargs):
self.slug = slugify(self.title)
super(Post, self).save(*args, **kwargs)
def __str__(self):
return self.title
and my urls.py file with relevant info
from django.contrib.sitemaps.views import sitemap
sitemaps = {
'static': StaticViewSitemap,
'blog': BlogSitemap,
'deals': DealSitemap
}
path('sitemap.xml', sitemap,
{'sitemaps': sitemaps},
name='django.contrib.sitemaps.views.sitemap'),

You haven't followed the example properly for the StaticViewSitemap. As the docs say, the elements returned from items() are passed to the location() method; since the items would normally be model instances, the default implementation of this method is to call the get_absolute_url() method of each instance. In your case you are passing URL names, so you need to redefine location() appropriately - again as the example does.
def location(self, item):
return reverse(item)

It's the location() function who request for get_absolute_url() method : here. If you are absolutly sur that your string is already an absolute path you can simply override it in your class by:
def location(self, item) :
return item
This will return your already setup absolut path.

Related

Setup UpdateView in Django with a form that has the __init__ method configured

When I use UpdateView in Django with a form that has the __init__ method configured to customize the ModelMultipleChoiceField querysets do not load the initial values of the instance?
Some context first, I find myself making an application that manages documents associated to subportals, for that each subportal has associated Service Groups and Dependencies.
I need that when a document is loaded, it can be categorized by Service Groups and Dependencies that are only associated to the subportal. I achieved this by using the __init__ method in the forms.
The problem is that when I need to update the document data, the initial values of the model do not appear.
I show the codes
Models.py
class ServiceGroup(models.Model):
subportal = models.ForeignKey(Subportal, null=True, blank=True, on_delete=models.CASCADE)
title = models.CharField(max_length=150, null=False, blank=False)
description = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.title
class Dependence(models.Model):
subportal = models.ForeignKey(Subportal, null=True, blank=True, on_delete=models.CASCADE)
title = models.CharField(max_length=150, null=False, blank=False)
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.title
class SubportalDocument(models.Model):
def get_upload_to(instance, filename):
return '{}/documents/{}'.format(instance.subportal.title, filename)
subportal = models.ForeignKey(Subportal, null=True, blank=True, on_delete=models.CASCADE)
showcategory = models.OneToOneField(ShowCategory, null=True, blank=True, on_delete=models.CASCADE)
title = models.CharField(max_length=150, null=False, blank=False)
file = models.FileField(upload_to=get_upload_to, null=False, blank=False)
review_date = models.DateField(null=False, blank=True)
review_nro = models.IntegerField(null=False, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
dependences = models.ManyToManyField(Dependence, related_name='dependencesdoc', blank=True)
servicegroups = models.ManyToManyField(ServiceGroup, related_name='servicegroupsdoc', blank=True)
def __str__(self):
return self.title
Forms.py
class SubportalDocumentForm(forms.ModelForm):
class Meta:
model = SubportalDocument
exclude = ['subportal', 'created_at', 'status']
labels = {
'showcategory':'Categoría de Despliegue:',
'title':'Nombre del Documento:',
'file':'Cargar el archivo:',
'review_nro':'Número de Revisión:',
'review_date':'Fecha de Revisión:',
}
widgets = {
'showcategory':forms.Select(attrs={'class':'form-select'}),
'title':forms.TextInput(attrs={'class':'form-control'}),
'file':forms.FileInput(attrs={'class':'form-control'}),
'review_nro': forms.NumberInput(attrs={'class':'form-control'}),
'review_date': forms.DateInput(format=('%d/%m/%Y'),
attrs={'class':'form-control',
'type':'date'}),
}
servicegroups = forms.ModelMultipleChoiceField(
label='Grupos de Servicios:',
queryset=None,
widget=forms.CheckboxSelectMultiple,
)
dependences = forms.ModelMultipleChoiceField(
label='Dependencias:',
queryset=None,
widget=forms.CheckboxSelectMultiple,
)
def __init__(self, *args, **kwargs):
self.subportal = kwargs.pop('subportal')
super(SubportalDocumentForm, self).__init__(*args, **kwargs)
self.fields['servicegroups'].queryset = ServiceGroup.objects.filter(
subportal=self.subportal)
self.fields['dependences'].queryset = Dependence.objects.filter(
subportal=self.subportal)
self.fields['showcategory'].queryset = ShowCategory.objects.filter(
subportal=self.subportal)
self.fields['servicegroups'].widget.attrs.update({
'class': 'form-check-input',
})
self.fields['dependences'].widget.attrs.update({
'class': 'form-check-input',
})
Views.py
class SubportalDocumentUpdateView(UpdateView):
model = SubportalDocument
form_class = SubportalDocumentForm
template_name = 'portal_manager/create_document.html'
def get_form_kwargs(self, *args, **kwargs):
subportal_id = self.get_object().subportal_id
subportal = get_object_or_404(Subportal, id=subportal_id)
kwargs = {
"subportal": subportal,
}
return kwargs
def dispatch(self, request, *args, **kwargs):
id = self.get_object().subportal_id
self.get_form().fields['servicegroups'].queryset = ServiceGroup.objects.filter(subportal_id=id)
self.get_form().fields['dependences'].queryset = Dependence.objects.filter(subportal_id=id)
return super(SubportalDocumentUpdateView, self).dispatch(request, *args, **kwargs)
def get_success_url(self):
id = self.get_object().subportal_id
return reverse_lazy('portal_manager:admin_subportal', kwargs={'id': id})
Urls.py
path('modificar-documento/<int:pk>', views.SubportalDocumentUpdateView.as_view(), name='update_document'),
The result I get is this.
image of the form without the initial values:
Now, if I don't use the __init__ method in the forms to filter the Service Groups and Dependencies by subportal, I get the initial values.
forms.py not init
class SubportalDocumentForm(forms.ModelForm):
class Meta:
model = SubportalDocument
exclude = ['subportal', 'created_at', 'status']
labels = {
'showcategory':'Categoría de Despliegue:',
'title':'Nombre del Documento:',
'file':'Cargar el archivo:',
'review_nro':'Número de Revisión:',
'review_date':'Fecha de Revisión:',
}
widgets = {
'showcategory':forms.Select(attrs={'class':'form-select'}),
'title':forms.TextInput(attrs={'class':'form-control'}),
'file':forms.FileInput(attrs={'class':'form-control'}),
'review_nro': forms.NumberInput(attrs={'class':'form-control'}),
'review_date': forms.DateInput(format=('%d/%m/%Y'),
attrs={'class':'form-control',
'type':'date'}),
}
servicegroups = forms.ModelMultipleChoiceField(
label='Grupos de Servicios:',
queryset=ServiceGroup.objects.all(),
widget=forms.CheckboxSelectMultiple,
)
dependences = forms.ModelMultipleChoiceField(
label='Dependencias:',
queryset=Dependence.objects.all(),
widget=forms.CheckboxSelectMultiple,
)
Ajust Views.py
class SubportalDocumentUpdateView(UpdateView):
model = SubportalDocument
form_class = SubportalDocumentForm
template_name = 'portal_manager/create_document.html'
def dispatch(self, request, *args, **kwargs):
id = self.get_object().subportal_id
self.get_form().fields['servicegroups'].queryset = ServiceGroup.objects.filter(subportal_id=id)
self.get_form().fields['dependences'].queryset = Dependence.objects.filter(subportal_id=id)
return super(SubportalDocumentUpdateView, self).dispatch(request, *args, **kwargs)
def get_success_url(self):
id = self.get_object().subportal_id
return reverse_lazy('portal_manager:admin_subportal', kwargs={'id': id})
Image with the expected result but filtering the Service Groups and Dependencies:
If someone could help me or give me a clue about what is happening, I would appreciate it very much, I have been investigating for a long time and I can't get an answer.

Unit testing in Django for CreateView

I have a CreateView with which I create new blog posts, I want to test it in order to check if everything is ok but something is wrong with my test and I can't understand what exactly. it gives me 2 errors, for the first method I get this error:
Traceback (most recent call last):
File "C:\Users\Bularu Lilian\Desktop\EcoMon\blog\tests\test_views.py", line 73, in test_post_create_view_GET
self.assertEquals(response.status_code, 200)
AssertionError: 302 != 200
and for the second one is this error:
File "C:\Users\Bularu Lilian\Desktop\EcoMon\blog\tests\test_views.py", line 78, in test_post_create_view_POST_success
post = Post.objects.get(title=self.post['title'])
File "C:\Users\Bularu Lilian\Desktop\Environments\ecomon\lib\site-packages\django\db\models\manager.py", line 85, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "C:\Users\Bularu Lilian\Desktop\Environments\ecomon\lib\site-packages\django\db\models\query.py", line 429, in get
raise self.model.DoesNotExist(
blog.models.Post.DoesNotExist: Post matching query does not exist.
This is my Test class:
class TestPostCreateViews(BaseTest):
def test_post_create_view_GET(self):
response = self.client.get(self.add_post_url)
self.assertEquals(response.status_code, 200)
self.assertTemplateUsed(response, 'blog/add_post.html')
def test_post_create_view_POST_success(self):
response = self.client.post(self.add_post_url, self.post, author=self.user, format='text/html')
post = Post.objects.get(title=self.post['title'])
self.assertEquals(response.status_code, 302)
self.assertEquals(post.title, 'test post')
my CreateView:
class PostCreateView(LoginRequiredMixin, IsSuperuserOrStaffMixin, CreateView):
template_name = 'blog/add_post.html'
form_class = PostCreateForm
def form_valid(self, form):
form.instance.author = self.request.user
return super().form_valid(form)
my url path:
path('new/post/', PostCreateView.as_view(), name='add-post'),
my form:
class PostCreateForm(forms.ModelForm):
title = forms.CharField(widget=forms.TextInput(), max_length=200)
content = forms.CharField(widget=forms.Textarea(attrs={'rows': 25, 'cols': 50}))
class Meta:
model = Post
exclude = ['author', 'slug', 'published_date', 'updated_date']
and my model:
class Post(models.Model):
class PostCategory(models.TextChoices):
FAMILY = 'FAMILY', _('Family')
BUSINESS = 'BUSINESS', _('Business')
MWRKETING = 'MARKETING', _('Marketing')
SPENDINGS = 'SPENDINGS', _('Spendings')
author = models.ForeignKey(User, on_delete=models.CASCADE)
title = models.CharField(_('Title'), max_length=200, unique=True)
content = models.TextField(_('Content'))
category = models.CharField(_('Category'), max_length=9, choices=PostCategory.choices, default=PostCategory.BUSINESS)
slug = models.SlugField(_('Slug'), max_length=200, blank=True, null=False, unique=True)
tags = TaggableManager(_('Tags'))
published_date = models.DateTimeField(_('Published Date/Time'), auto_now_add=True)
updated_date = models.DateTimeField(_('Updated Date/Time'), auto_now=True)
def __str__(self):
return self.title
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.title)
super().save(*args, **kwargs)
#property
def comments_count(self):
return self.comments.count()
def get_absolute_url(self):
return reverse('blog')
for any help I would be greatefull
Try to write it like this:
def test_post_create_view_POST_success(self):
data = {
'author': self.user,
'title': 'test_title',
'content': 'test_content',
'category': 'test_category',
'slug': 'test_slug',
'tags': None, # or create some tags and populate
}
response = self.client.post(self.add_post_url, data=data, follow=True) # make sure your url is correct too btw that could also be the issue
self.assertEquals(response.status_code, 200)
self.assertEquals(Post.objects.filter(title='test_title').count(), 1)

__init__() got an unexpected keyword argument 'book_category'

Hi? I'm new to web development can you plz help me whats the problem with my file?
I don't know why is this, I have defined my category model properly and imported it. I have also defined book_category. Im stuck
views.py: the error is found here
class AddBookIndexView(View):
def get(self, request):
booksQS = Books.objects.all()
authorsQS = Author.objects.all()
categoryQS = Category.objects.all()
print(authorsQS)
print(categoryQS)
print(booksQS)
return render(request, 'addbook.html')
def post(self, request):
form = BooksForm(request.POST, request.FILES)
if form.is_valid():
book_category = request.POST.get('book_category')
firstname = request.POST.get('Firstname')
lastname = request.POST.get('Lastname')
author = Author.objects.filter(Q(firstname__icontains = firstname) & Q(lastname__icontains = lastname))
if author:
print(author)
else:
form = AuthorForm(firstname= firstname, lastname=lastname)
form.save()
category = Category.objects.filter(Q(book_category__icontains = book_category))
if category:
print(category)
else:
form = CategoryForm(book_category= book_category)#this is where the error
form.save()
author = Author.objects.filter(Q(firstname__icontains = firstname) & Q(lastname__icontains = lastname))
category = Category.objects.filter(Q(book_category__icontains = book_category))
for a in author:
print(a.book_author_id)
for c in category:
print(c.book_category_no)
book_title = request.POST.get('book_title')
book_cover = request.FILES.get('book_cover')
book_file = request.FILES.get('book_file')
book_year = request.POST.get('book_year')
book_tags = request.POST.get('book_tags')
book_summary = request.POST.get('book_summary')
form = Books(book_title = book_title, book_author_id = Author.objects.get(book_author_id = a.book_author_id), book_cover = book_cover,
book_file = book_file, book_year = book_year, book_summary = book_summary, book_category_no = Category.objects.get(book_category_no = c.book_category_no),
is_bookmarked = 0, is_downloaded = 0, is_read = 0, is_deleted = 0)
form.save()
return HttpResponse('Book Saved!')
else:
print(form.errors)
return HttpResponse('Not Valid')
This is what my models.py looks like:
from django.db import models
from django.utils import timezone
class Category(models.Model):
# book_category_no = models.CharField(primary_key=True, max_length=50)
book_category_no = models.AutoField(primary_key=True)
book_category = models.CharField(max_length=100)
class Meta:
db_table = "Category"
class Books(models.Model):
# book_id = models.CharField(primary_key=True, max_length=50)
book_id = models.AutoField(primary_key=True)
book_title = models.CharField(max_length = 100)
book_author_id = models.ForeignKey(Author, on_delete=models.CASCADE)
book_cover = models.ImageField(upload_to='media/')
book_file = models.FileField(upload_to='media/')
book_year = models.DateField()
book_tags = models.CharField(max_length = 100)
book_summary = models.CharField(max_length = 100)
book_category_no = models.ForeignKey(Category, on_delete=models.CASCADE)
date_added = models.DateField(default=timezone.now)
# book_info = models.CharField(max_length = 100, default="")
is_bookmarked = models.BooleanField()
is_downloaded = models.BooleanField()
is_read = models.BooleanField()
is_deleted= models.BooleanField(default=False)
class Meta:
db_table = "Books"
Traceback
File "C:\Users\user\AppData\Local\Programs\Python\Python35\lib\site-packages\django\core\handlers\exception.py" in inner
34. response = get_response(request)
File "C:\Users\user\AppData\Local\Programs\Python\Python35\lib\site-packages\django\core\handlers\base.py" in _get_response
115. response = self.process_exception_by_middleware(e, request)
File "C:\Users\user\AppData\Local\Programs\Python\Python35\lib\site-packages\django\core\handlers\base.py" in _get_response
113. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\Users\user\AppData\Local\Programs\Python\Python35\lib\site-packages\django\views\generic\base.py" in view
71. return self.dispatch(request, *args, **kwargs)
File "C:\Users\user\AppData\Local\Programs\Python\Python35\lib\site-packages\django\views\generic\base.py" in dispatch
97. return handler(request, *args, **kwargs)
File "C:\ARMS\projectarms\arms\views.py" in post
315. form = CategoryForm(book_category= book_category)
Exception Type: TypeError at /arms/addbook/
Exception Value: init() got an unexpected keyword argument 'book_category'
`
Most certainly your Category or CategoryForm model is missing a field book_category which you use here:
category = Category.objects.filter(Q(book_category__icontains = book_category))

Django: Expected view likeList to be called with a URL keyword argument named "id"

Ive been trying to create an API that would return all objects from Like model however, I received an error (Expected view likeList to be called with a URL keyword argument named "id". Fix your URL conf, or set the .lookup_field attribute on the view correctly.).
Here is my model
class Post(models.Model):
title = models.CharField(max_length=100)
content = models.TextField()
date_posted = models.DateTimeField(auto_now_add=True)
date_updated = models.DateTimeField(auto_now=True)
author = models.ForeignKey(User, on_delete=models.CASCADE)
objects = models.Manager()
image = models.ImageField(upload_to='post_pics')
def __str__(self):
return self.title
#property
def useremail(self):
return self.author.email
#property
def owner(self):
return self.author
def get_absolute_url(self):
return reverse('post-detail', kwargs={'pk':self.pk})
def get_api_url(self, request=None):
return api_reverse('post-detail', kwargs={'pk': self.pk}, request=request)
def get_like_count(self):
return self.like_set.count()
class Like(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
post = models.ForeignKey(Post, on_delete=models.CASCADE)
created = models.DateTimeField(auto_now_add=True)
Serializer
class likeserializers(serializers.ModelSerializer):
username = serializers.SerializerMethodField(read_only=True)
post_title = serializers.SerializerMethodField(read_only=True)
class Meta:
model = Like
fields = ('id','created',
'user','username',
'post','post_title')
def get_username(self, obj):
return obj.user.username
def get_post_title(self, obj):
return obj.post.title
Views
class likeList(generics.RetrieveUpdateDestroyAPIView):
lookup_field = 'id'
serializer_class = likeserializers
def get_queryset(self):
return Like.objects.all()
URLS
urlpatterns = [
path('users/', API_views.userList.as_view(), name = 'users'),
path('users/id=<int:id>/', API_views.userListbyID.as_view(), name = 'usersid'),
path('posts/', API_views.postList.as_view(), name = 'post'),
path('posts/id=<int:id>', API_views.postListbyID.as_view(), name = 'postid'),
path('likes/', API_views.likeList.as_view(), name = 'likes'),
path('likes/id=<int:id>', API_views.likeListbyID.as_view(), name = 'likesid'),
path('follows/', API_views.followList.as_view(), name = 'likes'),
path('follows/id=<int:id>', API_views.followListbyID.as_view(), name = 'likesid'),
]
As per the error I should either fix my URL conf, or set the .lookup_field attribute on the view correctly. It works as intended if I change my URL conf however, if I use only lookup_field it fix the issue. I have completely the same view for posts and it works.
Post serializer:
class postserializer(serializers.ModelSerializer):
url = serializers.SerializerMethodField(read_only=True)
like_count = serializers.SerializerMethodField(read_only=True)
class Meta:
model = Post
fields = ('url','id',
'title','content',
'date_posted','author',
'useremail','like_count')
def get_url(self,obj):
request = self.context.get("request")
return obj.get_api_url(request=request)
def get_like_count(self,obj):
return obj.get_like_count()
def validate_title(self,value):
qs = Post.objects.filter(title__iexact = value)
#exclude the same instance
if self.instance:
qs = qs.exclude(pk=self.instance.pk)
#if title already exists raise error
if qs.exists():
raise serializers.ValidationError(f"Post with title '{value}' already exists")
return value
and post view:
class postList(mixins.CreateModelMixin, generics.ListAPIView):
lookup_field = 'id'
serializer_class = postserializer
permission_classes = [IsOwnerOrReadOnly]
# permissions can be set up here as well + in settings.py
# permission_classes =
def get_queryset(self):
qs = Post.objects.all()
query = self.request.GET.get("q")
if query is not None:
qs = qs.filter(
Q(title__icontains = query)|
Q(content__icontains = query)
).distinct()
return qs
def post(self, request, *args, **kwargs):
return self.create(request, *args, **kwargs)
What am I missing? What is the difference between my post and like views/serializers which are causing this issue?

TypeError 'x' object has no attribute '__getitem__'

Im getting the error
'CampSite' object has no attribute '__getitem__'
when I save a new CampCon entry in the admin interface. I have one application called campsites that handles the database of campsites, and I have another application called content that handles reviews. I am very new to Django and this is my first non-tutorial based project. I have been racking my brain and searching the web for an answer with no luck. Thank you in advance for your help.
Here is my campsite model:
from django.contrib.gis.db import models
class CampSite(models.Model):
name = models.CharField(max_length=250)
showers = models.BooleanField()
flush = models.BooleanField()
rv = models.BooleanField()
lonlat = models.PointField(null=True, blank=True)
objects = models.GeoManager()
def __unicode__(self):
return self.name
Here is the content model:
from django.contrib.gis.db import models
from campsites.models import CampSite
from django.contrib.auth.models import User
from activities.models import Activities
class CampCon(models.Model):
campsite = models.ForeignKey(CampSite)
trip = models.ForeignKey('Trip')
Date = models.DateField()
user = models.ForeignKey(User)
overall_review = models.TextField()
facilities_review = models.IntegerField()
things_to_do = models.IntegerField()
privacy = models.IntegerField()
beauty = models.IntegerField()
overall_rating = models.IntegerField()
def __unicode__(self):
return self.campsite
class ImageDB(models.Model):
campsite = models.ForeignKey(CampSite)
user = models.ForeignKey(User)
description = models.CharField(max_length=200)
image = models.ImageField(upload_to='/home/bobby/Pictures/CampThat')
date_uploaded = models.DateField()
date_taken = models.DateField()
trip = models.ForeignKey('Trip')
activity = models.ForeignKey(Activities)
def __unicode__(self):
return self.campsite
class Trip(models.Model):
date = models.DateField()
description = models.CharField(max_length=100)
title = models.CharField(max_length=100)
blog = models.TextField()
def __unicode__(self):
return self.title
class ActivityCon(models.Model):
trip = models.ForeignKey(Trip)
rating = models.IntegerField()
overall_review = models.TextField()
activity = models.ForeignKey(Activities)
And here is the full Traceback:
Environment:
Request Method: POST
Request URL: http://localhost:8000/admin/content/campcon/add/
Django Version: 1.5
Python Version: 2.7.3
Installed Applications:
('django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.messages',
'django.contrib.staticfiles',
'campsites',
'auth',
'trips',
'content',
'activities',
'django.contrib.admin')
Installed Middleware:
('django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware')
Traceback:
File "/usr/lib/python2.7/site-packages/django/core/handlers/base.py" in get_response
116. response = callback(request, *callback_args, **callback_kwargs)
File "/usr/lib/python2.7/site-packages/django/contrib/admin/options.py" in wrapper
367. return self.admin_site.admin_view(view)(*args, **kwargs)
File "/usr/lib/python2.7/site-packages/django/utils/decorators.py" in _wrapped_view
91. response = view_func(request, *args, **kwargs)
File "/usr/lib/python2.7/site-packages/django/views/decorators/cache.py" in _wrapped_view_func
89. response = view_func(request, *args, **kwargs)
File "/usr/lib/python2.7/site-packages/django/contrib/admin/sites.py" in inner
202. return view(request, *args, **kwargs)
File "/usr/lib/python2.7/site-packages/django/utils/decorators.py" in _wrapper
25. return bound_func(*args, **kwargs)
File "/usr/lib/python2.7/site-packages/django/utils/decorators.py" in _wrapped_view
91. response = view_func(request, *args, **kwargs)
File "/usr/lib/python2.7/site-packages/django/utils/decorators.py" in bound_func
21. return func(self, *args2, **kwargs2)
File "/usr/lib/python2.7/site-packages/django/db/transaction.py" in inner
208. return func(*args, **kwargs)
File "/usr/lib/python2.7/site-packages/django/contrib/admin/options.py" in add_view
958. self.log_addition(request, new_object)
File "/usr/lib/python2.7/site-packages/django/contrib/admin/options.py" in log_addition
525. action_flag = ADDITION
File "/usr/lib/python2.7/site-packages/django/contrib/admin/models.py" in log_action
18. e = self.model(None, None, user_id, content_type_id, smart_text(object_id), object_repr[:200], action_flag, change_message)
Exception Type: TypeError at /admin/content/campcon/add/
Exception Value: 'CampSite' object has no attribute '__getitem__'
Your issue is that your __unicode__ functions are returning model objects when they need to be returning unicode strings.
You can achieve this by adding the unicode() function to your __unicode__ methods:
class CampCon(models.Model):
campsite = models.ForeignKey(CampSite)
trip = models.ForeignKey('Trip')
Date = models.DateField()
user = models.ForeignKey(User)
overall_review = models.TextField()
facilities_review = models.IntegerField()
things_to_do = models.IntegerField()
privacy = models.IntegerField()
beauty = models.IntegerField()
overall_rating = models.IntegerField()
def __unicode__(self):
return unicode(self.campsite)
class ImageDB(models.Model):
campsite = models.ForeignKey(CampSite)
user = models.ForeignKey(User)
description = models.CharField(max_length=200)
image = models.ImageField(upload_to='/home/bobby/Pictures/CampThat')
date_uploaded = models.DateField()
date_taken = models.DateField()
trip = models.ForeignKey('Trip')
activity = models.ForeignKey(Activities)
def __unicode__(self):
return unicode(self.campsite)
This will call CampSite.__unicode__ which will return campsite.name.
Use this method instead:
def __unicode__(self):
return unicode(self.campsite)
This also happens if you do it like this:
event_name = CharField(max_length = 250)
and not like this: (the right way)
event_name = models.CharField(max_length = 250)
might be helpful to someone
Since this is the first hit on Google: I got a similar error ('ItemGroup' object has no attribute '__getitem__') when doing the following:
class ItemGroup(models.Model):
groupname = models.CharField(max_length=128)
def __unicode__(self):
return "%s" % self.groupname
class Item(models.Model):
name = models.CharField(max_length=128)
group = models.ForeignKey(MedGroup, verbose_name="Groep")
def __unicode__(self):
return "%s (%s)" % (self.name, self.group[:10])
The last line is wrong.
It was fixed by replacing that line to return "%s (%s)" % (self.name, self.group.groupname[:10])

Categories

Resources