Django向导表单:是否可以为特定步骤使用搜索引擎?

2024-10-02 10:25:09 发布

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

我正在为我的Django应用程序苦苦挣扎,甚至要问我关于StackOverflow的第一个问题

简而言之,我有一个表单,用户(农民)允许他在培养基上添加植物

如果农场主不需要一个无聊的选择框,只需写下几个字母,所有相关的结果就会在屏幕上弹出,那就很方便了。农场主会捡起植物,继续下一步。因为他有330种不同的种子,这不仅仅是一个花哨的功能

我能够构建一个“简单”的向导表单,我已经有了搜索引擎,我的字段填充了modelcoocefield()。。。我觉得我离得太近了

我也认为WizardForm可能不是我所做的正确方法,但我觉得我只是错过了一些东西

你们有什么建议吗

下面,您可以阅读我的代码的一些摘录。我将尝试清理混乱,并为您提供一个可读的代码

models.py

'''
From the model, the only field that interests this question is the second one, id_graine (graine means seed).
'''

class Lot(models.Model):
    id = models.AutoField(primary_key = True)
    id_graine = models.ForeignKey('Graine', on_delete = models.PROTECT, related_name = 'id_graine', null = True, blank = True)
    nom_culture_incubation = models.ForeignKey('Culture', on_delete = models.PROTECT, related_name = 'nom_culture_incubation', null = True, blank = True)
    nom_culture = models.ForeignKey('Culture', on_delete = models.PROTECT, related_name = 'nom_culture', null = True, blank = True)
    etat_lot = models.CharField('état', choices = EtatLotsChoix.choices, max_length = 50, null = True, blank = True)
    quantite_lot = models.PositiveSmallIntegerField('quantité', null = True, blank = True)
    semis_date = models.DateField('date de semis', null = True, blank = True)
    phase_lunaire_semis = models.CharField('phase lunaire de semis', max_length = 4, blank = True)
    constellation_semis = models.CharField('constellations de semis', max_length = 7, blank = True)
    germination_date = models.DateField('date de germination', null = True, blank = True)
    plantaison_date = models.DateField('date de plantaison', null = True, blank = True)
    phase_lunaire_plantation = models.CharField('phase lunaire de plantation', choices = PhasesLunairesChoix.choices, max_length = 4, blank = True)
    constellation_plantation = models.CharField('constellations de plantation', choices = ConstellationChoix.choices, max_length = 7, blank = True)
    culture_introduction_date = models.DateField('date d\'introduction', null = True, blank = True)
    floraison_date = models.DateField('date de floraison', null = True, blank = True)
    recolte_date = models.DateField('date de récolte', null = True, blank = True)

    def __int__(self):
        return self.id

    class Meta:
        verbose_name = 'Lot'
        verbose_name_plural = 'Lots'
views.py

class AjoutLotWizard(SessionWizardView):
    template_name = 'wizardforms/ajout_lot_seme.html'

    def get_context_data(self, form, **kwargs):

        '''
        I told you that I was able to provide choices through a ModelChoiceField. But this approach 
        didn't pay off well. I also had a successful attempt by providing a context to the template
        with those informations.
        '''

        if self.request.GET.get('search_value') != None:

            search_value = self.request.GET.get('search_value')

            search_results = Graine.objects.filter(espece_graine__contains = search_value)

            context = super(AjoutLotWizard, self).get_context_data(form = form, **kwargs)

            if (self.steps.current == '0') & (self.request.GET.get('search_value') != None):
                context.update({'search_results': search_results})

                return context
            else:

                return context

在views.py中,我还尝试用get_form_kwargs()传递数据,get_form_step_data(),用自定义属性覆盖get()

使用get_form_kwargs的方法很有前途,因为一旦我能够将我的值存储在变量中,不幸的是,我无法在WizardView中按照我的意愿操作它们

forms.py

