I followed what is outlined here. Here is my code:
from google.appengine.api import users
from google.appengine.ext import db
class Book(db.Model):
title = db.StringProperty()
class Author(db.Model):
name = db.StringProperty()
class BookAuthor(db.Model):
book = db.ReferenceProperty(Book, required=True, collection_name='books')
author = db.ReferenceProperty(Author, required=True, collection_name='authors')
b = Book(title="My Book")
a = Author(name="Author of My Book")
db.put([b, a])
ba = BookAuthor(book=b, author=a)
ba.put()
b.authors
a.books
and I get AttributeError: 'Book' object has no attribute 'authors'
ReferenceProperties add query-objects as attributes to the referenced class. So look carefully at your mappings:
class BookAuthor(db.Model):
# This adds a query-object as an attribute named 'books' to Book entities.
book = db.ReferenceProperty(Book, required=True, collection_name='books')
# This adds a query-object as an attribute named 'authors' to Author entities.
author = db.ReferenceProperty(Author, required=True, collection_name='authors')
In your code:
b = Book(title="My Book")
a = Author(name="Author of My Book")
So, b would have a books attribute, not authors. And, a would have a authors attribute, not books.
If you change the collection names, your code should run.
class BookAuthor(db.Model):
# This adds a query-object as an attribute named 'authors' to Book entities.
book = db.ReferenceProperty(Book, required=True, collection_name='authors')
# This adds a query-object as an attribute named 'books' to Author entities.
author = db.ReferenceProperty(Author, required=True, collection_name='books')
Also, if BookAuthor does not have additional properties, make sure you look at the list-of-keys method outlined in the article you referenced.
Related
I am building a blog website and I am using Django rest framework
I want to fetch top 2 comments for a particular post along with their related data such as user details.
Now I have user details in two models
User
People
and the comments model is related to the user model using foreign key relationship
Models ->
Comments
class Comment(models.Model):
comment = models.TextField(null=True)
Created_date = models.DateTimeField(auto_now_add=True)
Updated_date = models.DateTimeField(auto_now=True)
post = models.ForeignKey(Post, on_delete=models.CASCADE,
related_name='comments_post')
user = models.ForeignKey(User, on_delete=models.CASCADE,
related_name='comments_user')
The People model is also connected to the user model with a foreign key relationship
People Model ->
class People(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE,related_name='people')
Name = models.CharField(max_length=255,null=True)
following = models.ManyToManyField(to=User, related_name='following', blank=True)
photo = models.ImageField(upload_to='profile_pics', blank=True,null=True)
Phone_number = models.CharField(max_length=255,null=True,blank=True)
Birth_Date = models.DateField(null=True,blank=True)
Created_date = models.DateTimeField(auto_now_add=True)
Updated_date = models.DateTimeField(auto_now=True)
for fetching the comments I am using rest-framework and the serializers look like this
class UserSerializer(serializers.Serializer):
username = serializers.CharField(max_length=255)
class peopleSerializer(serializers.Serializer):
Name = serializers.CharField(max_length=255)
class commentsSerializer(serializers.Serializer):
id = serializers.IntegerField(read_only=True)
comment = serializers.CharField(max_length=255)
Created_date = serializers.DateTimeField()
user = UserSerializer()
people = peopleSerializer()
The query to fetch the comments look like this ->
post_id = request.GET.get('post_id')
comments = Comment.objects.filter(post_id=post_id).select_related('user').prefetch_related('user__people').order_by('-Created_date')[:2]
serializer = commentsSerializer(comments, many=True)
return Response(serializer.data)
I am getting this error ->
Got AttributeError when attempting to get a value for field `people` on serializer `commentsSerializer`. The serializer field might be named incorrectly and not match any attribute or key on the `Comment` instance. Original exception text was: 'Comment' object has no attribute 'people'.
Unable to find a way out.
The source is user.people, not people, so:
class commentsSerializer(serializers.Serializer):
# …
people = peopleSerializer(source='user.people')
In the .select_related(…) [Django-doc] to can specify user__people: this will imply selecting user and will fetch the data in the same query, not in an extra query as is the case for .prefetch_related(…) [Django-doc]:
post_id = request.GET.get('post_id')
comments = Comment.objects.filter(
post_id=post_id
).select_related('user__people').order_by('-Created_date')[:2]
serializer = commentsSerializer(comments, many=True)
return Response(serializer.data)
Note: normally a Django model is given a singular name, so Person instead of People.
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: normally the name of the fields in a Django model are written in snake_case, not PascalCase, so it should be: created_date instead of Created_date.
I have 2 models: Book, Author
class Author(models.Model):
name = models.CharField(max_length=30)
class Book(models.Model):
title = models.CharField(max_length=100)
authors = models.ManyToManyField(Author)
and in admin :
class BookAdmin(admin.ModelAdmin):
list_display = ('title')
filter_horizontal = ('authors',)
in admin , I want to see only Authors that related to specified Book
not all Authors
(in add mode Authors must be empty)
AdminBook:
I'm playing with GeoDjango and have some doubts. I'll really appreciate any comment and suggestion.
This is my problem. First, I've defined this (abstract) class:
from django.contrib.gis.db import models
from django.contrib.gis.geos import *
class LocatableModel(models.Model):
country = models.CharField(max_length=48, blank=True)
country_code = models.CharField(max_length=2, blank=True)
locality = models.CharField(max_length=48, blank=True)
sub_locality = models.CharField(max_length=48, blank=True)
street = models.CharField(max_length=48, blank=True)
address = models.CharField(max_length=120, blank=True)
point = models.PointField(null=True)
objects = models.GeoManager()
class Meta:
abstract = True
Second, I've defined this other 'Entity' class, which
represents a person or organization related to my site:
from django.db import models
class Entity(models.Model):
name = models.CharField(max_length=64)
slug = models.SlugField(max_length=64, unique=True)
website = models.URLField(verify_exists=False, blank=True)
email = models.EmailField(blank=True)
...
Finally, I've created a class from the previous ones:
import LocatableModel
import Entity
class Organization(Entity, LocatableModel):
timetable = models.CharField(max_length=64)
...
In my views, I'd like to find organizations near a specific point:
from django.contrib.gis.geos import Point
from django.contrib.gis.measure import D
def index(request):
pnt = Point(12.4604, 43.9420)
dic = { 'orgs': Organization.objects.filter(point__distance__lte=(pnt, D(km=7))) }
return render_to_response('index.html', dic)
But I receive the error:
"Join on field 'point' not permitted. Did you misspell 'distance' for
the lookup type?"
I think I'm doing a mess with the model 'objects' property, but I'm not sure. Any ideas?
Thanks in advance.
This error has been seen before, and claimed to be solved in this ticket 3 years ago:
https://code.djangoproject.com/ticket/9364
When I ran into this same problem, I noticed in the ticket that the query manager was set explicitly to GeoManager in the inherited model(s). So adding a line like,
class Organization(Entity, LocatableModel):
timetable = models.CharField(max_length=64)
...
objects = models.GeoManager()
...may solve the issue you're seeing, it worked for me.
Say I have 3 entities:
class A(db.Model):
something = db.StringProperty()
class B(db.Model):
somethingelse = db.StringProperty()
class C(db.Model):
reference = db.ReferenceProperty()
where the Reference in C can be either A or B, how to I determine, given an instance of C, the reference's type (A or B)?
Regards,
Johnny
You can do this without fetching the referenced entity like this:
c_instance = C.get(...)
referenced_kind = C.reference.get_value_for_datastore(c_instance).kind()
or, if you already have an entity:
entity.key().kind()
See the docs on Key and Property for more info.
I get really confused with many-to-many database relationships, so can some one please clarify how I would achieve this?
I need a table of "Tags" (as in tag words) and a table for "Entries", such at many "Entries" could correspond to many Tag words.
Right now I have my models like this:
# models.py
class Tags(models.Model):
tag = models.CharField(max_length=255)
entry = models.ManyToManyField(Entry)
class Entry(models.Model):
entry = models.CharField(max_length=255)
description = models.TextField()
Now I'm confused, how would I setup my admin.py so I could then add tags when I create a new entry?
What you need is using the through feature of models:
class Tag(models.Model):
tag = models.CharField(max_length=255)
entry = models.ManyToManyField(Entry, through='TaggedEntries')
class Entry(models.Model):
entry = models.CharField(max_length=255)
description = models.TextField()
class TaggedEntries(models.Model):
entry = models.ForeignKey(Entry)
tag = models.ForeignKey(Tag)
and now use that model in your admin:
class TagsInline(admin.TabularInline):
model = TaggedEntries
extra = 1
class EntryAdmin(admin.ModelAdmin):
inlines = (TagsInline, )
admin.site.register(Entry, EntryAdmin)
admin.site.register(Tag)
You will need something along the lines of:
# admin.py
from django.contrib import admin
from models import *
class TagsInline(admin.TabularInline):
model = Tag
extra = 1
class EntryAdmin(admin.ModelAdmin):
inlines = (TagsInline, )
admin.site.register(Entry, EntryAdmin)
admin.site.register(Tag)
(Note, this code was written in a browser!)