Search code examples
djangodjango-modelsmany-to-manydjango-orm

Django usage of ManyToManyField between 2 different applications


Let's say we got 2 applications, games and streamers. Both applications got their own views, models, templates etc. In application streamers we got model Streamer

with field

games = models.ManyToManyField('games.Game')

and we are importing model Game from application games. Now after migrations, adding some content we can create object Streamer and assign to him games that he is playing. But when it comes to display all games that selected Streamer is playing by adding to template tag

{{ streamer.games }}

we are getting on template string

games.Game.None

so something causes it and we don't know yet what exactly. We have created views for games, streamers, templates, urls and everything works fine because we are getting data like streamer's nick, or streamer's links to YouTube/Twitch etc. but if we want in our Application streamers be allowed to display games assigned to streamers should we import views and models from streamers and games? Or should we change in app streamers/views.py any view and there place games imported from app games? I know how I could do this in single application with models and relation ManyToMany because I had already chance (with StackOverFlow help) to do something like this. But know I'm doing project (for learning) and I've decived to better to separate the single apps and I'm not sure how to do this. If the both models would be in 1 app and views would be written I could just use look like this

    {% for game in streamer.games.all %}
    {{ games.title }}
    {% endfor %}

but here is that problem for me because those are 2 different applications (I was reading that it's really better to seperate them, like good practive)

streamers/models.py

from django.db import models
from games.models import Game, Genre
from shots.utils import get_unique_slug
from django.utils import timezone

...

# model for streamer
class Streamer(models.Model):
    nick = models.CharField(max_length=30)
    twitch = models.CharField(max_length=70)
    games = models.ManyToManyField('games.Game')
        ...

streamers/views.py

from django.shortcuts import render, get_object_or_404, redirect
from .models import Streamer
from django.utils import timezone
from django.contrib.auth.decorators import login_required
from .forms import StreamerForm

...

# defining page for single streamer
def streamer_detail(request, slug):
    streamer = get_object_or_404(Streamer, slug=slug)
    return render(request, 'streamers/streamer_detail.html', {'streamer': streamer})
...

streamers/templates/streamer_detail.html

{% block content %}
    <div class="post">
        {% if streamer.published_date %}
            <div class="date">
                {{ streamer.published_date }}
            </div>
        {% endif %}
        {% if user.is_authenticated %}
        <a href="{% url 'streamer_edit' slug=streamer.slug %}">Edit streamer</a>
        {% endif %}
        <h2>{{ streamer.nick }}</h2>
        <a href="https://{{streamer.youtube}}">My YouTube Channel</a>
        <a href="https://{{ streamer.twitch }}">My Twitch Channel</a>
        <p>I'm streaming on {{ streamer.platform }}</p>
        Games that I'm playing
        {{ streamer.games }}
    </div>
{% endblock %}

games/models.py

from django.db import models
from django.utils import timezone
from shots.utils import get_unique_slug

# model for game
class Game(models.Model):
    title = models.CharField(max_length=70)
    genres = models.ManyToManyField('Genre', blank=True)
        ...
# model for genre
...

games/views.py

from django.shortcuts import render, get_object_or_404, redirect
from .models import Game
from django.utils import timezone
from django.contrib.auth.decorators import login_required
from .forms import GameForm

# defining page with newest games
...

# defining page for single games
def game_detail(request, slug):
    game = get_object_or_404(Game, slug=slug)
    return render(request, 'games/game.html', {'game': game})

...

Solution

  • Well, it looks like we don't have to import anything from views of 1 app to views of 2nd app. To access those querysets all what we need is to use correct loop, in my case there was 1 letter too much

    games.title

    so when I changed it to game.title everything works fine

        {% for game in streamer.games.all %}
        {{ game.title }}
        {% endfor %}