Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Context templatag #2

Merged
merged 9 commits into from
May 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .readthedocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,16 @@

# Required
version: 2
build:
os: ubuntu-20.04
tools:
python: "3.8"

# Build documentation in the docs/ directory with Sphinx
sphinx:
configuration: docs/conf.py

# Optionally set the version of Python and requirements required to build your docs
python:
version: 3.8
install:
- requirements: docs/requirements.txt
9 changes: 9 additions & 0 deletions docs/firm_info/exceptions.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
.. _intro_firm-info_exceptions:

==========
Exceptions
==========

.. automodule:: firm_info.exceptions
:members: SerializeFirmError
:exclude-members: MyAppBaseException
4 changes: 4 additions & 0 deletions docs/firm_info/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,7 @@ Django firm info
serializers.rst

templatetags.rst

exceptions.rst

managers.rst
9 changes: 9 additions & 0 deletions docs/firm_info/managers.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
.. _intro_firm-info_managers:

=======
Manager
=======

.. autoclass:: firm_info.managers.SingletonManager
:members:
:exclude-members: create
2 changes: 1 addition & 1 deletion docs/firm_info/serializers.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@ Serializers
===========

.. automodule:: firm_info.serializers
:members: SerializeFirmError, _format_address, serialize_firm_info, serialize_firm_social, serialize_firm_description, serialize_firm_social_sharing, serialize_firm_apps_banner
:members: _format_address, serialize_firm_info, serialize_firm_social, serialize_firm_description, serialize_firm_social_sharing, serialize_firm_apps_banner
:exclude-members: DoesNotExist, MultipleObjectsReturned
5 changes: 3 additions & 2 deletions firm_info/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ class MyAppBaseException(Exception):
pass


class DummyError(MyAppBaseException):
class SerializeFirmError(MyAppBaseException):
"""
Dummy exception sample to raise from your code.
Exceptions related to FirmContact serialization errors
during template tag generation.
"""
pass
32 changes: 31 additions & 1 deletion firm_info/factories.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import factory
from firm_info.models import Tracking

from .models import AppsBanner
from .models import AppsBanner, FirmContact


