Как присоединиться к этим моделям Django? - PullRequest
0 голосов
/ 13 мая 2019

Как мне присоединиться к этим моделям Django, чтобы получить все модели Player, которые участвуют в задачах зарегистрированных пользователей (см. Переменную под названием challenge_participants в views.py? Я не нашел решения о том, как эффективно реализовать это с моделями Django . Большое спасибо!

Пример данных: Давайте предположим, что Джон вошел в систему. Как мы видим в модели PlayerChallenge, он является частью задачи 1 и 2. Я пытаюсь получить все объекты игрока, которые являются частью задачи 1 (Роджер в этом примере), и второй список для всех объектов игрока, которые являются частью вызова 2 (Роджер и Клод в этом примере).

Модель игрока

╔═══════════╦═════════╦════════════════╗
║ user_name ║ user_id ║ wallet_balance ║
╠═══════════╬═════════╬════════════════╣
║ John      ║     123 ║             20 ║
║ Roger     ║     231 ║             15 ║
║ Claude    ║     582 ║             10 ║
╚═══════════╩═════════╩════════════════╝

Модель вызова

╔════╦═════════╦══════╦════════╦═══════════════════╦══════════╦═══════════════════╦═══════════════╗
║ id ║ status  ║ type ║ amount ║ created_timestamp ║ duration ║ started_timestamp ║ end_timestamp ║
╠════╬═════════╬══════╬════════╬═══════════════════╬══════════╬═══════════════════╬═══════════════╣
║  1 ║ active  ║    1 ║     20 ║ TimeStamp         ║ 02:00:00 ║ TimeStamp         ║ TimeStamp     ║
║  2 ║ waiting ║    2 ║     30 ║ TimeStamp         ║ 04:00:00 ║ TimeStamp         ║ TimeStamp     ║
║  3 ║ waiting ║    1 ║     35 ║ TimeStamp         ║ 07:00:00 ║ TimeStamp         ║ TimeStamp     ║
╚════╩═════════╩══════╩════════╩═══════════════════╩══════════╩═══════════════════╩═══════════════╝

PlayerChallenge модель

╔════╦════════╦═══════════╦════════════════════╗
║ id ║ player ║ challenge ║ accepted_timestamp ║
╠════╬════════╬═══════════╬════════════════════╣
║  1 ║ John   ║         1 ║ TimeStamp          ║
║  2 ║ Roger  ║         1 ║ TimeStamp          ║
║  3 ║ Roger  ║         2 ║ TimeStamp          ║
║  4 ║ Claude ║         2 ║ TimeStamp          ║
║  5 ║ John   ║         2 ║ TimeStamp          ║
╚════╩════════╩═══════════╩════════════════════╝

Код:

models.py

from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.dispatch import receiver

# Create your models here.

class Player(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    #additional fields
    userid = models.CharField(max_length=256)
    wallet_balance = models.IntegerField(default=0)
    def __str__(self):
        return self.user.username

@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
    if created:
        Player.objects.create(user=instance)

@receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
    instance.player.save()


class Challenge(models.Model):
    id = models.IntegerField(primary_key=True, unique=True)
    status = models.CharField(max_length=20)
    type = models.CharField(max_length=20)
    amount = models.DecimalField(max_digits=10, decimal_places=2)
    created_timestamp = models.DateTimeField()
    duration = models.DurationField()
    started_timestamp = models.DateTimeField(null=True, blank=True)
    end_timestamp = models.DateTimeField(null=True, blank=True)

    def __str__(self):
        return str(self.id)

class PlayerChallenge(models.Model):
    user_challenge_id = models.IntegerField(primary_key=True, unique=True)
    player = models.ForeignKey(Player, on_delete=models.CASCADE)
    challenge = models.ForeignKey(Challenge, on_delete=models.CASCADE)
    accepted_timestamp = models.DateTimeField(null=True, blank=True)

    def __str__(self):
        return str(self.user_challenge_id) + " (Player: " + str(self.player.user.username) + ", Challenge: " + str(self.challenge.id) + ")"

views.py

from django.shortcuts import render
from django.http import HttpResponse

from django.contrib.auth import authenticate, login, logout
from django.http import HttpResponseRedirect, HttpResponse
from django.urls import reverse
from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import User

from challengeview.models import Player,Challenge,PlayerChallenge

@login_required
def index(request):

    challenges = Challenge.objects.filter(playerchallenge__player = request.user.player)
    challenges_participants = Player.objects.filter(playerchallenge__challenge = challenges)

    my_dict = {
     'challenges_participants' : challenges_participants,
     'challenges' : challenges,

    }
    return render(request, "challengeview/index.html", context=my_dict)

Большое спасибо за вашу поддержку!

1 Ответ

0 голосов
/ 13 мая 2019

В Django вы не можете моделировать отношения, как в простых SQL таблицах.Там 3 мощных типа отношений OnetoOne, ForeignKey, ManytoMany.из django.utils import timezone

class Player(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    #additional fields
    userid = models.CharField(max_length=256)
    wallet_balance = models.IntegerField(default=0)
    challenges = models.ManyToMany('Challenge') #a challenge can be belonged to many players in this case
    def __str__(self):
        return self.user.username

@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
    if created:
        Player.objects.create(user=instance)

@receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
    instance.player.save()


class Challenge(models.Model):
    status = models.CharField(max_length=20)
    type = models.CharField(max_length=20)
    amount = models.DecimalField(max_digits=10, decimal_places=2)
    duration = models.DurationField()
    started_timestamp = models.DateTimeField(null=True, blank=True)
    end_timestamp = models.DateTimeField(null=True, blank=True)
    created_timestamp = models.DateTimeField()

    def __str__(self):
        return str(self.id)


class PlayerActivity(models.Model):
    challenge = models.ForeingKey(on_delete=models.SET_NULL,
                                   null=True,
                                 related_name='activity_challenge')
    created_by = models.ForeignKey(Player,
                                   on_delete=models.SET_NULL,
                                   null=True,
                                 related_name='activity_created_by')

    created_at = models.DateTimeField(default=timezone.now)

    def __str__(self):
        return str(self.user_challenge_id) + " (Player: " + str(self.player.user.username) + ", Challenge: " + str(self.challenge.id) + ")"

Если вызов может принадлежать только одному игроку, но у игрока может быть много испытаний, тогда Foreignkey .Если у игрока может быть много вызовов, и вызов может принадлежать многим игрокам, то ManyToMany .

Когда вы используете запросы, вы всегда должны думать о запросе, отправленном на сервер.Вы можете использовать select_related, чтобы минимизировать запрос.

all_challenges = Challenge.objects.all()
logged_user_challenges = Player.objects.filter(user=request.user,challenges__in=all_challenges)
others_same_challenges = Player.objects.filter(challenges=logged_user_challenges.challenges)

ИЛИ

logged_user_challenges = PlayerActivity.objects.filter(user=request.user).latest('created_at')

Но у вас будет проблема с другими _... Вам понадобится цикл, чтобы получить все, и это просто не рекомендуется.

Примечание. Необходимо управлять сохранением данных в представлениях.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...