0

I am currently doing projct that includes Django and React.

Post model in django

models.py

class PublishedManager(models.Manager):
    def get_queryset(self):
        return super(PublishedManager,
                     self).get_queryset()\
            .filter(status='published')

class Post(models.Model):
    STATUS = (
        ('project', 'Project'),
        ('published', 'Published'),
    )
    title = models.CharField(max_length=250)
    slug = models.SlugField(
        max_length=250, unique_for_date='publish')
    author = models.ForeignKey(
        User, on_delete=models.CASCADE, related_name='messages')
    body = models.TextField()
    publish = models.DateTimeField(default=timezone.now)
    created = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(auto_now=True)
    status = models.CharField(max_length=15, choices=STATUS, default='projekt')

    objects = models.Manager()
    published = PublishedManager()

    class Meta:
        ordering = ('-publish',)

    def __str__(self):
        return self.title

    def get_absolute_url(self):
        return reverse("frontend.views.post_detail",
                       kwargs={'year': self.publish.year,
                               'month': self.publish.month,
                               'day': self.publish.day,
                               'slug': self.publish.slug})

views.py

def post_list(request):
    posts = Post.published.all()
    serializer = PostSerializer(posts, many=True)
    json_data = json.dumps(serializer.data)
    return render(request, 'frontend/index.html', {'posts': json_data})


def post_detail(request, year, month, day, post):
    post = get_object_or_404(Post, slug=post,
                             status='published',
                             publish__year=year,
                             publish__month=month,
                             publish__day=day)
    return render(request,
                  'frontend/index.html',
                  {'post': post})

I want to get the 'posts' from post_list and 'post' from post_detail to index.html which is start point for React.

index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    [..]
    <script>
      const posts = {{ posts|safe }};
      const post = {{ post|safe }};
    </script>
    <link rel="stylesheet" href="{% static "css/style.css" %}" type="text/css">
  </head>
  <body>
      <div id="root"></div>
    <script src="{% static "frontend/main.js" %}"></script>

  </body>
</html>

The variables works perfectly fine when there's only one variable in script tag; what I mean is:

  • there's only one variable in script tag: const posts = {{ posts|safe }},
  • The code in react's component looks like {post.title} inside a paragraph,
  • I enter localhost:3000/posts/,
  • all posts from db are correctly displayed

The problem is, when I add another variable to the script tag (const post = {{ post|safe }}), it stops working, because the localhost:3000/posts/ no longer sees the post variable which is blank.

Also, I have hard time finding solution how to pass the get_absolute_url from model.py to work in a tag in react's components.

My final question is how to get this to work with multiple variables, i've already tried multiple times but nothing worked.

Raw output of '{{ posts|safe }}'

[
   {
      "id":2,
      "title":"wegew gqwr qw r",
      "slug":"wegew-gqwr-qw-r",
      "body":"wqg wqrg wqr qwwe gqwrg yh5rteh",
      "publish":"2021-11-07T17:46:57+03:00",
      "created":"2021-11-07T17:47:11.460183+03:00",
      "updated":"2021-11-07T17:47:11.460214+03:00",
      "status":"published",
      "author":1
   },
   {
      "id":1,
      "title":"dlaczego ja mam to pisac #2",
      "slug":"dlaczego-ja-mam-to-pisac-2",
      "body":"lorem lorem",
      "publish":"2021-11-07T13:18:38+03:00",
      "created":"2021-11-07T13:19:01.829642+03:00",
      "updated":"2021-11-07T17:46:04.150250+03:00",
      "status":"published",
      "author":1
   },
   {
      "id":3,
      "title":"post 3",
      "slug":"post-3",
      "body":"qwgr3qwgdrwdgf",
      "publish":"2021-10-06T19:09:22+03:00",
      "created":"2021-11-07T19:09:31.901192+03:00",
      "updated":"2021-11-07T19:10:02.729622+03:00",
      "status":"published",
      "author":1
   }
]

So it's an array, but the .map() function doesn't work.

After [posts].map()

