django/tests/foreign_object/models/article.py

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

111 lines
3.2 KiB
Python
Raw Normal View History

from django.db import models
from django.db.models.fields.related import ForwardManyToOneDescriptor
from django.utils.translation import get_language
class ArticleTranslationDescriptor(ForwardManyToOneDescriptor):
"""
The set of articletranslation should not set any local fields.
"""
def __set__(self, instance, value):
if instance is None:
raise AttributeError("%s must be accessed via instance" % self.field.name)
self.field.set_cached_value(instance, value)
if value is not None and not self.field.remote_field.multiple:
self.field.remote_field.set_cached_value(value, instance)
class ColConstraint:
# Anything with as_sql() method works in get_extra_restriction().
def __init__(self, alias, col, value):
self.alias, self.col, self.value = alias, col, value
def as_sql(self, compiler, connection):
qn = compiler.quote_name_unless_alias
return "%s.%s = %%s" % (qn(self.alias), qn(self.col)), [self.value]
class ActiveTranslationField(models.ForeignObject):
"""
This field will allow querying and fetching the currently active translation
for Article from ArticleTranslation.
"""
requires_unique_target = False
def get_extra_restriction(self, alias, related_alias):
return ColConstraint(alias, "lang", get_language())
def get_extra_descriptor_filter(self, instance):
return {"lang": get_language()}
def contribute_to_class(self, cls, name):
super().contribute_to_class(cls, name)
setattr(cls, self.name, ArticleTranslationDescriptor(self))
class ActiveTranslationFieldWithQ(ActiveTranslationField):
def get_extra_descriptor_filter(self, instance):
return models.Q(lang=get_language())
class Article(models.Model):
active_translation = ActiveTranslationField(
"ArticleTranslation",
from_fields=["id"],
to_fields=["article"],
related_name="+",
on_delete=models.CASCADE,
null=True,
)
active_translation_q = ActiveTranslationFieldWithQ(
"ArticleTranslation",
from_fields=["id"],
to_fields=["article"],
related_name="+",
on_delete=models.CASCADE,
null=True,
)
pub_date = models.DateField()
def __str__(self):
try:
return self.active_translation.title
except ArticleTranslation.DoesNotExist:
return "[No translation found]"
class NewsArticle(Article):
pass
class ArticleTranslation(models.Model):
article = models.ForeignKey(Article, models.CASCADE)
lang = models.CharField(max_length=2)
title = models.CharField(max_length=100)
body = models.TextField()
abstract = models.TextField(null=True)
class Meta:
unique_together = ("article", "lang")
class ArticleTag(models.Model):
article = models.ForeignKey(
Article,
models.CASCADE,
related_name="tags",
related_query_name="tag",
)
name = models.CharField(max_length=255)
class ArticleIdea(models.Model):
articles = models.ManyToManyField(
Article,
related_name="ideas",
related_query_name="idea_things",
)
name = models.CharField(max_length=255)