Kaydet (Commit) 825429c1 authored tarafından Tim Graham's avatar Tim Graham

Moved foreign_object models.py into a module.

üst 5b5a2794
from .article import (
Article, ArticleIdea, ArticleTag, ArticleTranslation, NewsArticle,
)
from .person import Country, Friendship, Group, Membership, Person
__all__ = [
'Article', 'ArticleIdea', 'ArticleTag', 'ArticleTranslation', 'Country',
'Friendship', 'Group', 'Membership', 'NewsArticle', 'Person',
]
from django.db import models
from django.db.models.fields.related import \
ReverseSingleRelatedObjectDescriptor
from django.utils.encoding import python_2_unicode_compatible
from django.utils.translation import get_language
class ArticleTranslationDescriptor(ReverseSingleRelatedObjectDescriptor):
"""
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)
setattr(instance, self.cache_name, value)
if value is not None and not self.field.remote_field.multiple:
setattr(value, self.field.related.get_cache_name(), instance)
class ColConstraint(object):
# 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, where_class, 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(ActiveTranslationField, self).contribute_to_class(cls, name)
setattr(cls, self.name, ArticleTranslationDescriptor(self))
@python_2_unicode_compatible
class Article(models.Model):
active_translation = ActiveTranslationField(
'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.CharField(max_length=400, null=True)
class Meta:
unique_together = ('article', 'lang')
ordering = ('active_translation__title',)
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)
import datetime import datetime
from django.db import models from django.db import models
from django.db.models.fields.related import \
ReverseSingleRelatedObjectDescriptor
from django.utils.encoding import python_2_unicode_compatible from django.utils.encoding import python_2_unicode_compatible
from django.utils.translation import get_language
@python_2_unicode_compatible @python_2_unicode_compatible
...@@ -112,89 +109,3 @@ class Friendship(models.Model): ...@@ -112,89 +109,3 @@ class Friendship(models.Model):
related_name='to_friend', related_name='to_friend',
on_delete=models.CASCADE, on_delete=models.CASCADE,
) )
class ArticleTranslationDescriptor(ReverseSingleRelatedObjectDescriptor):
"""
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)
setattr(instance, self.cache_name, value)
if value is not None and not self.field.remote_field.multiple:
setattr(value, self.field.related.get_cache_name(), instance)
class ColConstraint(object):
# 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, where_class, 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(ActiveTranslationField, self).contribute_to_class(cls, name)
setattr(cls, self.name, ArticleTranslationDescriptor(self))
@python_2_unicode_compatible
class Article(models.Model):
active_translation = ActiveTranslationField(
'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.CharField(max_length=400, null=True)
class Meta:
unique_together = ('article', 'lang')
ordering = ('active_translation__title',)
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)
import datetime
from django import forms
from django.test import TestCase
from .models import Article
class FormsTests(TestCase):
# ForeignObjects should not have any form fields, currently the user needs
# to manually deal with the foreignobject relation.
class ArticleForm(forms.ModelForm):
class Meta:
model = Article
fields = '__all__'
def test_foreign_object_form(self):
# A very crude test checking that the non-concrete fields do not get form fields.
form = FormsTests.ArticleForm()
self.assertIn('id_pub_date', form.as_table())
self.assertNotIn('active_translation', form.as_table())
form = FormsTests.ArticleForm(data={'pub_date': str(datetime.date.today())})
self.assertTrue(form.is_valid())
a = form.save()
self.assertEqual(a.pub_date, datetime.date.today())
form = FormsTests.ArticleForm(instance=a, data={'pub_date': '2013-01-01'})
a2 = form.save()
self.assertEqual(a.pk, a2.pk)
self.assertEqual(a2.pub_date, datetime.date(2013, 1, 1))
import datetime import datetime
from operator import attrgetter from operator import attrgetter
from django import forms
from django.core.exceptions import FieldError from django.core.exceptions import FieldError
from django.test import TestCase, skipUnlessDBFeature from django.test import TestCase, skipUnlessDBFeature
from django.utils import translation from django.utils import translation
...@@ -392,26 +391,3 @@ class MultiColumnFKTests(TestCase): ...@@ -392,26 +391,3 @@ class MultiColumnFKTests(TestCase):
""" See: https://code.djangoproject.com/ticket/21566 """ """ See: https://code.djangoproject.com/ticket/21566 """
objs = [Person(name="abcd_%s" % i, person_country=self.usa) for i in range(0, 5)] objs = [Person(name="abcd_%s" % i, person_country=self.usa) for i in range(0, 5)]
Person.objects.bulk_create(objs, 10) Person.objects.bulk_create(objs, 10)
class FormsTests(TestCase):
# ForeignObjects should not have any form fields, currently the user needs
# to manually deal with the foreignobject relation.
class ArticleForm(forms.ModelForm):
class Meta:
model = Article
fields = '__all__'
def test_foreign_object_form(self):
# A very crude test checking that the non-concrete fields do not get form fields.
form = FormsTests.ArticleForm()
self.assertIn('id_pub_date', form.as_table())
self.assertNotIn('active_translation', form.as_table())
form = FormsTests.ArticleForm(data={'pub_date': str(datetime.date.today())})
self.assertTrue(form.is_valid())
a = form.save()
self.assertEqual(a.pub_date, datetime.date.today())
form = FormsTests.ArticleForm(instance=a, data={'pub_date': '2013-01-01'})
a2 = form.save()
self.assertEqual(a.pk, a2.pk)
self.assertEqual(a2.pub_date, datetime.date(2013, 1, 1))
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment