В Django CreateView используют метод класса для генерации данных, которые используются в get_context_data () и form_valid () - PullRequest
0 голосов
/ 07 января 2020

На самом деле я работаю над студенческим проектом, в котором я пытаюсь создать игру в жанре roguelike в сети, используя Python Django.

Я смущаюсь своей проблемой, чтобы объяснить, что мне нужно нужно создать случайные характеристики в создании персонажа, на которые влияет выбранный класс персонажей.

Я хочу отправить эти характеристики пользователю, прежде чем он начнет игру. И используйте характеристики, которые я посылаю ему в своем form_valid (), чтобы сохранить символ в дБ.

Я знаю, что могу использовать get_context_data (), чтобы отправить некоторую информацию в мой шаблон, но я не знаю, могу ли используйте данные, отправленные get_context_data () в шаблон в форме form_valid ().

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

models.py

class CharacterClass(models.Model):
    name = models.CharField(max_length=20,
                            blank=True,
                            null=True)
    minHpMax = models.PositiveIntegerField(default=10,
                                           validators=[MinValueValidator(10)],
                                           blank=False,
                                           null=False)
    minStrength = models.IntegerField(default=1,
                                      validators=[MinValueValidator(0)],
                                      blank=False,
                                      null=False)
    minAgility = models.IntegerField(default=1,
                                     validators=[MinValueValidator(0)],
                                     blank=False,
                                     null=False)
    minInt = models.IntegerField(default=1,
                                 validators=[MinValueValidator(0)],
                                 blank=False,
                                 null=False)
    minPhysResis = models.IntegerField(default=0,
                                       validators=[MinValueValidator(0)],
                                       blank=False,
                                       null=False)
    minMagRes = models.IntegerField(default=0,
                                    validators=[MinValueValidator(0)],
                                    blank=False,
                                    null=False)

    def __str__(self):
        return f'{self.id}: {self.name}'

    def generateHpMax(self):
        return random.randint(self.minHpMax, self.minHpMax + 10)

    def generateStrength(self):
        return random.randint(self.minStrength, self.minStrength + 10)

    def generateAgility(self):
        return random.randint(self.minAgility, self.minAgility + 10)

    def generateIntelligence(self):
        return random.randint(self.minInt, self.minInt + 10)

    def generatePR(self):
        return random.randint(self.minPhysResis, self.minPhysResis + 10)

    def generateMR(self):
        return random.randint(self.minMagRes, self.minMagRes + 10)


class Character(models.Model):
    name = models.CharField(max_length=20,
                            default='Jon Doe',
                            blank=False,
                            null=False)
    characterClass = models.ForeignKey(CharacterClass,
                                       on_delete=models.CASCADE,
                                       related_name='characterClass')
    level = models.PositiveIntegerField(default=1,
                                        validators=[MinValueValidator(1)],
                                        blank=False,
                                        null=False)
    hpMax = models.PositiveIntegerField(default=10,
                                        validators=[MinValueValidator(0)],
                                        blank=False,
                                        null=False)
    hp = models.PositiveIntegerField(default=10,
                                     validators=[MinValueValidator(0)],
                                     blank=False,
                                     null=False)
    strength = models.IntegerField(default=1,
                                   validators=[MinValueValidator(0)],
                                   blank=False,
                                   null=False)
    agility = models.IntegerField(default=1,
                                  validators=[MinValueValidator(0)],
                                  blank=False,
                                  null=False)
    intelligence = models.IntegerField(default=1,
                                       validators=[MinValueValidator(0)],
                                       blank=False,
                                       null=False)
    physicalResistance = models.IntegerField(default=0,
                                             validators=[
                                                 MinValueValidator(0)],
                                             blank=False,
                                             null=False)
    magicalResistance = models.IntegerField(default=0,
                                            validators=[
                                                MinValueValidator(0)],
                                            blank=False,
                                            null=False)
    inventory = models.OneToOneField('Inventory',
                                     on_delete=models.PROTECT)

    def __str__(self):
        return f'{self.id}: {self.name} ' \
               f'[Lvl: {self.level}' \
               f'|Class: {self.characterClass}' \
               f'|HpM: {self.hpMax}' \
               f'|hp: {self.hp}' \
               f'|Str: {self.strength}' \
               f'|Ag: {self.agility}' \
               f'|Int: {self.intelligence}' \
               f'|Pr: {self.physicalResistance}' \
               f'|Mr: {self.magicalResistance}]'

    def get_absolute_url(self):
        return reverse('characterDetail', kwargs={'pk': self.pk})

