Django多次查看调用函数

2024-10-02 00:29:55 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在创建一个基于浏览器的RPG,其中战斗机制被构建到一个名为“战斗”的模型中。它根据一些公式在英雄、怪物和物品模型上执行动作。每个动作都会在“战斗日志”中添加一条消息。一个玩家可以以一种形式对另一个玩家或NPC发起战斗。提交表单时,它调用相同的视图,创建战斗对象,起草角色,运行游戏机制。你知道吗

出于某种原因,旧的“Battle”对象仍然在这些视图的运行之间被“选中”,只要它在同一个web会话中。因此,即使我创建了一个新对象,旧的作战日志也会转移到这个新对象。 我做错什么了?你知道吗

更新了更多内容

第一个对象中的fightlog字段是正确的。 第二个对象中的fightlog字段是第一个对象数据加上新数据。 第三次格斗是第一次加第二次加第三次,以此类推

你知道吗视图.py你知道吗

def battle_log(request):

    if request.session["last_battle"]:
        pk = request.session["last_battle"]
        b = Battletest.objects.get(pk=pk)
        battle_log = b.fightlog

        request.session["last_battle"] = ""
        context = { 'battle_log' : battle_log, }

        return render(request, 'battle.html', context)

    else:
        return redirect('/game/monster')

def fight_select_monster(request):
    form = SelectCharacter()
    if request.method=='POST':
        form = SelectCharacter(request.POST)
        if form.is_valid():
            b = Battletest.objects.create()
            b.draft(request.POST.get("character"))
            b.start_fight()
            b.round()
            b.eof()
            b.save()

            request.session["last_battle"] =  b.pk
            return redirect('/game/fight/')

    context = { 'form': form }
    request.session["last_battle"] = ""
    return render(request, 'fight.html', context)

你知道吗型号.py你知道吗

class Battletest(models.Model):
    messages = []
    fightlog = models.TextField()
    opponent = ""

    def draft(self, opponent):
        CHARACTERS= (
            (0, 'Confident Hacker'),
            (1, 'Confused Coder'),
        )
        self.opponent = CHARACTERS[int(opponent)][1]

    def start_fight(self):
        self.messages.append([0, "You joined the battle."])
        self.messages.append([0, self.opponent + "has appeared"])

    def round(self):
        # have character objects do stuff to eachother until
        # some edge case is met.
        self.messages.append([1, "You smack " + self.opponent + " in the face"])
        self.messages.append([1, self.opponent + " decides to leave this stupid fight"])

    def eof(self):
        self.messages.append([2, "The fight is over and noone wins"])
        self.fightlog = self.messages

你知道吗表单.py你知道吗

class SelectCharacter(forms.Form):

    CONFIDENTHACKER = 0
    CONFUSEDCODER = 1
    CHARACTERS= (
        (CONFIDENTHACKER, 'Confident Hacker'),
        (CONFUSEDCODER, 'Confused Coder'),
    )
    character = forms.ChoiceField(choices=CHARACTERS)

Tags: 对象selfformlogrequestsessiondeflast
1条回答
网友
1楼 · 发布于 2024-10-02 00:29:55

好的,你的问题是:

class Battletest(models.Model):
    messages = []
    opponent = ""

这将messagesopponent定义为属性 -属于类对象本身的属性,因此在类的所有实例之间共享,使它们实际上成为全局变量(因为类对象是单例的)。你知道吗

这里需要的是通过在初始值设定项中定义int使messages成为实例属性(这就是它的用途):

class Battletest(models.Model):
     fightlog = models.TextField()

     def __init__(self, *args, **kwargs):
         # let Model do it's own stuff !!!
         super(Battletest, self).__init__(*args, **kwargs) 

         # and add our ones:
         self.messages = []
         self.opponent = None

作为旁注:这样的错误通常是有人在没有先学习Python的基础知识的情况下“跳进”Django的标志,并且错误地认为因为Django模型使用class attribute来定义db字段,Python的类语法与Java或PHP相同,在Java或PHP中,您在类的顶层定义属性。但是that's not how Python works我强烈建议您现在停止一切,完成整个官方的Python教程—这将为您节省大量的时间和痛苦,真的。你知道吗

第二点注意:在服务器端web应用的上下文中,您希望在代码中避免任何类型的(可变的)全局状态。每一个可变的全局状态都应该存在于一些数据库您的模型、会话中,只要它在您的代码之外,并且可以在许多进程之间共享—因为在典型的生产设置中,您的应用程序将由许多不同的进程提供服务(是的,即使您有一个HTTP前端服务器,它通常也会管理一个池)django进程,请求将被任意分派到这些进程中的任何一个)。

现在,你有另一个问题:

def eof(self):
    # ...
    self.fightlog = self.messages

您将fightlog定义为一个文本字段,但要为其分配一个列表列表。保存的将是列表的文本表示,这不是很有用。你知道吗

理论上,这里的关系是一对多的关系(一个Battletest有很多消息),所以正确的关系设计应该是使用一个不同的Message模型,在Battletest-as shown in the tutorial上使用一个ForeignKey(你做了教程,是吗?)。你知道吗

现在,如果您真的坚持要对其进行反规范化,那么最好的(至少不那么糟糕)解决方案是在messages时间将json序列化为save(),然后在初始值设定项中将其反序列化回Python。这可以手动完成:

import json

class Battletest(models.Model):
     fightlog = models.TextField()

     def __init__(self, *args, **kwargs):
         # let Model do it's own stuff !!!
         super(Battletest, self).__init__(*args, **kwargs) 

         # and add our ones:
         if self.fightlog:
             self.messages = json.loads(self.fightlog)
         else:
             self.messages = []
         self.opponent = None

    # ...

    def save(self, *args, **kwargs):
        self.fightlog = json.dumps(self.messages)
        super(Battletest, self).save(*args, **kwargs)

或者使用JSONField(或多或少会自动处理这个问题),如果您的RDBMS支持的话。谷歌搜索“djangojsonfield”应该会提供一些提示。。。你知道吗

哦,是的。。。这里有重复的代码:

class Battletest(models.Model):

    # ...

    def draft(self, opponent):
        CHARACTERS= (
            (0, 'Confident Hacker'),
            (1, 'Confused Coder'),
        )
        self.opponent = CHARACTERS[int(opponent)][1]

在这里:

class SelectCharacter(forms.Form):

    CONFIDENTHACKER = 0
    CONFUSEDCODER = 1
    CHARACTERS= (
        (CONFIDENTHACKER, 'Confident Hacker'),
        (CONFUSEDCODER, 'Confused Coder'),
    )
    character = forms.ChoiceField(choices=CHARACTERS)

你想把这个因素考虑进去,这样你就有了一个单一的真理点:

class Battletest(models.Model):

        CONFIDENTHACKER = 0
        CONFUSEDCODER = 1
        CHARACTERS= [
            (CONFIDENTHACKER, 'Confident Hacker'),
            (CONFUSEDCODER, 'Confused Coder'),
        ]


    def draft(self, opponent):
        self.opponent = self.CHARACTERS[int(opponent)][1]

在你的表单.py地址:

from . models import Battletest

class SelectCharacter(forms.Form):
    character = forms.ChoiceField(choices=Battltest.CHARACTERS)

相关问题 更多 >

    热门问题