'
In the above example we specified the available image sources using the ``srcset`` parameter. We then used ``sizes`` to say:
- When the viewport is greater than ``1000px`` wide, the panda image will take up roughly half of the page width.
- When the viewport is less than ``1000px`` wide, the panda image will take up roughly full page width.
The default image ``src`` is what we specified using the ``url`` param. This is also what older browsers will fall back to
using. Modern browsers will instead pick the best source option from ``srcset`` (based on both the estimated image size and
screen resolution) to satisfy the condition met in ``sizes``.
.. note::
The value ``default`` in the second ``sizes`` entry above should be used when you want to omit a media query. This
makes it possible to provide a fallback size when no other media queries match.
Another example might be to serve a high resolution alternative for a fixed size image:
.. code-block:: python
resp_img(
url="img/panda.png",
srcset={
"img/panda-high-res.png": "2x"
}
)
This would output:
.. code-block:: html
Here we don't need a ``sizes`` attribute, since the panda image is fixed in size and small enough that it won't need to
resize along with the browser window. Instead the ``srcset`` image includes an alternate high resolution source URL, along
with a pixel density descriptor. This can then be used to say:
- When a browser specifies a device pixel ratio of ``2x`` or greater, use ``panda-high-res.png``.
- When a browser specifies a device pixel ration of less than ``2x``, use ``panda.png``.
The ``resp_img()`` helper also supports localized images by setting the ``'l10n'`` parameter to ``True```:
.. code-block:: python
resp_img(
url="img/panda-500.png",
srcset={
"img/panda-500.png": "500w",
"img/panda-750.png": "750w",
"img/panda-1000.png": "1000w"
},
sizes={
"(min-width: 1000px)": "calc(50vw - 200px)",
"default": "calc(100vw - 50px)"
},
optional_attributes={
"l10n": True
}
)
This would output (assuming ``de`` was your locale):
.. code-block:: html
'
Finally, you can also specify any other additional attributes you might need using ``optional_attributes``:
.. code-block:: python
resp_img(
url="img/panda-500.png",
srcset={
"img/panda-500.png": "500w",
"img/panda-750.png": "750w",
"img/panda-1000.png": "1000w"
},
sizes={
"(min-width: 1000px)": "calc(50vw - 200px)",
"default": "calc(100vw - 50px)"
},
optional_attributes={
"alt": "Red Panda",
"class": "panda-hero",
"height": "500",
"l10n": True,
"loading": "lazy",
"width": "500"
}
)
picture()
^^^^^^^^^
For `responsive images
The images referenced by ``l10n_img()`` must exist in ``media/img/l10n/``, so for above example, the images could include ``media/img/l10n/en-US/firefox/os/have-it-all/messages.jpg`` and ``media/img/l10n/es-ES/firefox/os/have-it-all/messages.jpg``.
qrcode()
^^^^^^^^
This is a helper function that will output SVG data for a QR Code at the spot in the template
where it is called. It caches the results to the ``data/qrcode_cache`` directory, so it only
generates the SVG data one time per data and box_size combination.
.. code-block:: python
qrcode("https://accounts.firefox.com", 30)
The first argument is the data you'd like to encode in the QR Code (usually a URL), and the second
is the "box size". It's a parameter that tells the generator how large to set the height and width
parameters on the XML SVG tag, the units of which are "mm". This can be overriden with CSS so you
may not need to use it at all. The ``box_size`` parameter is optional.
Using Large Assets
------------------
We don't want to (and if large enough GitHub won't let us) commit large files to the bedrock repo.
Files such as large PDFs or very-high-res JPG files (e.g. leadership team photos), or videos are not
well-tracked in git and will make every checkout after they're added slower and this diffs less useful.
So we have another domain at which we upload these files: assets.mozilla.net
This domain is simply an AWS S3 bucket with a CloudFront :abbr:`CDN (Content Delivery Network)` in front of it. It is highly available
and fast. We've made adding files to this domain very simple using `git-lfs This is the B variation of our test. Enjoy!
{% endif %} If you'd rather have a fully separate template for your test, you can use the ``template_name_variations`` argument to the view instead of ``template_context_variations``. .. code-block:: python # urls.py from django.urls import path from bedrock.utils.views import VariationTemplateView urlpatterns = [ path("testing/", VariationTemplateView.as_view(template_name="testing.html", template_name_variations=["1", "2"]), name="testing"), ] This will not provide any extra template context variables, but will instead look for alternate template names. If the URL is ``testing/?v=1``, it will use a template named ``testing-1.html``, if ``v=2`` it will use ``testing-2.html``, and for everything else it will use the default. It simply puts a dash and the variation value between the template file name and file extension. It is theoretically possible to use the template name and template context versions of this view together, but that would be an odd situation and potentially inappropriate for this utility. You can also limit your variations to certain locales. By default the variations will work for any localization of the page, but if you supply a list of locales to the ``variation_locales`` argument to the view then it will only set the variation context variable or alter the template name (depending on the options explained above) when requested at one of said locales. For example, the template name example above could be modified to only work for English or German like so .. code-block:: python # urls.py from django.urls import path from bedrock.utils.views import VariationTemplateView urlpatterns = [ path("testing/", VariationTemplateView.as_view(template_name="testing.html", template_name_variations=["1", "2"], variation_locales=["en-US", "de"]), name="testing"), ] Any request to the page in for example French would not use the alternate template even if a valid variation were given in the URL. .. note:: If you'd like to add this functionality to an existing Class-Based View, there is a mixin that implements this pattern that should work with most views: ``bedrock.utils.views.VariationMixin``. .. _geo-location: Geo Template View ~~~~~~~~~~~~~~~~~ Now that we have our :abbr:`CDN (Content Delivery Network)` configured properly, we can also just swap out templates per request country. This is very similar to the above, but it will simply use the proper template for the country from which the request originated. .. code-block:: python from bedrock.base.views import GeoTemplateView class CanadaIsSpecialView(GeoTemplateView): geo_template_names = { "CA": "mozorg/canada-is-special.html", } template_name = "mozorg/everywhere-else-is-also-good.html" For testing purposes while you're developing or on any deployment that is not accessed via the production domain (www.mozilla.org) you can append your URL with a ``geo`` query param (e.g. ``/firefox/?geo=DE``) and that will take precedence over the country from the request header. Other Geo Stuff ~~~~~~~~~~~~~~~ There are a couple of other tools at your disposal if you need to change things depending on the location of the user. You can use the ``bedrock.base.geo.get_country_from_request`` function in a view and it will return the country code for the request (either from the :abbr:`CDN (Content Delivery Network)` or the query param, just like above). .. code-block:: python from bedrock.base.geo import get_country_from_request def dude_view(request): country = get_country_from_request(request) if country == "US": # do a thing for the US else: # do the default thing The other convenience available is that the country code, either from the :abbr:`CDN (Content Delivery Network)` or the query param, is avilable in any template in the ``country_code`` variable. This allows you to change anything about how the template renders based on the location of the user. .. code-block:: jinja {% if country_code == "US" %}