views.py

    class GenerateCharacterView(CreateView):
    model = Character
    form_class = CharacterForm
    template_name = 'characterForm.html'

    def form_valid(self, form):
        # Creation of Character without db saving
        self.object = form.save(commit=False)

        # creation of empty inventory unique for the Character
        inventory = Inventory()
        inventory.save()
        self.object.inventory = inventory

        pkCharacterClass= form['characterClass'].value()
        currentCharacterClass = get_object_or_404(CharacterClass,
                                                  pk=pkCharacterClass)

        # for a CharacterClass found, get random characteristics for the Character in creation
        generatedHpMax = currentCharacterClass.generateHpMax()
        self.object.hpMax = generatedHpMax
        self.object.hp = generatedHpMax

        generatedStrength = currentCharacterClass.generateStrength()
        self.object.strength = generatedStrength

        generatedAgility = currentCharacterClass.generateAgility()
        self.object.agility = generatedAgility

        generatedIntelligence = currentCharacterClass.generateIntelligence()
        self.object.intelligence = generatedIntelligence

        generatedPhysicalResistance = currentCharacterClass.generatePR()
        self.object.physicalResistance = generatedPhysicalResistance

        generatedMagicalResistance = currentCharacterClass.generateMR()
        self.object.magicalResistance = generatedMagicalResistance

        # Enregistrement en BDD de l'objet et appel du super form valid pour
        # renvoie de la succes url défini en Model
        self.object.save()
        return super().form_valid(form)

forms.py

    class CharacterForm(forms.ModelForm):
    class Meta:
        model = Character
        # exclude = []
        fields = ['name', 'characterClass']

    name = forms.CharField(max_length=20, widget=widgets.TextInput(
        attrs={'placeholder': 'Enter Your Name'}
    ))

urls.py

    urlpatterns = [
    path('admin/', admin.site.urls),
    path('', IndexView.as_view(), name='home'),
    path('generateCharacter',
         GenerateCharacterView.as_view(),
         name='generateCharacter'),
    path('characterDetail/<int:pk>', CharacterDetailView.as_view(),
         name='characterDetail'),
]

Вам уже удалось использовать этот вид использования? Знаете ли вы, если это работает? и как ? У вас были какие-нибудь советы или рекомендации для меня? Я работаю над ним 2 дня и схожу с ума.


Здравствуйте, извините за этот билет, я могу ошибиться в том, что я показываю в нем.

На данный момент я использую код, который я показываю в заявке, для преодоления моей проблемы.

В данный момент я могу генерировать персонажа со случайными характеристиками, выбирая CharacterClass и имя персонажа.

Но что я хочу сделать, это генерировать случайные характеристики, когда я захожу на страницу формы.

Поэтому я пытаюсь поместить на страницу кнопку, которая вызывает путь «createCharacter / 1», где «1» - это pk of Мой класс персонажей.

И я попытался сгенерировать характеристики radom в этот момент, чтобы показать пользователю характеристики перед отправкой формы.

И в форме только спросил имя персонажа ,

Так что это был код, который я использовал ранее

urls.py

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', IndexView.as_view(), name='home'),
    path('createCharacter/<int:characterClass>',
         CreateCharacterView.as_view(),
         name='createCharacter'),
    path('characterDetail/<int:pk>', CharacterDetailView.as_view(),
         name='characterDetail'),
]

views.py

class CreateCharacterView(CreateView):
    model = Character
    form_class = CharacterForm
    template_name = 'characterForm.html'

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        classCharacter = get_object_or_404(CharacterClass ,self.kwargs['characterClass'])
        context['randomCarac'] = classCharacter.getRadomCarac()
        return context 

    def form_valid(self, form):
        self.object = form.save(commit=False)


        inventory = Inventory()
        inventory.save()
        self.object.inventory = inventory


        self.object.characterClass= context['characterClass']
        self.object.hpMax = context['hpMax ']
        self.object.hp = context['hpMax ']
        self.object.strength = context['strength ']
        self.object.agility = context['agility ']
        self.object.intelligence = context['intelligence  ']
        self.object.physicalResistance = context['physicalResistance ']
        self.object.magicalResistance = context['magicalResistance ']

        self.object.save()
        return super().form_valid(form)

