Content Types
buraq.contrib.contenttypes provides a generic foreign key mechanism — a way to link any model to any other model without a hard-coded foreign key.
Add to INSTALLED_APPS and run migrations:
INSTALLED_APPS = [ "buraq.contrib.contenttypes", ...]ContentType model
Section titled “ContentType model”ContentType stores a row for every installed model:
from buraq.contrib.contenttypes.models import ContentType
ct = await ContentType.get_for_model(Post)# <ContentType blog.post>
ct.app_label # "blog"ct.model # "post"GenericForeignKey
Section titled “GenericForeignKey”Link any model to any other model:
from sqlalchemy import Column, Integerfrom buraq.orm.base import Modelfrom buraq.contrib.contenttypes.fields import GenericForeignKey
class Comment(Model): content_type_id = Column(Integer, nullable=True) object_id = Column(Integer, nullable=True) content_object = GenericForeignKey("content_type_id", "object_id") body = Column(String(500))Resolve the linked object asynchronously:
comment = await Comment.objects.get(id=1)post = await comment.content_object # Post instance or NoneCreating a generic relation
Section titled “Creating a generic relation”from buraq.contrib.contenttypes.models import ContentType
ct = await ContentType.get_for_model(Post)post = await Post.objects.get(id=42)
comment = await Comment.objects.create( content_type_id=ct.id, object_id=post.id, body="Great post!",)ContentType lookup helpers
Section titled “ContentType lookup helpers”ct = await ContentType.get_for_model(Post)
# Look up by natural key (app_label, model)ct = await ContentType.get_by_natural_key("blog", "post")
# Get the Python class for a ContentType rowmodel_class = ct.model_class() # returns Post class, or None if not importableGenericRelation — reverse accessor
Section titled “GenericRelation — reverse accessor”Add GenericRelation to the target model to query all objects that point to it via a GenericForeignKey:
from buraq.contrib.contenttypes.fields import GenericForeignKey, GenericRelationfrom buraq.orm.base import Modelfrom sqlalchemy import Column, Integer, String
class Comment(Model): content_type_id = Column(Integer) object_id = Column(Integer) content_object = GenericForeignKey() body = Column(String(500))
class Post(Model): title = Column(String(200)) comments = GenericRelation(Comment) # reverse accessorQuery through the reverse relation:
post = await Post.objects.get(id=1)
# All comments for this postcomments = await post.comments.all()
# Filteredrecent = await post.comments.filter(created_at__gte=since)
# Countn = await post.comments.count()
# Create via relation (content_type_id and object_id filled automatically)new_comment = await post.comments.create(body="Nice!")Use a dotted string to avoid circular imports:
class Post(Model): comments = GenericRelation("blog.models.Comment")