use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(Debug, Clone, PartialEq)]
pub struct FieldDeconstruction {
pub name: Option<String>,
pub path: String,
pub args: Vec<FieldArg>,
pub kwargs: HashMap<String, FieldKwarg>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(untagged)]
pub enum FieldArg {
String(String),
Int(i64),
Bool(bool),
Float(f64),
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(untagged)]
pub enum FieldKwarg {
String(String),
Int(i64),
Uint(u64),
Bool(bool),
Float(f64),
Choices(Vec<(String, String)>),
Callable(String), }
pub trait Field: Send + Sync {
fn deconstruct(&self) -> FieldDeconstruction;
fn set_attributes_from_name(&mut self, name: &str);
fn name(&self) -> Option<&str>;
fn is_primary_key(&self) -> bool {
false
}
fn is_null(&self) -> bool {
false
}
fn is_blank(&self) -> bool {
false
}
}
#[derive(Debug, Clone)]
pub struct BaseField {
pub name: Option<String>,
pub null: bool,
pub blank: bool,
pub default: Option<FieldKwarg>,
pub db_default: Option<FieldKwarg>, pub db_column: Option<String>,
pub db_tablespace: Option<String>,
pub primary_key: bool,
pub unique: bool,
pub editable: bool,
pub choices: Option<Vec<(String, String)>>,
}
impl BaseField {
pub fn new() -> Self {
Self {
name: None,
null: false,
blank: false,
default: None,
db_default: None,
db_column: None,
db_tablespace: None,
primary_key: false,
unique: false,
editable: true,
choices: None,
}
}
pub fn get_kwargs(&self) -> HashMap<String, FieldKwarg> {
let mut kwargs = HashMap::new();
if self.null {
kwargs.insert("null".to_string(), FieldKwarg::Bool(true));
}
if self.blank {
kwargs.insert("blank".to_string(), FieldKwarg::Bool(true));
}
if let Some(ref default) = self.default {
kwargs.insert("default".to_string(), default.clone());
}
if let Some(ref db_default) = self.db_default {
kwargs.insert("db_default".to_string(), db_default.clone());
}
if let Some(ref db_column) = self.db_column {
kwargs.insert(
"db_column".to_string(),
FieldKwarg::String(db_column.clone()),
);
}
if let Some(ref db_tablespace) = self.db_tablespace {
kwargs.insert(
"db_tablespace".to_string(),
FieldKwarg::String(db_tablespace.clone()),
);
}
if self.primary_key {
kwargs.insert("primary_key".to_string(), FieldKwarg::Bool(true));
}
if self.unique {
kwargs.insert("unique".to_string(), FieldKwarg::Bool(true));
}
if !self.editable {
kwargs.insert("editable".to_string(), FieldKwarg::Bool(false));
}
if let Some(ref choices) = self.choices {
kwargs.insert("choices".to_string(), FieldKwarg::Choices(choices.clone()));
}
kwargs
}
}
impl Default for BaseField {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
pub struct AutoField {
pub base: BaseField,
}
impl Default for AutoField {
fn default() -> Self {
Self::new()
}
}
impl AutoField {
pub fn new() -> Self {
let mut base = BaseField::new();
base.primary_key = true;
Self { base }
}
}
impl Field for AutoField {
fn deconstruct(&self) -> FieldDeconstruction {
let kwargs = self.base.get_kwargs();
FieldDeconstruction {
name: self.base.name.clone(),
path: "reinhardt.orm.models.AutoField".to_string(),
args: vec![],
kwargs,
}
}
fn set_attributes_from_name(&mut self, name: &str) {
self.base.name = Some(name.to_string());
}
fn name(&self) -> Option<&str> {
self.base.name.as_deref()
}
fn is_primary_key(&self) -> bool {
self.base.primary_key
}
}
#[derive(Debug, Clone)]
pub struct BigIntegerField {
pub base: BaseField,
}
impl Default for BigIntegerField {
fn default() -> Self {
Self::new()
}
}
impl BigIntegerField {
pub fn new() -> Self {
Self {
base: BaseField::new(),
}
}
}
impl Field for BigIntegerField {
fn deconstruct(&self) -> FieldDeconstruction {
FieldDeconstruction {
name: self.base.name.clone(),
path: "reinhardt.orm.models.BigIntegerField".to_string(),
args: vec![],
kwargs: self.base.get_kwargs(),
}
}
fn set_attributes_from_name(&mut self, name: &str) {
self.base.name = Some(name.to_string());
}
fn name(&self) -> Option<&str> {
self.base.name.as_deref()
}
}
#[derive(Debug, Clone)]
pub struct BooleanField {
pub base: BaseField,
}
impl Default for BooleanField {
fn default() -> Self {
Self::new()
}
}
impl BooleanField {
pub fn new() -> Self {
Self {
base: BaseField::new(),
}
}
pub fn with_default(default: bool) -> Self {
let mut field = Self::new();
field.base.default = Some(FieldKwarg::Bool(default));
field
}
}
impl Field for BooleanField {
fn deconstruct(&self) -> FieldDeconstruction {
FieldDeconstruction {
name: self.base.name.clone(),
path: "reinhardt.orm.models.BooleanField".to_string(),
args: vec![],
kwargs: self.base.get_kwargs(),
}
}
fn set_attributes_from_name(&mut self, name: &str) {
self.base.name = Some(name.to_string());
}
fn name(&self) -> Option<&str> {
self.base.name.as_deref()
}
}
#[derive(Debug, Clone)]
pub struct CharField {
pub base: BaseField,
pub max_length: u64,
}
impl CharField {
pub fn new(max_length: u64) -> Self {
Self {
base: BaseField::new(),
max_length,
}
}
pub fn with_null_blank(max_length: u64) -> Self {
let mut base = BaseField::new();
base.null = true;
base.blank = true;
Self { base, max_length }
}
pub fn with_choices(max_length: u64, choices: Vec<(String, String)>) -> Self {
let mut base = BaseField::new();
base.choices = Some(choices);
Self { base, max_length }
}
}
impl Field for CharField {
fn deconstruct(&self) -> FieldDeconstruction {
let mut kwargs = self.base.get_kwargs();
kwargs.insert("max_length".to_string(), FieldKwarg::Uint(self.max_length));
FieldDeconstruction {
name: self.base.name.clone(),
path: "reinhardt.orm.models.CharField".to_string(),
args: vec![],
kwargs,
}
}
fn set_attributes_from_name(&mut self, name: &str) {
self.base.name = Some(name.to_string());
}
fn name(&self) -> Option<&str> {
self.base.name.as_deref()
}
}
#[derive(Debug, Clone)]
pub struct IntegerField {
pub base: BaseField,
}
impl Default for IntegerField {
fn default() -> Self {
Self::new()
}
}
impl IntegerField {
pub fn new() -> Self {
Self {
base: BaseField::new(),
}
}
pub fn with_choices(choices: Vec<(String, String)>) -> Self {
let mut base = BaseField::new();
base.choices = Some(choices);
Self { base }
}
pub fn with_callable_choices(_callable_name: &str) -> Self {
Self::new()
}
}
impl Field for IntegerField {
fn deconstruct(&self) -> FieldDeconstruction {
FieldDeconstruction {
name: self.base.name.clone(),
path: "reinhardt.orm.models.IntegerField".to_string(),
args: vec![],
kwargs: self.base.get_kwargs(),
}
}
fn set_attributes_from_name(&mut self, name: &str) {
self.base.name = Some(name.to_string());
}
fn name(&self) -> Option<&str> {
self.base.name.as_deref()
}
}
#[derive(Debug, Clone)]
pub struct DateField {
pub base: BaseField,
pub auto_now: bool,
pub auto_now_add: bool,
}
impl Default for DateField {
fn default() -> Self {
Self::new()
}
}
impl DateField {
pub fn new() -> Self {
Self {
base: BaseField::new(),
auto_now: false,
auto_now_add: false,
}
}
pub fn with_auto_now() -> Self {
Self {
base: BaseField::new(),
auto_now: true,
auto_now_add: false,
}
}
}
impl Field for DateField {
fn deconstruct(&self) -> FieldDeconstruction {
let mut kwargs = self.base.get_kwargs();
if self.auto_now {
kwargs.insert("auto_now".to_string(), FieldKwarg::Bool(true));
}
if self.auto_now_add {
kwargs.insert("auto_now_add".to_string(), FieldKwarg::Bool(true));
}
FieldDeconstruction {
name: self.base.name.clone(),
path: "reinhardt.orm.models.DateField".to_string(),
args: vec![],
kwargs,
}
}
fn set_attributes_from_name(&mut self, name: &str) {
self.base.name = Some(name.to_string());
}
fn name(&self) -> Option<&str> {
self.base.name.as_deref()
}
}
#[derive(Debug, Clone)]
pub struct DateTimeField {
pub base: BaseField,
pub auto_now: bool,
pub auto_now_add: bool,
}
impl Default for DateTimeField {
fn default() -> Self {
Self::new()
}
}
impl DateTimeField {
pub fn new() -> Self {
Self {
base: BaseField::new(),
auto_now: false,
auto_now_add: false,
}
}
pub fn with_auto_now_add() -> Self {
Self {
base: BaseField::new(),
auto_now: false,
auto_now_add: true,
}
}
pub fn with_both() -> Self {
Self {
base: BaseField::new(),
auto_now: true,
auto_now_add: true,
}
}
}
impl Field for DateTimeField {
fn deconstruct(&self) -> FieldDeconstruction {
let mut kwargs = self.base.get_kwargs();
if self.auto_now {
kwargs.insert("auto_now".to_string(), FieldKwarg::Bool(true));
}
if self.auto_now_add {
kwargs.insert("auto_now_add".to_string(), FieldKwarg::Bool(true));
}
FieldDeconstruction {
name: self.base.name.clone(),
path: "reinhardt.orm.models.DateTimeField".to_string(),
args: vec![],
kwargs,
}
}
fn set_attributes_from_name(&mut self, name: &str) {
self.base.name = Some(name.to_string());
}
fn name(&self) -> Option<&str> {
self.base.name.as_deref()
}
}
#[derive(Debug, Clone)]
pub struct DecimalField {
pub base: BaseField,
pub max_digits: u32,
pub decimal_places: u32,
}
impl DecimalField {
pub fn new(max_digits: u32, decimal_places: u32) -> Self {
Self {
base: BaseField::new(),
max_digits,
decimal_places,
}
}
}
impl Field for DecimalField {
fn deconstruct(&self) -> FieldDeconstruction {
let mut kwargs = self.base.get_kwargs();
kwargs.insert(
"max_digits".to_string(),
FieldKwarg::Uint(self.max_digits as u64),
);
kwargs.insert(
"decimal_places".to_string(),
FieldKwarg::Uint(self.decimal_places as u64),
);
FieldDeconstruction {
name: self.base.name.clone(),
path: "reinhardt.orm.models.DecimalField".to_string(),
args: vec![],
kwargs,
}
}
fn set_attributes_from_name(&mut self, name: &str) {
self.base.name = Some(name.to_string());
}
fn name(&self) -> Option<&str> {
self.base.name.as_deref()
}
}
#[derive(Debug, Clone)]
pub struct EmailField {
pub base: BaseField,
pub max_length: u64,
}
impl Default for EmailField {
fn default() -> Self {
Self::new()
}
}
impl EmailField {
pub fn new() -> Self {
Self {
base: BaseField::new(),
max_length: 254, }
}
pub fn with_max_length(max_length: u64) -> Self {
Self {
base: BaseField::new(),
max_length,
}
}
}
impl Field for EmailField {
fn deconstruct(&self) -> FieldDeconstruction {
let mut kwargs = self.base.get_kwargs();
kwargs.insert("max_length".to_string(), FieldKwarg::Uint(self.max_length));
FieldDeconstruction {
name: self.base.name.clone(),
path: "reinhardt.orm.models.EmailField".to_string(),
args: vec![],
kwargs,
}
}
fn set_attributes_from_name(&mut self, name: &str) {
self.base.name = Some(name.to_string());
}
fn name(&self) -> Option<&str> {
self.base.name.as_deref()
}
}
#[derive(Debug, Clone)]
pub struct FloatField {
pub base: BaseField,
}
impl Default for FloatField {
fn default() -> Self {
Self::new()
}
}
impl FloatField {
pub fn new() -> Self {
Self {
base: BaseField::new(),
}
}
}
impl Field for FloatField {
fn deconstruct(&self) -> FieldDeconstruction {
FieldDeconstruction {
name: self.base.name.clone(),
path: "reinhardt.orm.models.FloatField".to_string(),
args: vec![],
kwargs: self.base.get_kwargs(),
}
}
fn set_attributes_from_name(&mut self, name: &str) {
self.base.name = Some(name.to_string());
}
fn name(&self) -> Option<&str> {
self.base.name.as_deref()
}
}
#[derive(Debug, Clone)]
pub struct TextField {
pub base: BaseField,
}
impl Default for TextField {
fn default() -> Self {
Self::new()
}
}
impl TextField {
pub fn new() -> Self {
Self {
base: BaseField::new(),
}
}
}
impl Field for TextField {
fn deconstruct(&self) -> FieldDeconstruction {
FieldDeconstruction {
name: self.base.name.clone(),
path: "reinhardt.orm.models.TextField".to_string(),
args: vec![],
kwargs: self.base.get_kwargs(),
}
}
fn set_attributes_from_name(&mut self, name: &str) {
self.base.name = Some(name.to_string());
}
fn name(&self) -> Option<&str> {
self.base.name.as_deref()
}
}
#[derive(Debug, Clone)]
pub struct TimeField {
pub base: BaseField,
pub auto_now: bool,
pub auto_now_add: bool,
}
impl Default for TimeField {
fn default() -> Self {
Self::new()
}
}
impl TimeField {
pub fn new() -> Self {
Self {
base: BaseField::new(),
auto_now: false,
auto_now_add: false,
}
}
pub fn with_auto_now() -> Self {
Self {
base: BaseField::new(),
auto_now: true,
auto_now_add: false,
}
}
pub fn with_auto_now_add() -> Self {
Self {
base: BaseField::new(),
auto_now: false,
auto_now_add: true,
}
}
}
impl Field for TimeField {
fn deconstruct(&self) -> FieldDeconstruction {
let mut kwargs = self.base.get_kwargs();
if self.auto_now {
kwargs.insert("auto_now".to_string(), FieldKwarg::Bool(true));
}
if self.auto_now_add {
kwargs.insert("auto_now_add".to_string(), FieldKwarg::Bool(true));
}
FieldDeconstruction {
name: self.base.name.clone(),
path: "reinhardt.orm.models.TimeField".to_string(),
args: vec![],
kwargs,
}
}
fn set_attributes_from_name(&mut self, name: &str) {
self.base.name = Some(name.to_string());
}
fn name(&self) -> Option<&str> {
self.base.name.as_deref()
}
}
#[derive(Debug, Clone)]
pub struct URLField {
pub base: BaseField,
pub max_length: u64,
}
impl Default for URLField {
fn default() -> Self {
Self::new()
}
}
impl URLField {
pub fn new() -> Self {
Self {
base: BaseField::new(),
max_length: 200, }
}
pub fn with_max_length(max_length: u64) -> Self {
Self {
base: BaseField::new(),
max_length,
}
}
}
impl Field for URLField {
fn deconstruct(&self) -> FieldDeconstruction {
let mut kwargs = self.base.get_kwargs();
if self.max_length != 200 {
kwargs.insert("max_length".to_string(), FieldKwarg::Uint(self.max_length));
}
FieldDeconstruction {
name: self.base.name.clone(),
path: "reinhardt.orm.models.URLField".to_string(),
args: vec![],
kwargs,
}
}
fn set_attributes_from_name(&mut self, name: &str) {
self.base.name = Some(name.to_string());
}
fn name(&self) -> Option<&str> {
self.base.name.as_deref()
}
}
#[derive(Debug, Clone)]
pub struct BinaryField {
pub base: BaseField,
}
impl Default for BinaryField {
fn default() -> Self {
Self::new()
}
}
impl BinaryField {
pub fn new() -> Self {
let mut base = BaseField::new();
base.editable = false; Self { base }
}
pub fn with_editable() -> Self {
let mut base = BaseField::new();
base.editable = true;
Self { base }
}
}
impl Field for BinaryField {
fn deconstruct(&self) -> FieldDeconstruction {
let mut kwargs = self.base.get_kwargs();
kwargs.remove("editable");
if self.base.editable {
kwargs.insert("editable".to_string(), FieldKwarg::Bool(true));
}
FieldDeconstruction {
name: self.base.name.clone(),
path: "reinhardt.orm.models.BinaryField".to_string(),
args: vec![],
kwargs,
}
}
fn set_attributes_from_name(&mut self, name: &str) {
self.base.name = Some(name.to_string());
}
fn name(&self) -> Option<&str> {
self.base.name.as_deref()
}
}
#[derive(Debug, Clone)]
pub struct SlugField {
pub base: BaseField,
pub max_length: u64,
pub db_index: bool,
}
impl Default for SlugField {
fn default() -> Self {
Self::new()
}
}
impl SlugField {
pub fn new() -> Self {
Self {
base: BaseField::new(),
max_length: 50, db_index: true, }
}
pub fn with_options(max_length: u64, db_index: bool) -> Self {
Self {
base: BaseField::new(),
max_length,
db_index,
}
}
}
impl Field for SlugField {
fn deconstruct(&self) -> FieldDeconstruction {
let mut kwargs = self.base.get_kwargs();
if self.max_length != 50 {
kwargs.insert("max_length".to_string(), FieldKwarg::Uint(self.max_length));
}
if !self.db_index {
kwargs.insert("db_index".to_string(), FieldKwarg::Bool(false));
}
FieldDeconstruction {
name: self.base.name.clone(),
path: "reinhardt.orm.models.SlugField".to_string(),
args: vec![],
kwargs,
}
}
fn set_attributes_from_name(&mut self, name: &str) {
self.base.name = Some(name.to_string());
}
fn name(&self) -> Option<&str> {
self.base.name.as_deref()
}
}
#[derive(Debug, Clone)]
pub struct SmallIntegerField {
pub base: BaseField,
}
impl Default for SmallIntegerField {
fn default() -> Self {
Self::new()
}
}
impl SmallIntegerField {
pub fn new() -> Self {
Self {
base: BaseField::new(),
}
}
}
impl Field for SmallIntegerField {
fn deconstruct(&self) -> FieldDeconstruction {
FieldDeconstruction {
name: self.base.name.clone(),
path: "reinhardt.orm.models.SmallIntegerField".to_string(),
args: vec![],
kwargs: self.base.get_kwargs(),
}
}
fn set_attributes_from_name(&mut self, name: &str) {
self.base.name = Some(name.to_string());
}
fn name(&self) -> Option<&str> {
self.base.name.as_deref()
}
}
#[derive(Debug, Clone)]
pub struct PositiveIntegerField {
pub base: BaseField,
}
impl Default for PositiveIntegerField {
fn default() -> Self {
Self::new()
}
}
impl PositiveIntegerField {
pub fn new() -> Self {
Self {
base: BaseField::new(),
}
}
}
impl Field for PositiveIntegerField {
fn deconstruct(&self) -> FieldDeconstruction {
FieldDeconstruction {
name: self.base.name.clone(),
path: "reinhardt.orm.models.PositiveIntegerField".to_string(),
args: vec![],
kwargs: self.base.get_kwargs(),
}
}
fn set_attributes_from_name(&mut self, name: &str) {
self.base.name = Some(name.to_string());
}
fn name(&self) -> Option<&str> {
self.base.name.as_deref()
}
}
#[derive(Debug, Clone)]
pub struct PositiveSmallIntegerField {
pub base: BaseField,
}
impl Default for PositiveSmallIntegerField {
fn default() -> Self {
Self::new()
}
}
impl PositiveSmallIntegerField {
pub fn new() -> Self {
Self {
base: BaseField::new(),
}
}
}
impl Field for PositiveSmallIntegerField {
fn deconstruct(&self) -> FieldDeconstruction {
FieldDeconstruction {
name: self.base.name.clone(),
path: "reinhardt.orm.models.PositiveSmallIntegerField".to_string(),
args: vec![],
kwargs: self.base.get_kwargs(),
}
}
fn set_attributes_from_name(&mut self, name: &str) {
self.base.name = Some(name.to_string());
}
fn name(&self) -> Option<&str> {
self.base.name.as_deref()
}
}
#[derive(Debug, Clone)]
pub struct PositiveBigIntegerField {
pub base: BaseField,
}
impl Default for PositiveBigIntegerField {
fn default() -> Self {
Self::new()
}
}
impl PositiveBigIntegerField {
pub fn new() -> Self {
Self {
base: BaseField::new(),
}
}
}
impl Field for PositiveBigIntegerField {
fn deconstruct(&self) -> FieldDeconstruction {
FieldDeconstruction {
name: self.base.name.clone(),
path: "reinhardt.orm.models.PositiveBigIntegerField".to_string(),
args: vec![],
kwargs: self.base.get_kwargs(),
}
}
fn set_attributes_from_name(&mut self, name: &str) {
self.base.name = Some(name.to_string());
}
fn name(&self) -> Option<&str> {
self.base.name.as_deref()
}
}
#[derive(Debug, Clone)]
pub struct GenericIPAddressField {
pub base: BaseField,
pub protocol: String, pub unpack_ipv4: bool,
}
impl Default for GenericIPAddressField {
fn default() -> Self {
Self::new()
}
}
impl GenericIPAddressField {
pub fn new() -> Self {
Self {
base: BaseField::new(),
protocol: "both".to_string(),
unpack_ipv4: false,
}
}
pub fn ipv4_only() -> Self {
Self {
base: BaseField::new(),
protocol: "IPv4".to_string(),
unpack_ipv4: false,
}
}
pub fn ipv6_only() -> Self {
Self {
base: BaseField::new(),
protocol: "IPv6".to_string(),
unpack_ipv4: false,
}
}
}
impl Field for GenericIPAddressField {
fn deconstruct(&self) -> FieldDeconstruction {
let mut kwargs = self.base.get_kwargs();
if self.protocol != "both" {
kwargs.insert(
"protocol".to_string(),
FieldKwarg::String(self.protocol.clone()),
);
}
if self.unpack_ipv4 {
kwargs.insert("unpack_ipv4".to_string(), FieldKwarg::Bool(true));
}
FieldDeconstruction {
name: self.base.name.clone(),
path: "reinhardt.orm.models.GenericIPAddressField".to_string(),
args: vec![],
kwargs,
}
}
fn set_attributes_from_name(&mut self, name: &str) {
self.base.name = Some(name.to_string());
}
fn name(&self) -> Option<&str> {
self.base.name.as_deref()
}
}
#[derive(Debug, Clone)]
pub struct FilePathField {
pub base: BaseField,
pub path: String,
pub match_pattern: Option<String>,
pub recursive: bool,
pub allow_files: bool,
pub allow_folders: bool,
pub max_length: u64,
}
impl FilePathField {
pub fn new(path: String) -> Self {
Self {
base: BaseField::new(),
path,
match_pattern: None,
recursive: false,
allow_files: true,
allow_folders: false,
max_length: 100,
}
}
}
impl Field for FilePathField {
fn deconstruct(&self) -> FieldDeconstruction {
let mut kwargs = self.base.get_kwargs();
kwargs.insert("path".to_string(), FieldKwarg::String(self.path.clone()));
if let Some(ref pattern) = self.match_pattern {
kwargs.insert("match".to_string(), FieldKwarg::String(pattern.clone()));
}
if self.recursive {
kwargs.insert("recursive".to_string(), FieldKwarg::Bool(true));
}
if !self.allow_files {
kwargs.insert("allow_files".to_string(), FieldKwarg::Bool(false));
}
if self.allow_folders {
kwargs.insert("allow_folders".to_string(), FieldKwarg::Bool(true));
}
if self.max_length != 100 {
kwargs.insert("max_length".to_string(), FieldKwarg::Uint(self.max_length));
}
FieldDeconstruction {
name: self.base.name.clone(),
path: "reinhardt.orm.models.FilePathField".to_string(),
args: vec![],
kwargs,
}
}
fn set_attributes_from_name(&mut self, name: &str) {
self.base.name = Some(name.to_string());
}
fn name(&self) -> Option<&str> {
self.base.name.as_deref()
}
}
#[derive(Debug, Clone)]
pub struct ForeignKey {
pub base: BaseField,
pub to: String, pub on_delete: String, pub related_name: Option<String>,
}
impl ForeignKey {
pub fn new(to: String, on_delete: String) -> Self {
Self {
base: BaseField::new(),
to,
on_delete,
related_name: None,
}
}
}
impl Field for ForeignKey {
fn deconstruct(&self) -> FieldDeconstruction {
let mut kwargs = self.base.get_kwargs();
kwargs.insert("to".to_string(), FieldKwarg::String(self.to.to_lowercase()));
kwargs.insert(
"on_delete".to_string(),
FieldKwarg::String(self.on_delete.clone()),
);
if let Some(ref name) = self.related_name {
kwargs.insert("related_name".to_string(), FieldKwarg::String(name.clone()));
}
FieldDeconstruction {
name: self.base.name.clone(),
path: "reinhardt.orm.models.ForeignKey".to_string(),
args: vec![],
kwargs,
}
}
fn set_attributes_from_name(&mut self, name: &str) {
self.base.name = Some(name.to_string());
}
fn name(&self) -> Option<&str> {
self.base.name.as_deref()
}
}
#[derive(Debug, Clone)]
pub struct OneToOneField {
pub base: BaseField,
pub to: String,
pub on_delete: String,
pub related_name: Option<String>,
}
impl OneToOneField {
pub fn new(to: String, on_delete: String) -> Self {
Self {
base: BaseField::new(),
to,
on_delete,
related_name: None,
}
}
}
impl Field for OneToOneField {
fn deconstruct(&self) -> FieldDeconstruction {
let mut kwargs = self.base.get_kwargs();
kwargs.insert("to".to_string(), FieldKwarg::String(self.to.to_lowercase()));
kwargs.insert(
"on_delete".to_string(),
FieldKwarg::String(self.on_delete.clone()),
);
if let Some(ref name) = self.related_name {
kwargs.insert("related_name".to_string(), FieldKwarg::String(name.clone()));
}
FieldDeconstruction {
name: self.base.name.clone(),
path: "reinhardt.orm.models.OneToOneField".to_string(),
args: vec![],
kwargs,
}
}
fn set_attributes_from_name(&mut self, name: &str) {
self.base.name = Some(name.to_string());
}
fn name(&self) -> Option<&str> {
self.base.name.as_deref()
}
}
#[derive(Debug, Clone)]
pub struct ManyToManyField {
pub base: BaseField,
pub to: String,
pub related_name: Option<String>,
pub through: Option<String>,
}
impl ManyToManyField {
pub fn new(to: String) -> Self {
Self {
base: BaseField::new(),
to,
related_name: None,
through: None,
}
}
pub fn with_related_name(to: String, related_name: String) -> Self {
Self {
base: BaseField::new(),
to,
related_name: Some(related_name),
through: None,
}
}
}
impl Field for ManyToManyField {
fn deconstruct(&self) -> FieldDeconstruction {
let mut kwargs = self.base.get_kwargs();
kwargs.insert("to".to_string(), FieldKwarg::String(self.to.to_lowercase()));
if let Some(ref name) = self.related_name {
kwargs.insert("related_name".to_string(), FieldKwarg::String(name.clone()));
}
if let Some(ref through) = self.through {
kwargs.insert("through".to_string(), FieldKwarg::String(through.clone()));
}
FieldDeconstruction {
name: self.base.name.clone(),
path: "reinhardt.orm.models.ManyToManyField".to_string(),
args: vec![],
kwargs,
}
}
fn set_attributes_from_name(&mut self, name: &str) {
self.base.name = Some(name.to_string());
}
fn name(&self) -> Option<&str> {
self.base.name.as_deref()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_auto_field_deconstruct() {
let mut field = AutoField::new();
field.set_attributes_from_name("id");
let dec = field.deconstruct();
assert_eq!(dec.name, Some("id".to_string()));
assert_eq!(dec.path, "reinhardt.orm.models.AutoField");
assert_eq!(dec.args.len(), 0);
assert_eq!(dec.kwargs.get("primary_key"), Some(&FieldKwarg::Bool(true)));
}
#[test]
fn test_big_integer_field_deconstruct() {
let field = BigIntegerField::new();
let dec = field.deconstruct();
assert_eq!(dec.path, "reinhardt.orm.models.BigIntegerField");
assert_eq!(dec.args.len(), 0);
assert!(dec.kwargs.is_empty());
}
#[test]
fn test_boolean_field_deconstruct() {
let field = BooleanField::new();
let dec = field.deconstruct();
assert_eq!(dec.path, "reinhardt.orm.models.BooleanField");
assert!(dec.kwargs.is_empty());
let field_with_default = BooleanField::with_default(true);
let dec2 = field_with_default.deconstruct();
assert_eq!(dec2.kwargs.get("default"), Some(&FieldKwarg::Bool(true)));
}
#[test]
fn test_char_field_deconstruct() {
let field = CharField::new(65);
let dec = field.deconstruct();
assert_eq!(dec.path, "reinhardt.orm.models.CharField");
assert_eq!(dec.kwargs.get("max_length"), Some(&FieldKwarg::Uint(65)));
let field2 = CharField::with_null_blank(65);
let dec2 = field2.deconstruct();
assert_eq!(dec2.kwargs.get("null"), Some(&FieldKwarg::Bool(true)));
assert_eq!(dec2.kwargs.get("blank"), Some(&FieldKwarg::Bool(true)));
}
#[test]
fn test_char_field_choices() {
let choices = vec![
("A".to_string(), "One".to_string()),
("B".to_string(), "Two".to_string()),
];
let field = CharField::with_choices(1, choices.clone());
let dec = field.deconstruct();
assert_eq!(
dec.kwargs.get("choices"),
Some(&FieldKwarg::Choices(choices))
);
assert_eq!(dec.kwargs.get("max_length"), Some(&FieldKwarg::Uint(1)));
}
#[test]
fn test_date_field_deconstruct() {
let field = DateField::new();
let dec = field.deconstruct();
assert_eq!(dec.path, "reinhardt.orm.models.DateField");
assert!(dec.kwargs.is_empty());
let field2 = DateField::with_auto_now();
let dec2 = field2.deconstruct();
assert_eq!(dec2.kwargs.get("auto_now"), Some(&FieldKwarg::Bool(true)));
}
#[test]
fn test_datetime_field_deconstruct() {
let field = DateTimeField::new();
let dec = field.deconstruct();
assert!(dec.kwargs.is_empty());
let field2 = DateTimeField::with_auto_now_add();
let dec2 = field2.deconstruct();
assert_eq!(
dec2.kwargs.get("auto_now_add"),
Some(&FieldKwarg::Bool(true))
);
let field3 = DateTimeField::with_both();
let dec3 = field3.deconstruct();
assert_eq!(dec3.kwargs.get("auto_now"), Some(&FieldKwarg::Bool(true)));
assert_eq!(
dec3.kwargs.get("auto_now_add"),
Some(&FieldKwarg::Bool(true))
);
}
#[test]
fn test_decimal_field_deconstruct() {
let field = DecimalField::new(5, 2);
let dec = field.deconstruct();
assert_eq!(dec.path, "reinhardt.orm.models.DecimalField");
assert_eq!(dec.kwargs.get("max_digits"), Some(&FieldKwarg::Uint(5)));
assert_eq!(dec.kwargs.get("decimal_places"), Some(&FieldKwarg::Uint(2)));
}
#[test]
fn test_email_field_deconstruct() {
let field = EmailField::new();
let dec = field.deconstruct();
assert_eq!(dec.path, "reinhardt.orm.models.EmailField");
assert_eq!(dec.kwargs.get("max_length"), Some(&FieldKwarg::Uint(254)));
let field2 = EmailField::with_max_length(255);
let dec2 = field2.deconstruct();
assert_eq!(dec2.kwargs.get("max_length"), Some(&FieldKwarg::Uint(255)));
}
}