models.py

class CharacterClass(models.Model):
    name = models.CharField(max_length=20,
                            blank=True,
                            null=True)
    minHpMax = models.PositiveIntegerField(default=10,
                                           validators=[MinValueValidator(10)],
                                           blank=False,
                                           null=False)
    minStrength = models.IntegerField(default=1,
                                      validators=[MinValueValidator(0)],
                                      blank=False,
                                      null=False)
    minAgility = models.IntegerField(default=1,
                                     validators=[MinValueValidator(0)],
                                     blank=False,
                                     null=False)
    minInt = models.IntegerField(default=1,
                                 validators=[MinValueValidator(0)],
                                 blank=False,
                                 null=False)
    minPhysResis = models.IntegerField(default=0,
                                       validators=[MinValueValidator(0)],
                                       blank=False,
                                       null=False)
    minMagRes = models.IntegerField(default=0,
                                    validators=[MinValueValidator(0)],
                                    blank=False,
                                    null=False)

    def __str__(self):
        return f'{self.id}: {self.name}'

    def generateHpMax(self):
        return random.randint(self.minHpMax, self.minHpMax + 10)

    def generateStrength(self):
        return random.randint(self.minStrength, self.minStrength + 10)

    def generateAgility(self):
        return random.randint(self.minAgility, self.minAgility + 10)

    def generateIntelligence(self):
        return random.randint(self.minInt, self.minInt + 10)

    def generatePR(self):
        return random.randint(self.minPhysResis, self.minPhysResis + 10)

    def generateMR(self):
        return random.randint(self.minMagRes, self.minMagRes + 10)

    def getRadomCarac(self):
        return {'hpMax': self.generateHpMax(),
                'strength': self.generateStrength(),
                'agility': self.generateAgility(),
                'intelligence': self.generateIntelligence(),
                'physicalResistance': self.generatePR(),
                'magicalResistance': self.getRadomCarac()}


Это не работает. Кажется, у меня нет доступа к моему контексту ['что-то'] в form_validation ()

Так что я также попытался

class CreateCharacterView(CreateView):
    model = Character
    form_class = CharacterForm
    template_name = 'characterForm.html'
    classCharacter = get_object_or_404(CharacterClass ,self.kwargs['characterClass'])
    randomCarac = classCharacter.getRadomCarac()

def form_valid(self, form):
        # Do things here with randomCarac['something']

иметь значение 'global' в Вид для использования, когда я хочу, get_object_or_404 () не работает

Ответы [ 3 ]

1 голос
/ 09 января 2020

Хорошо, ребята, это последний код, который работает в моем проекте

url.py

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', IndexView.as_view(), name='home'),
    path('generateCharacterByPk/<int:pk>', GenerateCharacterView2.as_view(),
         name='generateCharacterByPk'),
    path('generateCharacter', GenerateCharacterView.as_view(),
         name='generateCharacter'),
    path('characterDetail/<int:pk>', CharacterDetailView.as_view(),
         name='characterDetail'),
]

forms.py

class CharacterForm2(forms.ModelForm):
    class Meta:
        model = Character
        # exclude = []
        fields = ['name']

    name = forms.CharField(max_length=20, widget=widgets.TextInput(
        attrs={'placeholder': 'Enter Your Name'}
    ))

views.py