def create_image_file(filename=None, size=(100, 100), color="blue",
Expand Down Expand Up @@ -104,3 +104,33 @@ def image(self):
"""

return create_image_file()


class FirmContactFactory(factory.django.DjangoModelFactory):
"""
Factory to create instance of a FirmContact.
"""

phone_number = factory.Faker("phone_number")
email = factory.Faker("email")
address = factory.Faker("address")
postal_code = factory.Faker("postcode")
city = factory.Faker("city")
country = factory.Faker("country")
baseline = factory.Faker("text", max_nb_chars=255)
short_description = factory.Faker("text")

class Meta:
model = FirmContact

@factory.lazy_attribute
def logo(self):
return create_image_file()

@factory.lazy_attribute
def logo_invert(self):
return create_image_file()

@factory.lazy_attribute
def favicon(self):
return create_image_file()
11 changes: 11 additions & 0 deletions firm_info/managers.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,17 @@


class SingletonManager(models.Manager):
"""
A manager to ensure that only one instance of the model exists.

This manager overrides the `create` method to enforce a singleton pattern
on the associated model. If an instance of the model already exists,
attempting to create another instance will raise a `ValueError`.

Methods:
create(**kwargs): Creates a new instance of the model if none exists.
Raises `ValueError` if an instance already exists.
"""
def create(self, **kwargs):
if self.model.objects.exists():
error_message = _("Model {model_name} has already one instance")
Expand Down
3 changes: 1 addition & 2 deletions firm_info/serializers.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
class SerializeFirmError(Exception):
pass
from firm_info.exceptions import SerializeFirmError


def _format_address(firm_info: dict) -> str:
Expand Down
54 changes: 30 additions & 24 deletions firm_info/templatetags/firm_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
register = Library()


@register.simple_tag(name="firm_contact")
def firm_contact(template_path):
@register.simple_tag(takes_context=True, name="firm_contact")
def firm_contact(context, template_path):
"""
Renders the template which path is provided as param
using FirmContact only instance serialized contact data.
Expand All @@ -36,15 +36,16 @@ def firm_contact(template_path):
qs_firm_info = FirmContact.objects.all()
if qs_firm_info.exists():
template = loader.get_template(template_path)
context = serialize_firm_info(qs_firm_info)
rendered = template.render(context)
specific_context = serialize_firm_info(qs_firm_info)
combined_context = {**context.flatten(), **specific_context}
rendered = template.render(combined_context)
return rendered
else:
return ''


@register.simple_tag(name="firm_social_links")
def firm_social_links(template_path):
@register.simple_tag(takes_context=True, name="firm_social_links")
def firm_social_links(context, template_path):
"""
Renders the template which path is provided as param
using all social network link objects serialized data
Expand All @@ -67,15 +68,16 @@ def firm_social_links(template_path):
links = Link.objects.all()
if links.exists():
template = loader.get_template(template_path)
context = serialize_firm_social(links)
rendered = template.render(context)
specific_context = serialize_firm_social(links)
combined_context = {**context.flatten(), **specific_context}
rendered = template.render(combined_context)
return rendered
else:
return ''


@register.simple_tag(name="firm_description")
def firm_description(template_path):
@register.simple_tag(takes_context=True, name="firm_description")
def firm_description(context, template_path):
"""
Renders the template which path is provided as param
using FirmContact only instance serialized description data.
Expand All @@ -97,15 +99,16 @@ def firm_description(template_path):
qs_firm_info = FirmContact.objects.all()
if qs_firm_info.exists():
template = loader.get_template(template_path)
context = serialize_firm_description(qs_firm_info)
rendered = template.render(context)
specific_context = serialize_firm_description(qs_firm_info)
combined_context = {**context.flatten(), **specific_context}
rendered = template.render(combined_context)
return rendered
else:
return ''


@register.simple_tag(name="firm_logos")
def firm_logos(template_path):
@register.simple_tag(takes_context=True, name="firm_logos")
def firm_logos(context, template_path):
"""
Renders the firm logos using the specified template.

Expand All @@ -126,19 +129,20 @@ def firm_logos(template_path):
firm_instance = FirmContact.objects.first()
if firm_instance:
template = loader.get_template(template_path)
context = {
specific_context = {
"logo": getattr(firm_instance, "logo", None),
"logo_invert": getattr(firm_instance, "logo_invert", None),
"favicon": getattr(firm_instance, "favicon", None),
}
rendered = template.render(context)
combined_context = {**context.flatten(), **specific_context}
rendered = template.render(combined_context)
return rendered
else:
return ''


@register.simple_tag(name="firm_social_shares")
def firm_social_shares(template_path):
@register.simple_tag(takes_context=True, name="firm_social_shares")
def firm_social_shares(context, template_path):
"""
Renders the template which path is provided as param
using all social network shares link objects serialized data
Expand All @@ -162,8 +166,9 @@ def firm_social_shares(template_path):

if social_shares:
template = loader.get_template(template_path)
context = serialize_firm_social_sharing(social_shares)
rendered = template.render(context)
specific_context = serialize_firm_social_sharing(social_shares)
combined_context = {**context.flatten(), **specific_context}
rendered = template.render(combined_context)

return rendered
else:
Expand Down Expand Up @@ -193,8 +198,8 @@ def firm_tag_analytic(value=None):
return Tracking.objects.first().tag_analytic if Tracking.objects.exists() else ""


@register.simple_tag(name="app_banner")
def app_banner(app_type, template_path):
@register.simple_tag(takes_context=True, name="app_banner")
def app_banner(context, app_type, template_path):
"""
Renders the app banner using the specified template and application type.

Expand All @@ -218,7 +223,8 @@ def app_banner(app_type, template_path):

with contextlib.suppress(ObjectDoesNotExist):
app_banner = AppsBanner.objects.get(application_type=app_type)
context = serialize_firm_apps_banner(app_banner)
rendered = template.render(context)
specific_context = serialize_firm_apps_banner(app_banner)
combined_context = {**context.flatten(), **specific_context}
rendered = template.render(combined_context)

return rendered
15 changes: 15 additions & 0 deletions frozen.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Frozen requirement versions from '0.1.4' installation
Django==4.2.13
django-smart-media==0.3.1
djangocms-text-ckeditor==5.1.5
factory-boy==3.3.0
flake8==7.0.0
freezegun==1.5.1
livereload==2.6.3
pyquery==2.0.0
pytest==8.2.1
pytest-django==4.8.0
Sphinx==5.3.0
sphinx-rtd-theme==1.1.0
tox==4.15.0
twine==5.1.0
1 change: 1 addition & 0 deletions sandbox/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

SECRET_KEY = "***TOPSECRET***"

DEFAULT_AUTO_FIELD = "django.db.models.AutoField"

# Root of project repository
BASE_DIR = Path(__file__).parents[2]
Expand Down
5 changes: 3 additions & 2 deletions sandbox/settings/tests.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
"""
Django settings for tests
"""
from sandbox.settings.base import * # noqa: F403
# flake8: noqa: F403,F405
from sandbox.settings.base import *

DATABASES = {
"default": {
Expand All @@ -12,4 +13,4 @@

# Media directory dedicated to tests to avoid polluting other environment
# media directory
MEDIA_ROOT = VAR_PATH / "media-tests" # noqa: F405
MEDIA_ROOT = VAR_PATH / "media-tests"
12 changes: 7 additions & 5 deletions tests/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
from firm_info.models import FirmContact
from tests.utils import get_admin_add_url

from .constantes import RAW_CONTACT


User = get_user_model()

Expand All @@ -23,7 +25,7 @@ def admin_client(client, admin_user):
return client


def test_firm_contact_create(db, admin_client, raw_contact):
def test_firm_contact_create(db, admin_client):
# Check that admin client can access the admin interface
url = reverse("admin:index")
response = admin_client.get(url)
Expand All @@ -35,11 +37,11 @@ def test_firm_contact_create(db, admin_client, raw_contact):
assert response.status_code == 200

# needed for post in admin chg
raw_contact.update({
RAW_CONTACT.update({
"link_set-TOTAL_FORMS": 1,
"link_set-INITIAL_FORMS": 0
})
response = admin_client.post(url, raw_contact)
response = admin_client.post(url, RAW_CONTACT)
assert response.status_code == 302

# Check that the FirmContact instance was created
Expand All @@ -55,11 +57,11 @@ def test_firm_contact_create(db, admin_client, raw_contact):
)
assert qs_firm_contact_values is not None
assert all((
item in raw_contact.items()
item in RAW_CONTACT.items()
for item in qs_firm_contact_values[0].items()
))

# Check that the admin can't create another instance
response = admin_client.post(url, raw_contact)
response = admin_client.post(url, RAW_CONTACT)
assert response.status_code == 403
assert FirmContact.objects.filter().count() == 1
Loading
Loading