django/tests/model_forms/models.py

524 lines
14 KiB
Python

import datetime
import os
import tempfile
import uuid
from django.core import validators
from django.core.exceptions import ValidationError
from django.core.files.storage import FileSystemStorage
from django.db import models
temp_storage_dir = tempfile.mkdtemp()
temp_storage = FileSystemStorage(temp_storage_dir)
class Person(models.Model):
name = models.CharField(max_length=100)
class Category(models.Model):
name = models.CharField(max_length=20)
slug = models.SlugField(max_length=20)
url = models.CharField("The URL", max_length=40)
class Meta:
ordering = ("pk",)
def __str__(self):
return self.name
def __repr__(self):
return self.__str__()
class WriterManager(models.Manager):
def get_queryset(self):
qs = super().get_queryset()
return qs.filter(archived=False)
class Writer(models.Model):
name = models.CharField(max_length=50, help_text="Use both first and last names.")
archived = models.BooleanField(default=False, editable=False)
objects = WriterManager()
class Meta:
ordering = ("name",)
def __str__(self):
return self.name
class Article(models.Model):
ARTICLE_STATUS = (
(1, "Draft"),
(2, "Pending"),
(3, "Live"),
)
headline = models.CharField(max_length=50)
slug = models.SlugField()
pub_date = models.DateField()
created = models.DateField(editable=False)
writer = models.ForeignKey(Writer, models.CASCADE)
article = models.TextField()
categories = models.ManyToManyField(Category, blank=True)
status = models.PositiveIntegerField(choices=ARTICLE_STATUS, blank=True, null=True)
def save(self, *args, **kwargs):
if not self.id:
self.created = datetime.date.today()
return super().save(*args, **kwargs)
def __str__(self):
return self.headline
class ImprovedArticle(models.Model):
article = models.OneToOneField(Article, models.CASCADE)
class ImprovedArticleWithParentLink(models.Model):
article = models.OneToOneField(Article, models.CASCADE, parent_link=True)
class BetterWriter(Writer):
score = models.IntegerField()
class Publication(models.Model):
title = models.CharField(max_length=30)
date_published = models.DateField()
def __str__(self):
return self.title
def default_mode():
return "di"
def default_category():
return 3
class PublicationDefaults(models.Model):
MODE_CHOICES = (("di", "direct"), ("de", "delayed"))
CATEGORY_CHOICES = ((1, "Games"), (2, "Comics"), (3, "Novel"))
title = models.CharField(max_length=30)
date_published = models.DateField(default=datetime.date.today)
datetime_published = models.DateTimeField(default=datetime.datetime(2000, 1, 1))
mode = models.CharField(max_length=2, choices=MODE_CHOICES, default=default_mode)
category = models.IntegerField(choices=CATEGORY_CHOICES, default=default_category)
active = models.BooleanField(default=True)
file = models.FileField(default="default.txt")
class Author(models.Model):
publication = models.OneToOneField(
Publication, models.SET_NULL, null=True, blank=True
)
full_name = models.CharField(max_length=255)
class Author1(models.Model):
publication = models.OneToOneField(Publication, models.CASCADE, null=False)
full_name = models.CharField(max_length=255)
class WriterProfile(models.Model):
writer = models.OneToOneField(Writer, models.CASCADE, primary_key=True)
age = models.PositiveIntegerField()
def __str__(self):
return "%s is %s" % (self.writer, self.age)
class Document(models.Model):
myfile = models.FileField(upload_to="unused", blank=True)
class TextFile(models.Model):
description = models.CharField(max_length=20)
file = models.FileField(storage=temp_storage, upload_to="tests", max_length=15)
def __str__(self):
return self.description
class CustomFileField(models.FileField):
def save_form_data(self, instance, data):
been_here = getattr(self, "been_saved", False)
assert not been_here, "save_form_data called more than once"
setattr(self, "been_saved", True)
class CustomFF(models.Model):
f = CustomFileField(upload_to="unused", blank=True)
class FilePathModel(models.Model):
path = models.FilePathField(
path=os.path.dirname(__file__), match="models.py", blank=True
)
try:
from PIL import Image # NOQA: detect if Pillow is installed
test_images = True
class ImageFile(models.Model):
def custom_upload_path(self, filename):
path = self.path or "tests"
return "%s/%s" % (path, filename)
description = models.CharField(max_length=20)
# Deliberately put the image field *after* the width/height fields to
# trigger the bug in #10404 with width/height not getting assigned.
width = models.IntegerField(editable=False)
height = models.IntegerField(editable=False)
image = models.ImageField(
storage=temp_storage,
upload_to=custom_upload_path,
width_field="width",
height_field="height",
)
path = models.CharField(max_length=16, blank=True, default="")
def __str__(self):
return self.description
class OptionalImageFile(models.Model):
def custom_upload_path(self, filename):
path = self.path or "tests"
return "%s/%s" % (path, filename)
description = models.CharField(max_length=20)
image = models.ImageField(
storage=temp_storage,
upload_to=custom_upload_path,
width_field="width",
height_field="height",
blank=True,
null=True,
)
width = models.IntegerField(editable=False, null=True)
height = models.IntegerField(editable=False, null=True)
path = models.CharField(max_length=16, blank=True, default="")
def __str__(self):
return self.description
class NoExtensionImageFile(models.Model):
def upload_to(self, filename):
return "tests/no_extension"
description = models.CharField(max_length=20)
image = models.ImageField(storage=temp_storage, upload_to=upload_to)
def __str__(self):
return self.description
except ImportError:
test_images = False
class Homepage(models.Model):
url = models.URLField()
class Product(models.Model):
slug = models.SlugField(unique=True)
def __str__(self):
return self.slug
class Price(models.Model):
price = models.DecimalField(max_digits=10, decimal_places=2)
quantity = models.PositiveIntegerField()
class Meta:
unique_together = (("price", "quantity"),)
def __str__(self):
return "%s for %s" % (self.quantity, self.price)
class Triple(models.Model):
left = models.IntegerField()
middle = models.IntegerField()
right = models.IntegerField()
class Meta:
unique_together = (("left", "middle"), ("middle", "right"))
class ArticleStatus(models.Model):
ARTICLE_STATUS_CHAR = (
("d", "Draft"),
("p", "Pending"),
("l", "Live"),
)
status = models.CharField(
max_length=2, choices=ARTICLE_STATUS_CHAR, blank=True, null=True
)
class Inventory(models.Model):
barcode = models.PositiveIntegerField(unique=True)
parent = models.ForeignKey(
"self", models.SET_NULL, to_field="barcode", blank=True, null=True
)
name = models.CharField(blank=False, max_length=20)
class Meta:
ordering = ("name",)
def __str__(self):
return self.name
def __repr__(self):
return self.__str__()
class Book(models.Model):
title = models.CharField(max_length=40)
author = models.ForeignKey(Writer, models.SET_NULL, blank=True, null=True)
special_id = models.IntegerField(blank=True, null=True, unique=True)
class Meta:
unique_together = ("title", "author")
class BookXtra(models.Model):
isbn = models.CharField(max_length=16, unique=True)
suffix1 = models.IntegerField(blank=True, default=0)
suffix2 = models.IntegerField(blank=True, default=0)
class Meta:
unique_together = ("suffix1", "suffix2")
abstract = True
class DerivedBook(Book, BookXtra):
pass
class ExplicitPK(models.Model):
key = models.CharField(max_length=20, primary_key=True)
desc = models.CharField(max_length=20, blank=True, unique=True)
class Meta:
unique_together = ("key", "desc")
def __str__(self):
return self.key
class Post(models.Model):
title = models.CharField(max_length=50, unique_for_date="posted", blank=True)
slug = models.CharField(max_length=50, unique_for_year="posted", blank=True)
subtitle = models.CharField(max_length=50, unique_for_month="posted", blank=True)
posted = models.DateField()
def __str__(self):
return self.title
class DateTimePost(models.Model):
title = models.CharField(max_length=50, unique_for_date="posted", blank=True)
slug = models.CharField(max_length=50, unique_for_year="posted", blank=True)
subtitle = models.CharField(max_length=50, unique_for_month="posted", blank=True)
posted = models.DateTimeField(editable=False)
def __str__(self):
return self.title
class DerivedPost(Post):
pass
class BigInt(models.Model):
biggie = models.BigIntegerField()
def __str__(self):
return str(self.biggie)
class MarkupField(models.CharField):
def __init__(self, *args, **kwargs):
kwargs["max_length"] = 20
super().__init__(*args, **kwargs)
def formfield(self, **kwargs):
# don't allow this field to be used in form (real use-case might be
# that you know the markup will always be X, but it is among an app
# that allows the user to say it could be something else)
# regressed at r10062
return None
class CustomFieldForExclusionModel(models.Model):
name = models.CharField(max_length=10)
markup = MarkupField()
class FlexibleDatePost(models.Model):
title = models.CharField(max_length=50, unique_for_date="posted", blank=True)
slug = models.CharField(max_length=50, unique_for_year="posted", blank=True)
subtitle = models.CharField(max_length=50, unique_for_month="posted", blank=True)
posted = models.DateField(blank=True, null=True)
class Colour(models.Model):
name = models.CharField(max_length=50)
def __iter__(self):
yield from range(5)
def __str__(self):
return self.name
class ColourfulItem(models.Model):
name = models.CharField(max_length=50)
colours = models.ManyToManyField(Colour)
class CustomErrorMessage(models.Model):
name1 = models.CharField(
max_length=50,
validators=[validators.validate_slug],
error_messages={"invalid": "Model custom error message."},
)
name2 = models.CharField(
max_length=50,
validators=[validators.validate_slug],
error_messages={"invalid": "Model custom error message."},
)
def clean(self):
if self.name1 == "FORBIDDEN_VALUE":
raise ValidationError(
{"name1": [ValidationError("Model.clean() error messages.")]}
)
elif self.name1 == "FORBIDDEN_VALUE2":
raise ValidationError(
{"name1": "Model.clean() error messages (simpler syntax)."}
)
elif self.name1 == "GLOBAL_ERROR":
raise ValidationError("Global error message.")
def today_callable_dict():
return {"last_action__gte": datetime.datetime.today()}
def today_callable_q():
return models.Q(last_action__gte=datetime.datetime.today())
class Character(models.Model):
username = models.CharField(max_length=100)
last_action = models.DateTimeField()
def __str__(self):
return self.username
class StumpJoke(models.Model):
most_recently_fooled = models.ForeignKey(
Character,
models.CASCADE,
limit_choices_to=today_callable_dict,
related_name="jokes",
)
has_fooled_today = models.ManyToManyField(
Character,
limit_choices_to=today_callable_q,
related_name="jokes_today",
)
funny = models.BooleanField(default=False)
# Model for #13776
class Student(models.Model):
character = models.ForeignKey(Character, models.CASCADE)
study = models.CharField(max_length=30)
# Model for #639
class Photo(models.Model):
title = models.CharField(max_length=30)
image = models.FileField(storage=temp_storage, upload_to="tests")
# Support code for the tests; this keeps track of how many times save()
# gets called on each instance.
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self._savecount = 0
def save(self, force_insert=False, force_update=False):
super().save(force_insert, force_update)
self._savecount += 1
class UUIDPK(models.Model):
uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
name = models.CharField(max_length=30)
# Models for #24706
class StrictAssignmentFieldSpecific(models.Model):
title = models.CharField(max_length=30)
_should_error = False
def __setattr__(self, key, value):
if self._should_error is True:
raise ValidationError(message={key: "Cannot set attribute"}, code="invalid")
super().__setattr__(key, value)
class StrictAssignmentAll(models.Model):
title = models.CharField(max_length=30)
_should_error = False
def __setattr__(self, key, value):
if self._should_error is True:
raise ValidationError(message="Cannot set attribute", code="invalid")
super().__setattr__(key, value)
# A model with ForeignKey(blank=False, null=True)
class Award(models.Model):
name = models.CharField(max_length=30)
character = models.ForeignKey(Character, models.SET_NULL, blank=False, null=True)
class NullableUniqueCharFieldModel(models.Model):
codename = models.CharField(max_length=50, blank=True, null=True, unique=True)
email = models.EmailField(blank=True, null=True)
slug = models.SlugField(blank=True, null=True)
url = models.URLField(blank=True, null=True)
class Number(models.Model):
value = models.IntegerField()
class NumbersToDice(models.Model):
number = models.ForeignKey("Number", on_delete=models.CASCADE)
die = models.ForeignKey("Dice", on_delete=models.CASCADE)
class Dice(models.Model):
numbers = models.ManyToManyField(
Number,
through=NumbersToDice,
limit_choices_to=models.Q(value__gte=1),
)