class GenerateCharacterView2(CreateView):
    model = Character
    form_class = CharacterForm2
    template_name = 'characterForm.html'

    def get_context_data(self, **kwargs):
        result = super().get_context_data(**kwargs)
        result['title'] = 'Create Character'
        return result

    def get(self, *args, **kwargs):
        currentCharacterClass = get_object_or_404(CharacterClass,
                                                  pk=self.kwargs['pk'])

        self.request.session['characterClass'] = self.kwargs['pk']
        self.request.session['HpMax'] = currentCharacterClass.generateHpMax()
        self.request.session['Strength'] = currentCharacterClass.generateStrength()
        self.request.session['Agility'] = currentCharacterClass.generateAgility()
        self.request.session['Intelligence'] = currentCharacterClass.generateIntelligence()
        self.request.session['PhysicalResistance'] = currentCharacterClass.generatePR()
        self.request.session['MagicalResistance'] = currentCharacterClass.generateMR()
        return super().get(self)

    def form_valid(self, form):
        # Création de l'objet sans enregistrement en base
        self.object = form.save(commit=False)

        # Création d'un inventaire vide unique au personnage avec affectation et récupéraction de la classe du personnage
        currentCharacterClass = get_object_or_404(CharacterClass,
                                                  pk=self.request.session['characterClass'])
        inventory = Inventory()
        inventory.save()

        # Constitution du personnage
        self.object.inventory = inventory
        self.object.characterClass = currentCharacterClass
        self.object.hpMax = self.request.session['HpMax']
        self.object.hp = self.request.session['HpMax']
        self.object.strength = self.request.session['Strength']
        self.object.agility = self.request.session['Agility']
        self.object.intelligence = self.request.session['Intelligence']
        self.object.physicalResistance = self.request.session['PhysicalResistance']
        self.object.magicalResistance = self.request.session['MagicalResistance']

        # Création en BDD du personnage
        self.object.save()
        return super().form_valid(form)

символьная форма . html

{% extends 'base.html' %}

{% block page-top %}


    <form method="POST">
        {% csrf_token %}
        {% for field in form %}
            <div class="h5 font-weight-bold text-primary text-uppercase mb-1">
                <label>
                    {{ field.label }}:
                </label>
                <nav>
                    {{ field }}
                </nav>
            </div>
        {% endfor %}

        {{ request.session.characterClass }}
        {{ request.session.HpMax }}
        {{ request.session.Strength }}
        {{ request.session.Intelligence }}
        {{ request.session.Agility }}
        {{ request.session.PhysicalResistance }}
        {{ request.session.MagicalResistance }}
        <button type="submit">Valider</button>
    </form>


{% endblock %}

Спасибо @dirkgroten за вашу помощь, это было действительно полезно

0 голосов
/ 09 января 2020

Может что-то упустить в вашем решении, я пробовал решение 2, и я пишу код ниже

index. html

    <button>
        <a href="{% url 'generateCharacterByPk' 1 %}">Play2(pk=1)</a>
    </button>

    <button>
        <a href="{% url 'generateCharacterByPk' 2 %}">Play2(pk=2)</a>
    </button>

urls.py

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', IndexView.as_view(), name='home'),
    path('generateCharacterByPk/<int:pk>',
         GenerateCharacterView2.as_view(),
         name='generateCharacterByPk'),
    path('generateCharacter',
         GenerateCharacterView.as_view(),
         name='generateCharacter'),
    path('characterDetail/<int:pk>', CharacterDetailView.as_view(),
         name='characterDetail'),
]

forms.py

class CharacterForm2(forms.ModelForm):
    class Meta:
        model = Character
        # exclude = []
        fields = ['name']

    name = forms.CharField(max_length=20, widget=widgets.TextInput(
        attrs={'placeholder': 'Enter Your Name'}
    ))

views.py

class GenerateCharacterView2(CreateView):
    model = Character
    form_class = CharacterForm2
    template_name = 'characterForm.html'

    def get_context_data(self, **kwargs):
        result = super().get_context_data(**kwargs)
        result['title'] = 'Create Character'
        return result

    def get(self, request, *args, **kwargs):
        request.session.characterClass = self.kwargs['pk']
        currentCharacterClass = get_object_or_404(CharacterClass,
                                                  pk=self.kwargs['pk'])
        request.session.characterClass = currentCharacterClass
        request.session.HpMax = currentCharacterClass.generateHpMax()
        request.session.Strength = currentCharacterClass.generateStrength()
        request.session.Agility = currentCharacterClass.generateAgility()
        request.session.Intelligence = currentCharacterClass.generateIntelligence()
        request.session.PhysicalResistance = currentCharacterClass.generatePR()
        request.session.MagicalResistance = currentCharacterClass.generateMR()
        return render(request, 'characterForm.html')

    def form_valid(self, form):
        # Création de l'objet sans enregistrement en base
        self.object = form.save(commit=False)

        # Création d'un inventaire vide unique au personnage avec affectation
        inventory = Inventory()
        inventory.save()

        self.object.inventory = inventory
        self.object.hpMax = request.session.characterClass
        self.object.hpMax = request.session.HpMax
        self.object.hp = request.session.HpMax
        self.object.strength = request.session.Strength
        self.object.agility = request.session.Agility
        self.object.intelligence = request.session.Intelligence
        self.object.physicalResistance = request.session.PhysicalResistance
        self.object.magicalResistance = request.session.MagicalResistance

        self.object.save()
        return super().form_valid(form)