class AddLotSemeStep1(forms.ModelForm):

    '''
    This file might not be accurate. I did a mess on that part by rewriting __init__().
    But from what I remember, there wasn't more within the form when I use get_context_data
    to provide choices anyway with the template.
    '''

    class Meta:
        model = Lot
        fields = ['id_graine']
        labels = {
            'id_graine': 'Graine'
        }
        widgets = {
            'id_graine': forms.RadioSelect()
        }
template.html

{% load static %}
{% load i18n %}
{% block content %}
    {% include 'components/_base.html' %}
    <main class="wizard-form-main">
        <h2>Ajout de lot semé - le 1</h2>
        <p>Step {{ wizard.steps.step1 }} of {{ wizard.steps.count }}</p>

        <form action="" method="GET" name="searchbar">
            <input type="text" name="search_value">
            <button type="submit">Rechercher</button>
        </form>

        <form action = "" method = "POST" name="wizardform">
        {% csrf_token %}
            <table>
                {{ wizard.management_form }}
                {% if wizard.form %}
                    {{ wizard.form.management_form }}
                    {{ wizard.form }}
                {% else %}
                    {% for result in search_results %}
                        <p>
                            <label>
                                <input type="radio" name="chope_id" value="{{result.id}}">
                                {{result.espece_graine}} {{result.variete_graine}}, ({{result.provenance}} {{result.annee_de_recolte|cut:".0"}})
                            </label>
                            <input type="submit" value="Ajouter cette graine">
                        </p>
                    {% endfor %}
                {% endif %}
            </table>
            {% if wizard.steps.prev %}
            <!--<button name="wizard_goto_step" type="submit" value="{{ wizard.steps.first }}">{% trans "first step" %}</button>-->
            <button name="wizard_goto_step" type="submit" value="{{ wizard.steps.prev }}">{% trans "prev step" %}</button>
            {% endif %}
            <input type = "submit" value = "étape suivante">
        </form>
    </main>
{% endblock %}

感谢您的关注,如果您设法阅读了所有内容


Tags: nameformidtruesearchgetdatevalue
1条回答
网友
1楼 · 发布于 2024-10-02 10:25:09

你们好,那个浏览过这个页面的家伙。如果你也在寻找一个多页表单,它有一个特定的步骤,比如我的搜索栏,你可以这样做

我将把我的原始代码存放在这里。这应该已经有帮助了。一旦我的Django应用程序完成,我会花时间解释

views.py

