GithubHelp home page GithubHelp logo

frojd / django-react-templatetags Goto Github PK

View Code? Open in Web Editor NEW
434.0 434.0 38.0 302 KB

A quick way to add React components to your Django templates.

License: MIT License

Python 96.28% HTML 1.68% Dockerfile 0.85% Shell 1.20%
django django-templates reactjs

django-react-templatetags's People

Contributors

aleehedl avatar ariamoradi avatar code-review-doctor avatar dependabot-preview[bot] avatar jproffitt avatar marteinn avatar martinjobb avatar mikaelengstrom avatar niespodd avatar robi-richter avatar ssteinerx avatar umairtw avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

django-react-templatetags's Issues

Issue with rendering React when using the browser back button

Hi there,

Firstly thanks for this project! It has enabled me to start shifting to start adding React to my codebase incrementally which is amazing!

Disclaimer: This issue could be down to the particular code base I am working on. It is using this library which looks to mess with the state of the back button (https://github.com/defunkt/jquery-pjax)

This issue can be reproduced as follows:

  1. Go to a page which uses this library
  2. Then navigate to another page
  3. Then use the browser back button
  4. If at this point you inspect the elements the uuid in the data/javascript is different from the uuid in the HTML id of the div where the React should render.

Screen recording: https://www.loom.com/share/5247e399ace045ee82d3744b009d6b1bx

Workaround: just use the identifier argument in the react_render template tag.

Guidance on inline React component?

Thanks for this really great library.

The example in the readme shows a "Menu" React component loaded into part of a larger template. But there isn't any guidance on creating this React component for specific use as an inline component in a Django app using django-react-templates.

The example app that is mentioned seems to be a full SPA-like React app built using react-sass-starterkit...unsure how that example fits into the inline component approach.

Do you have any guidance or suggestions for building something more like the "Menu" component? (e.g. create a separate Django app "components" in your project, setup webpack to compile from components/src/my_component.js to static, make sure not to include X, etc. etc.)

Probably very obvious to most but for a React newbie like me it's hard to discover the easiest way to write an inline (not SPA) React component for use with Django + django-react-templates.

For example, I'm not sure if using react-sass-starterkit is appropriate for an inline component like "Menu"...does it bake in extra js that django-react-template will itself provide? Any extra steps to properly integrate the result of a webpack build in react-sass-starterkit into the Django app?

Thanks for any suggestions.

Hypernova SSR not propagating errors correctly

This problem might be with hypernova-python plugin. The error gets stuck inside "results" and not at the base dictionary. Eventhough I get the response that everything is OK, the SSR failed.

This is a snippet of the JSON returned from https://github.com/ornj/hypernova-python/blob/master/hypernova/__init__.py#L79

{
  "success": True,
  "error": "None",
  "results": {
    "Components.App": {
      "name": "Components.App",
      "html": "None",
      "meta": {

      },
      "duration": 310.156114,
      "statusCode": 500,
      "success": False,
      "error": {
        "name
        ":"
        ReferenceError ",
        "message": "window is not defined",
        "stack": [
          "ReferenceError: window is not defined",
          "at useMediaQuery (/mnt/persist/www/signalisten/shared/ssr/frontend/ssr_frontend/utils/useMediaQ
          uery.js: 37: 25)
        ",
        ]
}

Option to change ReactTagManager

Hi,

I would like an option to use a custom ReactTagManager by setting it in Django settings:

REACT_TAG_MANAGER = 'myapp.MyCustomReactTagManager'

Do you think that would be possible?

Support React 15 out of the box?

I don't know if it's actually necessary since it's pretty easy to override react_print.html, but ReactDOM.hydrate is only available from React >= 16.

It would be fairly straight forward to support both though. Check if ReactDOM.hydrate is a function, if so use it - else use ReactDOM.render.

Or just mention it in the readme.

SSR request content_type not application/json

Hi,

I'm using this library with a custom Node backend for SSR. As this library sends json to the SSR backend it would be logical to set the Content-type header to application/json. This could be achiewed by setting the header manually like this:

headers = {'Content-type': 'application/json', 'Accept': 'text/plain'}
requests.post('http://httpbin.org/post', data='{"key": "value"}', headers=headers)

or by using the json keyword argument provided by requests like this:

requests.post('http://httpbin.org/post', json={"key": "value"})

Uncaught ReferenceError: Component is not defined

Hello!

Thank you for this fantastic library. I'm working on implementing it for a new project, and I'm running into an issue in the initial set up.

I've got the React and ReactDOM global imports working, but the script tag is throwing Uncaught ReferenceError: KnowledgeBase is not defined. I've looked through both examples but I can't figure out what I'm doing wrong.

How can I get this component accessible to the template? Am I exporting my components incorrectly?

Here's the code I'm using. We're building using webpack as well:

knowledge_base.html

{% block main %}
<noscript>You need to enable JavaScript to run this app.</noscript>

{% react_render component="KnowledgeBase" props=kb_home_data identifier="knowledgebase" %}

{% endblock main %}

{% block extra_js %}
    <script type="text/javascript" src="{{ WEBPACK_TEMPLATES_BUNDLE }}"></script>
    <script type="text/javascript" src="{{ WEBPACK_KB_BUNDLE }}"></script>
    {% react_print %}
{% endblock %}

knowledgebase/index.js

import KnowledgeBase from './KnowledgeBase';

export default {
  KnowledgeBase
}

knowledgebase/KnowledgeBase.js

import React, {Component} from "react";

export default class KnowledgeBase extends Component {
  constructor(props) {
    super(props);
  }

  render(){
    console.log(this.props);
    return <h1>KnowledgeBase</h1>;
  }

}

Thank you so much!

No module named requests

Somehow importing django_react_templatetags.context_processors.react_context_processor in settings.TEMPLATES throws a error that requests in not installed and the problem goes away if I install the requests library

here is what i got

(venv) D:\Desktop\django-es-modules-template-tags>python manage.py runserver
Watching for file changes with StatReloader
Performing system checks...

Exception in thread django-main-thread:
Traceback (most recent call last):
  File "D:\Desktop\django-es-modules-template-tags\venv\lib\site-packages\django\template\utils.py", line 66, in __getitem__
    return self._engines[alias]
KeyError: 'django'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "D:\Desktop\django-es-modules-template-tags\venv\lib\site-packages\django\template\backends\django.py", line 121, in get_package_libraries
    module = import_module(entry[1])
  File "C:\Python37\lib\importlib\__init__.py", line 127, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1006, in _gcd_import
  File "<frozen importlib._bootstrap>", line 983, in _find_and_load
  File "<frozen importlib._bootstrap>", line 967, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 677, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 728, in exec_module
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "D:\Desktop\django-es-modules-template-tags\venv\lib\site-packages\django_react_templatetags\templatetags\react.py", line 14, in <module>
    from django_react_templatetags.ssr import SSRService
  File "D:\Desktop\django-es-modules-template-tags\venv\lib\site-packages\django_react_templatetags\ssr.py", line 10, in <module>
    import requests
ModuleNotFoundError: No module named 'requests'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Python37\lib\threading.py", line 926, in _bootstrap_inner
    self.run()
  File "C:\Python37\lib\threading.py", line 870, in run
    self._target(*self._args, **self._kwargs)
  File "D:\Desktop\django-es-modules-template-tags\venv\lib\site-packages\django\utils\autoreload.py", line 53, in wrapper
    fn(*args, **kwargs)
  File "D:\Desktop\django-es-modules-template-tags\venv\lib\site-packages\django\core\management\commands\runserver.py", line 117, in inner_run
    self.check(display_num_errors=True)
  File "D:\Desktop\django-es-modules-template-tags\venv\lib\site-packages\django\core\management\base.py", line 395, in check
    include_deployment_checks=include_deployment_checks,
  File "D:\Desktop\django-es-modules-template-tags\venv\lib\site-packages\django\core\management\base.py", line 382, in _run_checks
    return checks.run_checks(**kwargs)
  File "D:\Desktop\django-es-modules-template-tags\venv\lib\site-packages\django\core\checks\registry.py", line 72, in run_checks
    new_errors = check(app_configs=app_configs)
  File "D:\Desktop\django-es-modules-template-tags\venv\lib\site-packages\django\contrib\admin\checks.py", line 76, in check_dependencies
    for engine in engines.all():
  File "D:\Desktop\django-es-modules-template-tags\venv\lib\site-packages\django\template\utils.py", line 90, in all
    return [self[alias] for alias in self]
  File "D:\Desktop\django-es-modules-template-tags\venv\lib\site-packages\django\template\utils.py", line 90, in <listcomp>
    return [self[alias] for alias in self]
  File "D:\Desktop\django-es-modules-template-tags\venv\lib\site-packages\django\template\utils.py", line 81, in __getitem__
    engine = engine_cls(params)
  File "D:\Desktop\django-es-modules-template-tags\venv\lib\site-packages\django\template\backends\django.py", line 25, in __init__
    options['libraries'] = self.get_templatetag_libraries(libraries)
  File "D:\Desktop\django-es-modules-template-tags\venv\lib\site-packages\django\template\backends\django.py", line 43, in get_templatetag_libraries
    libraries = get_installed_libraries()
  File "D:\Desktop\django-es-modules-template-tags\venv\lib\site-packages\django\template\backends\django.py", line 108, in get_installed_libraries
    for name in get_package_libraries(pkg):
  File "D:\Desktop\django-es-modules-template-tags\venv\lib\site-packages\django\template\backends\django.py", line 125, in get_package_libraries
    "trying to load '%s': %s" % (entry[1], e)
django.template.library.InvalidTemplateLibrary: Invalid template library specified. ImportError raised when trying to load 'django_react_templatetags.templatetags.react': No module named 'reque
sts'

Make the ReactMixin from the example available via this package.

Thanks for building this! It would be helpful if the ReactMixin from the example repo were available in this package. Documenting that would have made integrating this library a lot easier (for my use case at least).

Would a PR be welcomed that would do the following?:

  • Add ReactMixin as a class to be importable from django_react_templatetags
  • Update documentation to show how to use the ReactMixin in Class Based Views of an existing project

Add to_react_representation to RepresentationMixin

Today we get a lot of warnings when working with RepresentationMixin due to react_representation not being implemented. react_representation is deprecated and should be removed from mixin and replaced with to_react_representation.

ES modules import

I have been investigating the usage of es module imports for react components in the react template tags in order to not use a bundler in the front end tooling process. Here is where the idea came from: Building without bundling and I got a working example that I will post here in the next comment

Who is using this library?

Not really an issue, just wanted to start a thread for projects and companies using this library.

I found it super helpful for my own projects. And just want to help promote it.

I can start:

  • Panelbear: Privacy focused analytics service.

I actually mention the library in a blog post I just published describing the tech stack in case anyone is interested: https://panelbear.com/blog/tech-stack/

Thanks a lot for building this, it has saved me a lot of work.

Individual string props are set to null

I think the code speaks for itsself:

If I put this into a template

{% react_render component="Component" prop_country="Sweden" prop_city="Stockholm" prop_position=1 %}
{% react_print %}

It is rendered like that:

ReactDOM.render(
    React.createElement(Component,
        
            {"country": null, "city": null, "position": 1}
        ),
    document.getElementById('Component_5ec708c7a3474dbab0469f7fa02ad3d9')
);

Add support for x-disable-ssr header

If x-disable-ssr header is set and true then it should disable the serverside rendering for that request even if REACT_HOST is set

This is to be able to see how the page is rendered without the SSR for testing purposes

Uncaught ReferenceError: ReactDOM is not defined

I got this error( (index):14 Uncaught ReferenceError: ReactDOM is not defined ) in console while run this code snippet. i am using django 1.11.2. As i am beginner in ReactJS. please help me out.

Removing `react_context_processor` prevents components from being rendered

Our django application calls react_render in various templates to add react components to the page, and then calls react_print at the bottom of our main template.

If I remove the react_context_processor from our settings.py, as suggested by the deprecation warning, none of our components render. Adding the context processor back in results in them rendering correctly.

I believe this is caused by django's template variable scoping rules: https://docs.djangoproject.com/en/2.2/howto/custom-template-tags/#setting-a-variable-in-the-context
image

We call react_render in a different block than the one that contains the react_print, so removing the context processor results in react_print not seeing the list of components that was built up by the react_render calls.

Create Hypernova plugin to replace Hastur

The Rails community created their equivalent of django-react-templatetags which seems to be much better supported: https://github.com/airbnb/hypernova

Although DRTT works fine - it's fairly simple piece of code - the library provided as SSR backend "Hastur" looks a bit abandoned.

Does anyone use DRTT with Hypernova? Would it be worth integrating it? It looks like they have slightly different API integration on the react bridge.

Support for callbacks/literals

The current approach resolves template variables to a type, or fails. You cannot pass a literal, because the template tag forcibly passes json to the component tag.

This eliminates literally half of the "IO" functionality of React, by killing the "O" part. The only way React components can communicate with the outside world is by callback, and this behaviour is unsupported, because functions are not JSON-encodable.

I've looked through the documentation but see only mention of feeding data in, no capability for getting data back out via callback.

Is there something I'm missing, or is there no support for passing in callback functions so that React components can communicate back to the page they're hosted on?

Add Hypernova as alternative SSR service

The work to include Hypernova is ongoing, this issue precedes #40 and is meant to be a more transparent list of what needs to be done before we can release it.

  • Allow more complex data to be returned from SSR service (Most importantly so we can pass Hypernova id and key from service). Ref: a4c18f2
  • Include Hypernova id and key as return values from SSR service (Parse out Hypernova id and key from response html, additional SSR values are passed as params in the response dict). Ref: ace55f4
  • Add extra data from SSR back into the component object stored in queue (So we can, if we wish, use the Hypernova id/key in the react_print template). Ref: 34e13ef
  • Create tag attribute no_placeholder that disables the default DRTT wrapper and only uses the return value from SSR (since Hypernova includes its own div wrapper, our wrapper is redundant, depending on client side initialization method of course). Ref: e41208b
  • Add Hypernova support in the regular react_print.html partial. Ref: 0c8c890
  • Create a example project with Hypernova with DRTT to show implementation. Completed: https://github.com/marteinn/django-react-polls-with-hypernova-examples
  • (Nice to have) Measure code coverage
  • (Nice to have) Look into the double serialization of prop values in the Hypernova -> SSR bridge

Some tests misusing assertTrue for comparisons

assertTrue is not for comparing arguments, should use assertEqual for that.

The developer's intent of the test was to compare argument 1 with argument 2, which is not happening. Really what is happening is the test is passing because first argument is truthy. The correct method to use is assertEqual. more details

I found this issue automatically, see other issues here

render instead of hydrate if SSR turned off

Hey,

great work, thanks for the package.

I want to use it without SSR. The ReactDOM.hydrate call gives me the following warning in the browser console:

warning.js:33 Warning: Expected server HTML to contain a matching <div> in <div>.

While scanning through that issue on a (I guess comparable) rails package, I guessed using ReactDOM.render instead will solve the problem: reactjs/react-rails#842

And indeed, it did. I could fix it by overwriting react_print.html in my templates folder by:

<script>
    {% for component in components %}
        ReactDOM.hydrate(
            React.createElement({{ component.name }},
                {% if component.json %}
                    {{ component.json|safe }}
                {% else %}
                    null
                {% endif %}),
            document.getElementById('{{ component.identifier }}')
        );
    {% endfor %}
</script>

Would there be a simple way to automatically set it to ReactDOM.render, if SSR is not configured?

Cheers
Lars

ReactDOMServer as a SSR service

hey,
what are your thoughts on implementing a python bridge to call ReactDOMServer to make the html from inside of the template itself?

I'm thinking about something like this:

{% react_dom_server_render component="ComponentName" props=component_data %}

which will generate something like <h1 id="ComponentName_12344565689">The data was Hello World</h1>

and maybe create a tag for calling React.hydrate() with a tag similar to react_print:
{% react_dom_server_print %}

=====

I'm not sure what the performance of such a component will be but it eliminates the need for a seprate SSR engine.

When is the next release?

Hey there,

I was wondering when the next release would be published to pypi? There is useful SSR code currently in the develop branch (added like a month ago) that I don't believe is in v5.4.0 build.

Thank you!

XSS vulnerability: no escaping of HTML tags in rendered props

I couldn't find a non-public channel on which to communicate the security vulnerability. Here it goes:

Severity

High. The injected code could be executed on any page in which the malicious input is rendered and can affect any visitor, including site admins. This could allow attackers to hijack sessions, execute any Javascript on the browser of the visitor or even include their own HTML into the page.

Problem

Normally Django would take care of escaping HTML tags in templates when including model fields and other variables in the rendered template. But in this case, the React props are simply rendered as a JSON object in a script element.

Since the JSON inside the React.createElement(...) is not properly escaped, a malicious user is able to inject any custom HTML/Javascript into the rendered templates.

Simple example

  1. Create any model with fields that can be set by the user, for example: UserProfile(name: str, bio: str, ...)
  2. Let the user fill in the data as usual: could be Django form, React component, REST API, etc...
  3. Populate any React component using this library, passing any of those fields as a prop:
{% load react %}
<html>
    <head>...</head>

    <body>
            {% react_render component="UserProfileComponent" prop_name=user_profile.name %}
    </body>

    {% react_print %}
</html>
  1. If a user sets the name to be </script><script>alert('Foo')</script>, it will be rendered in the template as follows:
<html>
    <head>...</head>

    <body>
            <div id="UserProfileComponent_UUID"></div>
    </body>

    <script>
        ReactDOM.render(
            React.createElement(UserProfileComponent, {"name": "</script><script>alert('Foo')</script>"}),
            document.getElementById('UserProfileComponent_UUID')
        );
    </script>
</html>
  1. The first </script> ends the script element in which the React render snippet is placed, and executes the malicious code.

Proposed solution

I think that one of the following would prevent this vulnerability:

  1. Preferred: make use of Django's json_script to handle escaping of malicious code and render the JSON object into the template.
    https://docs.djangoproject.com/en/3.1/ref/templates/builtins/#json-script
<html>
    <head>...</head>

    <body>
            <div id="UserProfileComponent_UUID"></div>
    </body>

    <script id="UserProfileComponent_props_UUID" type="application/json">{"name": "\\u003C/script\\u003E..."}</script>

    <script>
        ReactDOM.render(
            React.createElement(UserProfileComponent, JSON.parse(document.getElementById('UserProfileComponent_props_UUID').textContent)),
            document.getElementById('UserProfileComponent_UUID')
        );
    </script>
</html>
  1. Base64 encode the stringified props JSON on render, and decode within the <script>...</script> element on the browser. For example:
<html>
    <head>...</head>

    <body>
            <div id="UserProfileComponent_UUID"></div>
    </body>

    <script>
        ReactDOM.render(
            React.createElement(UserProfileComponent, JSON.parse(atob("eyJuYW1lIjoiPC9zY3JpcHQ+PHNjcmlwdD5hbGVydCgnRm9vJyk8L3NjcmlwdD4ifQ=="))),
            document.getElementById('UserProfileComponent_UUID')
        );
    </script>
</html>
  1. Recursively escape the strings in the rendered JSON before rendering the props into the template.

Useful links

  1. https://docs.djangoproject.com/en/3.1/ref/templates/builtins/#json-script
  2. https://adamj.eu/tech/2020/02/18/safely-including-data-for-javascript-in-a-django-template/

Hypernova SSR Example Doesn't Work

I followed the Hypernova SSR example, but the webpages I receive are completely blank.

Tried to run the example directly, the following error occurs on the hypernova server:

Error [ERR_REQUIRE_ESM]: Must use import to load ES Module

Any idea why this could be?

Recommended development environment

Not a bug or problem with the project.

Is there a development environment that anyone would recommend for doing frontend development with django-react-templatetags?

Specifically, how do you go about developing react components and debugging them with the Django and Hypernova SSR setup?

Thanks

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.