символьная форма. html

{% extends 'base.html' %}

{% block page-top %}


    <form method="POST">
        {% csrf_token %}
        {% for field in form %}
            <div class="h5 font-weight-bold text-primary text-uppercase mb-1">
                <label>
                    {{ field.label }}:
                </label>
                <nav>
                    {{ field }}
                </nav>
            </div>
        {% endfor %}

        {{ request.session.characterClass }}
        {{ request.session.HpMax }}
        {{ request.session.Strength }}
        {{ request.session.Intelligence }}
        {{ request.session.Agility }}
        {{ request.session.PhysicalResistance }}
        {{ request.session.MagicalResistance }}
        <button type="submit">Valider</button>
    </form>


{% endblock %}

И у меня возникает странная реакция, когда я получаю доступ к generateCharacterByPk / 1 или generateCharacterByPk / 2

Сначала я вижу случайные объекты, случайно сгенерированные при получении, на моей странице с помощью кнопки отправки.

Когда я нажимаю на страницу перезагрузки и получаю форму и кнопку отправки, но больше не вижу функций на своей странице.

И когда я проверяю форму, я получаю следующее ошибка:

AttributeError at /generateCharacterByPk/1
module 'django.http.request' has no attribute 'session'.
Request Method: POST
Request URL: http://127.0.0.1:8000/generateCharacterByPk/1
Django Version: 3.0.2
Exception Type: AttributeError
Exception Value:    
module 'django.http.request' has no attribute 'session'.
Exception Location: C:\Users\u049298\Desktop\PYTHON_DJANGO\projetWebRPG\app\views.py in form_valid, line 130
```
0 голосов
/ 08 января 2020

Если вы хотите создать случайный символ, когда форма отображается пользователю , и оставить этот случайный символ для сохранения, когда пользователь отправляет форму (имя символа), вам потребуется сохранить случайный символ каким-либо образом.

У вас есть несколько вариантов:

  1. Создание и сохранение символа уже при рендеринге формы первым время с запросом GET (с пустым именем) и включите идентификатор символа в форму как скрытое поле, чтобы при отправке формы вы обновляли символ с именем. Вы захотите проверить, что отправленный id принадлежит какому-либо «черновому» символу, чтобы быть уверенным, что пользователь не украдет другого уже существующего символа, поэтому вам может понадобиться добавить поле status в ваш Character модель. Вы бы не использовали CreateView здесь, но более подходящим было бы функциональное представление.

  2. Вы создаете значения для символа в методе get() вашего представления и сохраняете их в request.session (см. здесь ), чтобы вы могли извлечь указанные значения из сеанса в методе form_valid(). Этот метод кажется мне проще. Вы все еще можете использовать CreateView здесь. Вы можете отобразить их в своем шаблоне либо напрямую, используя {{ request.session.<somekey> }}, либо добавив их в свой контекст в get_context_data() в формате, который может быть легче отобразить в вашем шаблоне.

Отправка случайные значения через скрытые поля ввода формы не доступны, потому что любой может всегда подделать представленные значения.

Обратите внимание, что я не понимаю, почему ваша модель Character не имеет ссылки на User (ForeignKey или OneToOneField). Непонятно, как можно проверить, что персонаж принадлежит этому пользователю, и избежать того, чтобы пользователь украл чужого персонажа. Если вы добавите это, то в варианте 1 вам даже не нужно проверять id, поскольку request.user может иметь только один "черновик" Character.

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