Array(27) [ "[{\"id\": 2", " \"title\": \"wegew gqwr qw r\"", " \"slug\": \"wegew-gqwr-qw-r\"", " \"body\": \"wqg wqrg wqr qwwe gqwrg yh5rteh\"", " \"publish\": \"2021-11-07T17:46:57+03:00\"", " \"created\": \"2021-11-07T17:47:11.460183+03:00\"", " \"updated\": \"2021-11-07T17:47:11.460214+03:00\"", " \"status\": \"published\"", " \"author\": 1}", " {\"id\": 1", … ]
​
0: "[{\"id\": 2"
​
1: " \"title\": \"wegew gqwr qw r\""
​
2: " \"slug\": \"wegew-gqwr-qw-r\""
​
3: " \"body\": \"wqg wqrg wqr qwwe gqwrg yh5rteh\""
​
4: " \"publish\": \"2021-11-07T17:46:57+03:00\""
​
5: " \"created\": \"2021-11-07T17:47:11.460183+03:00\""
​
6: " \"updated\": \"2021-11-07T17:47:11.460214+03:00\""
​
7: " \"status\": \"published\""
​
8: " \"author\": 1}"
​
9: " {\"id\": 1"
​
10: " \"title\": \"dlaczego ja mam to pisac #2\""
​
11: " \"slug\": \"dlaczego-ja-mam-to-pisac-2\""
​
12: " \"body\": \"lorem lorem\""
​
13: " \"publish\": \"2021-11-07T13:18:38+03:00\""
​
14: " \"created\": \"2021-11-07T13:19:01.829642+03:00\""
​
15: " \"updated\": \"2021-11-07T17:46:04.150250+03:00\""
​
16: " \"status\": \"published\""
​
17: " \"author\": 1}"
​
18: " {\"id\": 3"
​
19: " \"title\": \"post 3\""
​
20: " \"slug\": \"post-3\""
​
21: " \"body\": \"qwgr3qwgdrwdgf\""
​
22: " \"publish\": \"2021-10-06T19:09:22+03:00\""
​
23: " \"created\": \"2021-11-07T19:09:31.901192+03:00\""
​
24: " \"updated\": \"2021-11-07T19:10:02.729622+03:00\""
​
25: " \"status\": \"published\""
​
26: " \"author\": 1}]"
​
length: 27

All right I figured out what needs to be done:

const posts = {{ posts|safe }}

posts.map((post, index) => 
    <p key={index}>{post.title}</p>
)}

to

const posts = '{{ posts|safe }}'

{JSON.parse(posts).map((post, index) => 
    <p key={index}>{post.title}</p>
)}
AUOI
  • 29
  • 1
  • 8
  • 1
    Can you try using quotes around the django variables: `const post = "{{ post|safe }}"`? See if this works. – xyres Nov 08 '21 at 16:47
  • Well, it kinda works but now I get an error `TypeError: posts.map is not a function` so posts aren't displayed and I don't know why, it returns the same array with objects in it. – AUOI Nov 08 '21 at 17:01
  • What was the error you were getting before? – xyres Nov 08 '21 at 17:37
  • `Uncaught SyntaxError: expected expression, got end of script` and it was because I was rendering page like `localhost:3000/posts/` to which data of all `Posts` were send, and I got the {{ posts|safe }} data, but on page `localhost:3000/post/2021/11/07/lorem-lorem/` the `posts` data wasn't there, only for the single `post`. – AUOI Nov 08 '21 at 17:49
  • 1
    I've answered a similar question about setting JS variables from Django: https://stackoverflow.com/a/43305140/1925257. If a context variable is a list or a dict and you want to use it in JS, you should first convert them to JSON data so that python specific keywords are translated to JS keywords (such as `True` to `true` and `None` to `null`, etc). – xyres Nov 08 '21 at 19:38
  • Thank You! It partly worked, but now that I use `'{{ posts|safe}}'` instead of `{{ posts|safe }}`, I can't use the posts.map function inside of the component as I wrote before. Error is `posts.map` is not a function. I've tried to put the `posts` into [ ], but it also didn't work. I have paste the raw output of the `'{{ posts|safe }}'` at the question's bottom – AUOI Nov 09 '21 at 10:47

0 Answers0