post_model.py
The markata.plugins.post_model
plugin defines the core Post model used throughout
Markata. It provides robust validation, serialization, and configuration options for
all post attributes.
Installation
This plugin is built-in and enabled by default through the 'default' plugin. If you want to be explicit, you can add it to your list of plugins:
hooks = [ "markata.plugins.post_model", ]
Uninstallation
Since this plugin is included in the default plugin set, to disable it you must explicitly add it to the disabled_hooks list if you are using the 'default' plugin:
disabled_hooks = [ "markata.plugins.post_model", ]
Note: Disabling this plugin will break most of Markata's functionality as the Post model is fundamental to the system.
Configuration
Configure post model behavior in your markata.toml
:
[markata.post_model] # Attributes to include when serializing posts include = [ "date", "description", "published", "slug", "title", "content", "html" ] # Attributes to show in post representations repr_include = [ "date", "description", "published", "slug", "title" ] # Attributes to include when exporting export_include = [ "date", "description", "published", "slug", "title" ]
Functionality
Post Model
Core attributes:
path
: Path to source fileslug
: URL-friendly identifierhref
: Full URL pathpublished
: Publication statusdescription
: Post summarycontent
: Raw markdown contenthtml
: Rendered HTML contenttags
: List of post tagsdate
: Publication datetitle
: Post title
Validation
The model provides:
- Type checking and coercion
- Required field validation
- Custom field validators
- Default values
- Rich error messages
Serialization
Supports multiple output formats:
- Full serialization (all fields)
- Representation (subset for display)
- Export (subset for external use)
- JSON/YAML compatible
Performance
Uses optimized Pydantic config:
- Disabled assignment validation
- Arbitrary types allowed
- Extra fields allowed
- String whitespace stripping
- Default value validation
- Number to string coercion
- Alias population
Dependencies
This plugin depends on:
- pydantic for model definition
- rich for console output
- yaml for YAML handling
Class
PostModelConfig class
Configuration for the Post model
PostModelConfig source
class PostModelConfig(pydantic.BaseModel): """Configuration for the Post model""" def __init__(self, **data) -> None: """ include: post attributes to include by default in Post model serialization. repr_include: post attributes to include by default in Post repr. If `repr_include` is None, it will default to `include`, but it is likely that you want less in the repr than serialized output. example: ``` toml title='markata.toml' [markata.post_model] include = ['date', 'description', 'published', 'slug', 'title', 'content', 'html'] repr_include = ['date', 'description', 'published', 'slug', 'title'] ``` """ super().__init__(**data) default_date: datetime.date = datetime.date.today() include: List[str] = [ "date", "description", "published", "slug", "title", "content", "html", ] repr_include: Optional[List[str]] = [ "date", "description", "published", "slug", "title", ] export_include: Optional[List[str]] = [ "date", "description", "published", "slug", "title", ] model_config = ConfigDict( validate_assignment=True, # Config model arbitrary_types_allowed=True, extra="allow", str_strip_whitespace=True, validate_default=True, coerce_numbers_to_str=True, populate_by_name=True, ) @field_validator("repr_include", mode="before") @classmethod def repr_include_validator(cls, v, info) -> Optional[List[str]]: if v: return v return info.data.get("include")
Method
metadata method
for backwards compatability
metadata source
def metadata(self: "Post") -> Dict: "for backwards compatability" return self.__dict__
Method
to_dict method
for backwards compatability
to_dict source
def to_dict(self: "Post") -> Dict: "for backwards compatability" return self.__dict__
Method
__getitem__ method
for backwards compatability
getitem source
def __getitem__(self: "Post", item: str) -> Any: "for backwards compatability" return getattr(self, item)
Method
__setitem__ method
for backwards compatability
setitem source
def __setitem__(self: "Post", key: str, item: Any) -> None: "for backwards compatability" setattr(self, key, item)
Method
get method
for backwards compatability
get source
def get(self: "Post", item: str, default: Any) -> Any: "for backwards compatability" return getattr(self, item, default)
Method
keys method
for backwards compatability
keys source
def keys(self: "Post") -> List[str]: "for backwards compatability" return self.__dict__.keys()
Method
yaml method
dump model to yaml
yaml source
def yaml(self: "Post") -> str: """ dump model to yaml """ import yaml return yaml.dump( self.dict( include={i: True for i in self.markata.config.post_model.include} ), Dumper=yaml.CDumper, )
Method
markdown method
dump model to markdown
markdown source
def markdown(self: "Post") -> str: """ dump model to markdown """ import yaml frontmatter = yaml.dump( self.dict( include={ i: True for i in [ _i for _i in self.markata.config.post_model.include if _i != "content" ] } ), Dumper=yaml.CDumper, ) post = "---\n" post += frontmatter post += "---\n\n" if self.content: post += self.content return post
Method
dumps method
dumps raw article back out
dumps source
def dumps(self): """ dumps raw article back out """ return f"---\n{self.yaml()}\n\n---\n\n{self.content}"
Method
parse_date_time method
Single validator to handle all date_time parsing cases
parse_date_time source
def parse_date_time(cls, v, info): """Single validator to handle all date_time parsing cases""" # If we have an explicit date_time value if v is not None: if isinstance(v, datetime.datetime): return v if isinstance(v, datetime.date): return datetime.datetime.combine(v, datetime.time.min) if isinstance(v, str): try: # Try ISO format first return datetime.datetime.fromisoformat(v.replace("Z", "+00:00")) except ValueError: try: return datetime.datetime.strptime(v, "%Y-%m-%d %H:%M") except ValueError: try: return datetime.datetime.strptime(v, "%Y-%m-%d") except ValueError: # Try dateparser as last resort for explicit date_time import dateparser parsed = dateparser.parse(v) if parsed: return parsed return datetime.datetime.now() # Get the raw date string directly from raw_date field raw_date = info.data.get("raw_date") if raw_date and isinstance(raw_date, str): try: # Try ISO format first return datetime.datetime.fromisoformat(raw_date.replace("Z", "+00:00")) except ValueError: try: # Try parsing raw_date with time first return datetime.datetime.strptime(raw_date, "%Y-%m-%d %H:%M") except ValueError: try: # Fallback to date only return datetime.datetime.strptime(raw_date, "%Y-%m-%d") except ValueError: # Try dateparser as last resort import dateparser parsed = dateparser.parse(raw_date) if parsed: return parsed # If no raw_date, try to derive from date field date = info.data.get("date") if date: if isinstance(date, datetime.datetime): return date if isinstance(date, str): try: # Try ISO format first return datetime.datetime.fromisoformat(date.replace("Z", "+00:00")) except ValueError: try: # Try parsing date with time first return datetime.datetime.strptime(date, "%Y-%m-%d %H:%M") except ValueError: try: # Fallback to date only return datetime.datetime.strptime(date, "%Y-%m-%d") except ValueError: # Try dateparser as last resort import dateparser parsed = dateparser.parse(date) if parsed: return parsed if isinstance(date, datetime.date): return datetime.datetime.combine(date, datetime.time.min) # If we still don't have a date, use now return datetime.datetime.now()
Method
__init__ method
include: post attributes to include by default in Post
model serialization.
repr_include: post attributes to include by default in Post
repr. If repr_include
is None, it will default to
include
, but it is likely that you want less in the repr
than serialized output.
example:
markata.toml
[markata.post_model] include = ['date', 'description', 'published', 'slug', 'title', 'content', 'html'] repr_include = ['date', 'description', 'published', 'slug', 'title']
init source
def __init__(self, **data) -> None: """ include: post attributes to include by default in Post model serialization. repr_include: post attributes to include by default in Post repr. If `repr_include` is None, it will default to `include`, but it is likely that you want less in the repr than serialized output. example: ``` toml title='markata.toml' [markata.post_model] include = ['date', 'description', 'published', 'slug', 'title', 'content', 'html'] repr_include = ['date', 'description', 'published', 'slug', 'title'] ``` """ super().__init__(**data)