def ajout_lot(request, nom_culture):

    # Initialization

    template_name = 'forms/ajout_lot.html'

    context = {

    }

    instance = Lot()
    model = Lot

    form_list = [AddLotStep1, AddLotStep2, AddLotStep3]

    fields = ['etat_lot', 'id_graine', 'quantite_lot', 'seme_date', 'plante_date', 'culture_introduction_date', 'phase_lunaire_seme', 'phase_lunaire_plante', 'constellation_seme', 'constellation_plante', 'nom_culture', 'nom_culture_incubation']

    form = {
        'step': 1,
        'count': len(form_list)
    }

    form.update({
        'form_fields': form_list[form['step'] -1]
    })

    context.update({'form': form})

    # Handling GET requests

    if request.GET.get('search_value') != None:

        search_value = request.GET.get('search_value')
        
        search_results = Graine.objects.filter(
            Q(espece_graine__contains = search_value) |
            Q(variete_graine__contains = search_value)
        )

        form.update({'step': 1})

        context.update({
            'form': form,
            'search_results': search_results
        })

    # Navigation throught steps

    if request.POST.get('next_step') != None:

        for field in fields:
            if request.POST.get(field) != None:
                request.session.update({field: request.POST.get(field)})
            else:
                pass

        form.update({
            'step': int(request.POST.get('next_step'))
        })

        form.update({
            'form_fields': form_list[form['step'] -1]()
        })

        context.update({'form': form})

    elif request.POST.get('previous_step') != None:

        form.update({
            'step': int(request.POST.get('previous_step'))
        })
        form.update({
            'form_fields': form_list[form['step'] -1]()
        })

        context.update({'form': form})

    # step 3
    if (request.POST.get('etat_lot') != None) and (len(request.POST) < 6):

        form_list[form['step'] -1] = AddLotStep3(request.POST or None, etat_lot = request.POST.get('etat_lot'))

        form.update({
            'form_fields': form_list[form['step'] -1],
            'step': 3
        })

        context.update({
            'form': form,
            'lunar_calendar': 'lunar_calendar'
        })

    # last step
    elif request.POST.get('confirmation_step') != None:

        for field in fields:
            if request.POST.get(field) != None:
                request.session.update({field: request.POST.get(field)})
            else:
                pass

        request.session.update({'nom_culture': nom_culture})

        # Now, every data from forms have been stored within request.session dictionnary.

        # Transfering data to a dictionnary, becausee it'd be bad practice to process data from there

        '''
        From data we have :
        - data_front that will display a summary of the form for the user
        - data_back that will save data in the database

        Once the user is satisfied with the summary, he can save data. Otherwise, he starts again from zero.
        '''

        data = {key: value for key, value in request.session.items() if key in fields}

        for key, value in data.items():
            if key == 'id_graine':
                data.update({key: Graine.objects.get(id = value)})
            elif key == 'nom_culture':
                data.update({key: Culture.objects.get(nom = value)})

        labels = []

        for datum in data:
            labels.append(getattr(model, datum).field.verbose_name)

        data_front = {label: value for label, value in zip(labels, data.values())}

        context.update({'data_front': data_front})

    elif request.POST.get('recommencer') != None:

        # Since we restart the form, we better have to clean request.session before

        for field in fields:
            try:
                del request.session[field]
            except KeyError:
                pass

        return redirect('ajout_lot', nom_culture = nom_culture)

    elif request.POST.get('sauvegarder') != None:

        data = {key: value for key, value in request.session.items() if key in fields}

        for key, value in data.items():
            if key == 'id_graine':
                data.update({key: Graine.objects.get(id = value)})
            elif (key == 'quantite_lot') and (value == ''):
                data.update({key: None})
            elif key == 'nom_culture':
                data.update({key: Culture.objects.get(nom = value)})
            elif (key.endswith('date')) and (key != None):
                data.update({key: dt.strptime(value, '%d-%m-%Y').strftime('%Y-%m-%d')})

        data_back = {}

        for key, value in data.items():
            if key == 'nom_culture':
                data_back.update({
                    key: value,   
                    'nom_culture_incubation': value
                })
            elif (key == 'seme_date') or (key == 'plante_date'):
                data_back.update({
                    key: value,
                    'culture_introduction_date': value
                })
            else:
                data_back.update({key: value})

        for key, value in data_back.items():
            setattr(instance, key, value)
        instance.save()

        # Once data are saved, we can clean request.session

        for field in fields:
            try:
                del request.session[field]
            except KeyError:
                pass
        
        context.update({
            'sauvegarder': 'sauvegarder',
            'nom_culture': nom_culture
        })

    return render(request, template_name, context)
forms.py

class AddLotStep1(forms.ModelForm):

    class Meta:
        model = Lot
        fields = ['id_graine']
        labels = {
            'id_graine': 'Choisissez la graine du lot'
        }

class AddLotStep2(forms.ModelForm):

    class Meta:
        model = Lot
        fields = ['quantite_lot']
        labels = {
            'quantite_lot': 'Indiquez la quantité'
        }
        widgets = {
            'quantite_lot': forms.TextInput
        }

