-
-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #16 from avixiii-dev/develop
Develop
- Loading branch information
Showing
10 changed files
with
352 additions
and
41 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
[pytest] | ||
DJANGO_SETTINGS_MODULE = seo_optimizer.settings | ||
DJANGO_SETTINGS_MODULE = tests.settings | ||
python_files = tests.py test_*.py *_tests.py | ||
addopts = --cov=seo_optimizer --cov-report=html --cov-report=term-missing -v |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,31 +2,11 @@ | |
Django SEO Optimizer - A powerful SEO optimization package | ||
Created by avixiii (https://avixiii.com) | ||
""" | ||
from typing import Type, TypeVar, Optional | ||
|
||
from django.apps import apps | ||
from django.conf import settings | ||
|
||
from .base import MetadataBase, register_metadata | ||
from .fields import MetadataField, KeywordsField, RobotsField, OpenGraphField | ||
from .models import setup | ||
from .version import VERSION | ||
|
||
__version__ = VERSION | ||
__author__ = "avixiii" | ||
__email__ = "[email protected]" | ||
__website__ = "https://avixiii.com" | ||
|
||
__all__ = [ | ||
"register_metadata", | ||
"MetadataField", | ||
"KeywordsField", | ||
"RobotsField", | ||
"OpenGraphField", | ||
"setup", | ||
] | ||
|
||
# Setup the application | ||
if apps.apps_ready and not hasattr(settings, "_SEO_OPTIMIZER_SETUP_DONE"): | ||
setup() | ||
settings._SEO_OPTIMIZER_SETUP_DONE = True | ||
default_app_config = 'seo_optimizer.apps.SEOOptimizerConfig' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
""" | ||
Custom exceptions for SEO Optimizer | ||
Created by avixiii (https://avixiii.com) | ||
""" | ||
|
||
class MetadataValidationError(Exception): | ||
"""Raised when metadata validation fails""" | ||
pass | ||
|
||
class MetadataNotFoundError(Exception): | ||
"""Raised when metadata is not found for a given path""" | ||
pass | ||
|
||
class InvalidMetadataError(Exception): | ||
"""Raised when metadata is invalid""" | ||
pass |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
""" | ||
Models for SEO Optimizer | ||
Created by avixiii (https://avixiii.com) | ||
""" | ||
from django.db import models | ||
from django.utils.translation import gettext_lazy as _ | ||
from django.apps import apps | ||
|
||
def setup(): | ||
"""Setup function called during Django initialization""" | ||
pass # We'll implement this later if needed | ||
|
||
class SEOMetadata(models.Model): | ||
"""Base model for SEO metadata""" | ||
path = models.CharField(_('Path'), max_length=255) | ||
site = models.ForeignKey('sites.Site', on_delete=models.CASCADE, related_name='seo_metadata') | ||
title = models.CharField(_('Title'), max_length=255, blank=True) | ||
description = models.TextField(_('Description'), blank=True) | ||
keywords = models.CharField(_('Keywords'), max_length=255, blank=True) | ||
robots = models.CharField(_('Robots'), max_length=255, blank=True) | ||
canonical_url = models.URLField(_('Canonical URL'), blank=True) | ||
og_title = models.CharField(_('Open Graph Title'), max_length=255, blank=True) | ||
og_description = models.TextField(_('Open Graph Description'), blank=True) | ||
og_image = models.URLField(_('Open Graph Image'), blank=True) | ||
created_at = models.DateTimeField(_('Created At'), auto_now_add=True) | ||
updated_at = models.DateTimeField(_('Updated At'), auto_now=True) | ||
|
||
class Meta: | ||
verbose_name = _('SEO Metadata') | ||
verbose_name_plural = _('SEO Metadata') | ||
unique_together = ('path', 'site') | ||
ordering = ('-updated_at',) | ||
|
||
def __str__(self): | ||
return f"{self.site.domain}{self.path}" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
""" | ||
Signal handlers for SEO Optimizer | ||
Created by avixiii (https://avixiii.com) | ||
""" | ||
from django.db.models.signals import post_save, post_delete | ||
from django.dispatch import receiver | ||
from django.contrib.sites.models import Site | ||
|
||
from .models import SEOMetadata | ||
|
||
@receiver(post_save, sender=Site) | ||
def handle_site_save(sender, instance, created, **kwargs): | ||
"""Handle Site model save signal""" | ||
# Add any site-related cleanup or cache invalidation here | ||
pass | ||
|
||
@receiver(post_delete, sender=Site) | ||
def handle_site_delete(sender, instance, **kwargs): | ||
"""Handle Site model delete signal""" | ||
# Add any site-related cleanup here | ||
pass | ||
|
||
@receiver(post_save, sender=SEOMetadata) | ||
def handle_metadata_save(sender, instance, created, **kwargs): | ||
"""Handle SEOMetadata model save signal""" | ||
# Add any metadata-related cache invalidation here | ||
pass | ||
|
||
@receiver(post_delete, sender=SEOMetadata) | ||
def handle_metadata_delete(sender, instance, **kwargs): | ||
"""Handle SEOMetadata model delete signal""" | ||
# Add any metadata-related cleanup here | ||
pass |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
""" | ||
Utility functions for SEO Optimizer | ||
Created by avixiii (https://avixiii.com) | ||
""" | ||
from typing import Any, TypeVar, Type, Optional | ||
|
||
T = TypeVar('T') | ||
|
||
class NotSet: | ||
"""Sentinel class for values that are not set""" | ||
pass | ||
|
||
class Literal: | ||
"""Class for literal values that should not be processed""" | ||
def __init__(self, value: Any): | ||
self.value = value | ||
|
||
def __str__(self) -> str: | ||
return str(self.value) | ||
|
||
def get_current_site(request) -> Optional[Any]: | ||
"""Get current site from request""" | ||
from django.contrib.sites.shortcuts import get_current_site | ||
try: | ||
return get_current_site(request) | ||
except Exception: | ||
return None | ||
|
||
def get_site_by_domain(domain: str) -> Optional[Any]: | ||
"""Get site by domain""" | ||
from django.contrib.sites.models import Site | ||
try: | ||
return Site.objects.get(domain=domain) | ||
except Site.DoesNotExist: | ||
return None |
Oops, something went wrong.