ReactPy-Django

repository·main·Indexed 18 days ago

https://github.com/reactive-python/reactpy-django

An integration package that enables the use of ReactPy, a Python-based UI library, within the Django framework. It allows developers to build reactive user interfaces using Python components, featuring SEO compatible rendering, client-side Python components via PyScript, and SPA capabilities. The library provides tools to embed components in Django templates via the {% component %} tag, convert Django views into components or iframes, and manage Django ORM queries within reactive components to avoid SynchronousOnlyOperation exceptions.

Tokens
28.9K
Snippets
112
Records
138
Agent score
62%

What's inside reactpy-django

  1. Overview of ReactPy-Django

    main

    ReactPy-Django is an integration package that adds ReactPy support to existing Django projects. It allows developers to build reactive user interfaces using Python components directly within the Django ecosystem.

    Key features include:

    • SEO compatible rendering: Prerendering components for search engines.
    • Client-Side Python components: Running Python logic in the browser via PyScript.
    • Single page application (SPA) capabilities: Using the Django router for SPA behavior.
    • Django Integrations: Converting Django views and forms into ReactPy components, and accessing Django static files and databases from within components.
    • Advanced ReactPy features: Distributed computing, multiple root components, and cross-process communication via channel layers.
  2. Use the PyScript tag for Python execution in HTML

    main

    The <pyscript> tag allows you to execute Python code directly within the browser using the PyScript interpreter. This serves as an alternative to using the #!python reactpy.html.script syntax.

    Note that this is a primitive HTML tag that is also leveraged by the reactpy_django.components.pyscript_component. The behavior of the <pyscript> tag is identical to HTML tags defined within #!python reactpy.html.

  3. Trigger data refreshes with `refetch` and `use_mutation`

    main

    You can synchronize your UI by linking mutations to queries:

    1. Manual Refetch: Call the refetch() method returned by a use_query hook to force a re-execution of that specific query.
    2. Automatic Refetch via Mutation: Pass the query function (or a list of functions) to the refetch parameter of use_mutation. When the mutation succeeds, the provided query functions will be automatically queued for re-execution.

    Note: When using refetch in use_mutation, it will cause all use_query hooks that use the specified query function in the current component tree to be refetched.

  4. Execute JavaScript within PyScript components

    main

    There are three primary ways to interact with JavaScript from within your Python components:

    1. Pyodide js module: Provides access to the browser's global JavaScript environment. Any global functions loaded in the HTML <head> can be called.
    2. PyScript Foreign Function Interface (FFI): Provides window and document modules for DOM interaction.
    3. PyScript JS Modules: Allows importing local JS bundles (stored in your static files) by configuring them in {% pyscript_setup %} and accessing them via pyscript.js_modules.*.
  5. Split large PyScript components into multiple files

    main

    Because PyScript components run in the browser, they cannot use standard Python import statements to load local files from your server.

    To organize large components, pass multiple file paths to the {% pyscript_component %} tag. ReactPy will automatically merge the contents of these files into a single execution context in the browser, allowing you to bypass the limitation of local imports while maintaining code organization.

    {# Merging multiple files into one component context #}
    {% pyscript_component "root.py" "child.py" %}
  6. How automatic ORM field fetching works

    main
    To prevent SynchronousOnlyOperation exceptions when accessing related fields within ReactPy components, reactpy-django provides a django_query_postprocessor. By default, this postprocessor enables automatic recursive fetching of ManyToManyField and ForeignKey fields. This ensures that related data is loaded during the initial query phase so it is available for use in your component logic without triggering synchronous IO errors.
  7. Set up a local interpreter for PyScript

    main

    To avoid downloading the Pyodide runtime from the internet every time, you can host a local interpreter in your project's static files:

    1. Download a Pyodide bundle (e.g., pyodide-0.26.3.tar.bz2) from the Pyodide GitHub releases.
    2. Extract the bundle into your project's static files directory.
    3. Configure {% pyscript_setup %} to use the local pyodide interpreter.
    {# Example configuration for a local interpreter #}
    {% pyscript_setup config="{'interpreter': 'pyodide', 'pyodide_path': '/static/pyodide/'}" %}
  8. Use Class Based Views with `view_to_iframe`

    main

    You can pass Django Class Based Views (CBVs) directly to view_to_iframe. While not strictly required, it is recommended to call .as_view() on the class to ensure compatibility.

    # Example usage for a Class Based View
    from reactpy_django import view_to_iframe
    from .views import MyClassBasedView
    
    def MyComponent():
        return view_to_iframe(MyClassBasedView.as_view())
  9. Load external CSS in ReactPy

    main

    The django_css component is strictly for local static files managed by Django. If you need to load an external stylesheet (e.g., from a CDN), use the standard reactpy.html.link component instead.

    from reactpy import html
    
    def MyComponent():
        # Use html.link for external URLs
        return html.div(
            html.link(rel="stylesheet", href="https://cdn.example.com/style.css"),
            "Content"
        )
  10. Configure Django Channels Layer for `use_channel_layer`

    main

    To use the use_channel_layer hook, you must configure Django Channels with a backend like Redis.

    1. Install redis on your system.
    2. Install channels-redis in your environment:
      pip install channels-redis
    3. Update settings.py with the CHANNEL_LAYERS configuration:
      CHANNEL_LAYERS = {
          "default": {
              "BACKEND": "channels_redis.core.RedisChannelLayer",
              "CONFIG": {
                  "hosts": [("127.0.0.1", 6379)],
              },
          },
      }
    CHANNEL_LAYERS = {
        "default": {
            "BACKEND": "channels_redis.core.RedisChannelLayer",
            "CONFIG": {
                "hosts": [("127.0.0.1", 6379)],
            },
        },
    }
  11. Render fallback content when user_passes_test fails

    main

    When using the user_passes_test decorator, you can control what the user sees if they do not meet the requirements of the test_func by using the fallback argument.

    There are two primary ways to provide fallback content:

    1. Render a different ReactPy component: Pass a component class or constructor to the fallback argument.
    2. Render a simple VDOM snippet: Pass a reactpy.html snippet directly to the fallback argument for lightweight feedback (e.g., a simple text message or error div).
    # Using a VDOM snippet as fallback
    @user_passes_test(test_func=is_staff, fallback=html.p("You do not have permission to view this."))
    class ProtectedComponent:
        def render(self):
            return html.div("Sensitive Data")
  12. Embed PyScript components in ReactPy

    main

    You can embed client-side PyScript components within traditional ReactPy components. This allows you to run Python code directly in the browser within your ReactPy application.

    Important Setup Requirement: You must call the {% pyscript_setup %} template tag in your Django template before using PyScript components to initialize PyScript on the client side.

    {% pyscript_setup %}