class AddLotStep3(forms.Form):

    etat_lot = forms.ChoiceField(
        label = 'Le lot a-t-il été semé ou planté ?',
        choices = [
            ('Semé', 'Semé'),
            ('Planté', 'Planté')
        ],
        widget = forms.RadioSelect(),
        required = False
    )

    def __init__(self, *args, **kwargs):

        etat_lot = kwargs.pop('etat_lot', None)

        super(AddLotStep3, self).__init__(*args, **kwargs)

        if etat_lot == 'Semé':
            self.fields['seme_date'] = forms.DateField(
                label = 'Date de semaison',
                widget = DatePicker(),
                required = False
            )
            self.fields['phase_lunaire_seme'] = forms.ChoiceField(
                label = 'Phase lunaire',
                choices = PhasesLunairesChoix.choices,
                required = False
            )
            self.fields['constellation_seme'] = forms.ChoiceField(
                label = 'Constellation',
                choices = ConstellationChoix.choices,
                required = False
            )
        elif etat_lot == 'Planté':
            self.fields['plante_date'] = forms.DateField(
                label = 'Date de plantaison',
                widget = DatePicker(),
                required = False
            )
            self.fields['phase_lunaire_plante'] = forms.ChoiceField(
                label = 'Phase lunaire',
                choices = PhasesLunairesChoix.choices,
                required = False
            )
            self.fields['constellation_plante'] = forms.ChoiceField(
                label = 'Constellation',
                choices = ConstellationChoix.choices,
                required = False
            )
app/urls.py

path('etat_jardin/<str:nom_culture>/ajout_lot', views.ajout_lot, name = 'ajout_lot')
template

{% block base %}
    {% include 'components/_base.html' %}
{% endblock %}

{% block content %}
    {% if sauvegarder %}
        <p>Les données ont bien été sauvegardées</p>
        <a href="{% url 'ajout_lot' nom_culture %}">Ajouter un nouveau lot</a>
        <a href="{% url 'etat_jardin_detail' nom_culture %}">Revenir à {{nom_culture}}</a>
    {% elif data_front %}
        <p>Récapitulatif</p>
        {% for label, value in data_front.items %}
            {% if label == "Graine" %}
                <p>{{label}} : {{value.espece_graine}} {{value.variete_graine}}</p>
            {% else %}
                <p>{{label}} : {{value|default:"Aucune données enregistrées"}}</p>
            {% endif %}
        {% endfor %}
        <form action="" method="POST">{% csrf_token %}
            <button name="recommencer" type="submit">Je me suis trompé, recommencer</button>
            <button name="sauvegarder" type="submit">Je confirme le lot, sauvegarder</button>
        </form>
    {% elif form %}
        {% if form.step == 1 %}
            <p>Étape {{ form.step }}/{{ form.count }}</p>
            <p>Choisissez la graine du lot</p>
            <form action="" method="GET" name="barre de recherche">
                <input type="text" name="search_value">
                <button type="submit" value="1">Valider</button>
            </form>
            <form action="" method="POST">{% csrf_token %}
                {% for result in search_results %}
                    <p>
                        <label>
                            <input type="radio" name="id_graine" value="{{result.id}}">
                            {{result.espece_graine}} {{result.variete_graine}}, ({{result.provenance}} {{result.annee_de_recolte|cut:".0"}})
                        </label>
                    </p>
                {% endfor %}
                <button name="next_step" type="submit" value="{{ form.step|add:'1' }}">Suivant</button>
            </form>
        {% elif form.step == form.count %}
            <p>Étape {{ form.step }}/{{ form.count }}</p>
            {% if lunar_calendar %}
                {% include 'components/_lunarCalendar.html' %}
            {% endif %}
            <form action="" method="POST">{% csrf_token %}
                {{ form.form_fields }}
                <button name="previous_step" type="submit" value="{{ form.step|add:'-1' }}">Précédent</button>
                <button name="confirmation_step" type="submit">Résumer</button>
            </form>
        {% else %}
            <p>Étape {{ form.step }}/{{ form.count }}</p>
            <form action="" method="POST">{% csrf_token %}
                {{ form.form_fields }}
                <button name="previous_step" type="submit" value="{{ form.step|add:'-1' }}">Précédent</button>
                <button name="next_step" type="submit" value="{{ form.step|add:'1' }}">Suivant</button>
            </form>
        {% endif %}
    {% endif %}
{% endblock %}

相关问题 更多 >

    热门问题