【问题标题】:Django - Update one field after form submittingDjango - 提交表单后更新一个字段
【发布时间】:2017-08-17 11:45:03
【问题描述】:

我正在寻找在用户提交后更新我的 Django 表单。 我用一些数据填写了我的BirthCertificateForm,但我只有一个未填写的字段:social_number

为什么?因为提交表单后,我从数据表单中创建了一个唯一的社交号码。所以,我想更新我之前的表格,根据好字段添加这个社交号并验证它。

我的 models.py 文件如下所示:

class BirthCertificate(models.Model):

    lastname = models.CharField(max_length=30, null=False, verbose_name='Nom de famille')
    firstname = models.CharField(max_length=30, null=False, verbose_name='Prénom(s)')
    sex = models.CharField(max_length=8, choices=SEX_CHOICES, verbose_name='Sexe')
    birthday = models.DateField(null=False, verbose_name='Date de naissance')
    birthhour = models.TimeField(null=True, verbose_name='Heure de naissance')
    birthcity = models.CharField(max_length=30, null=False, verbose_name='Ville de naissance')
    birthcountry = CountryField(blank_label='Sélectionner un pays', verbose_name='Pays de naissance')
    fk_parent1 = models.ForeignKey(Person, related_name='ID_Parent1', verbose_name='ID parent1', null=False)
    fk_parent2 = models.ForeignKey(Person, related_name='ID_Parent2', verbose_name='ID parent2', null=False)
    mairie = models.CharField(max_length=30, null=False, verbose_name='Mairie')
    social_number = models.CharField(max_length=30, null=True, verbose_name='numero social')
    created = models.DateTimeField(auto_now_add=True)

而我的 views.py 文件有 2 个功能:

第一个功能:

# First function which let to fill the form with some conditions / restrictions

@login_required
def BirthCertificate_Form(request) :
    # Fonction permettant de créer le formulaire Acte de Naissance et le remplissage


    query_lastname_father = request.GET.get('lastname_father')
    query_lastname_mother = request.GET.get('lastname_mother')

    if request.method == 'POST':

        form = BirthCertificateForm(request.POST or None)

        if form.is_valid() :   # Vérification sur la validité des données
            post = form.save()
            return HttpResponseRedirect(reverse('BC_treated', kwargs={'id': post.id}))

    else:
        form = BirthCertificateForm()


        parent1 = Person.objects.filter(lastname=query_lastname_father)
        parent2 = Person.objects.filter(lastname=query_lastname_mother)

        form = BirthCertificateForm(request.POST or None)
        form.fields['fk_parent1'].queryset = parent1.filter(sex="Masculin")
        form.fields['fk_parent2'].queryset = parent2.filter(sex="Feminin")

    context = {
        "form" : form,
        "query_lastname" : query_lastname_father,
        "query_lastname_mother" : query_lastname_mother,
    }

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

第二个功能:

# Second function which resume the previous form and create my social number

@login_required
def BirthCertificate_Resume(request, id) :

    birthcertificate = get_object_or_404(BirthCertificate, pk=id)

    #Homme = 1 / Femme = 2
    sex_number = []
    if birthcertificate.sex == 'Masculin' :
        sex_number = 1
        print sex_number
    else :
        sex_number = 2
        print sex_number

    #Récupère année de naissance
    birthyear_temp = str(birthcertificate.birthday.year)
    birthyear_temp2 = str(birthyear_temp.split(" "))
    birthyear = birthyear_temp2[4] + birthyear_temp2[5]

    #Récupère mois de naissance
    birthmonth_temp = birthcertificate.birthday.month
    if len(str(birthmonth_temp)) == 1 :
        birthmonth = '0' + str(birthmonth_temp)
    else :
        birthmonth = birthmonth_temp

    #Récupère N° Mairie (ici récupère nom mais sera changé en n°)
    birth_mairie = birthcertificate.mairie
    print birth_mairie

    #Génère un nombre aléaloire :
    key_temp = randint(0,999)
    if len(str(key_temp)) == 1 :
        key = '00' + str(key_temp)
    elif len(str(key_temp)) ==2 :
        key = 'O' + str(key_temp)
    else :
        key = key_temp
    print key

    social_number = str(sex_number) + ' ' + str(birthyear) + ' ' + str(birthmonth) + ' ' + str(birth_mairie) + ' - ' + str(key)
    print social_number

    return render(request, 'BC_resume.html', {"birthcertificate" : birthcertificate})

我的问题是:我怎样才能重新填写我的表格并修改它以填写刚刚创建的social_number 字段?

谢谢!

【问题讨论】:

  • 我建议构建一个post_save 钩子,在您保存在模型层后生成social_number?在视图中添加这个特定的逻辑并不真正遵循解耦的理念。
  • 是的,我想也许可以实现这种功能。但也许有些人有更好的主意;)这就是我发布问题的原因;)
  • 为什么不直接覆盖Form上的.save方法呢?
  • 为什么不,但我不明白我必须如何写这种东西
  • @Valentin 明白了!据我所知,post_save 是最好的方法,这就是我使用的方法。

标签: python django forms


【解决方案1】:

对于初学者,我建议您参考此article 和此article

现在,根据您要执行的操作,我将在您定义模型的 models.py 中写入 post_save。因此,这就是它的样子:

from django.db import models
from django.dispatch import receiver
from django.db.models.signals import post_save


class BirthCertificate(models.Model):
    ...  # your model attributes


# Here is where the post_save hook happens
@receiver(post_save, sender=BirthCertificate, dispatch_uid='generate_social_number')  # You can name the dispatch_uid whatever you want
def gen_social(sender, instance, **kwargs):
    if kwargs.get('created', False):
        # Auto-generate the social number
        # This is where you determine the sex number, birth year, birth month, etc. that you have calculated in your views.py.
        # Use the instance object to get all the model attributes.
        # Example: I'll calculate the sex number for you, but I leave the other calculations for you to figure out.
        if instance.sex == 'Masculin':
            sex_number = 1
        else:
            sex_number = 2

        ...  # Calculate the other variables that you will use to generate your social number
        ...  # More lines to create the variables

        instance.social_number = str(sex_number) + ...  # Now set the instance's social number with all the variables you calculated in the above steps
        instance.save()  # Finally your instance is saved again with the generated social number

注意:我假设您希望在创建出生证明记录时生成 social_number,而不是在您修改现有记录时.这就是我使用if kwargs.get('created', False) 条件的原因。这个条件基本上检查您是在创建新记录还是修改现有记录。如果您希望这个 post_save 在修改记录后仍然运行,请删除条件。

【讨论】:

  • 好吧,我不知道这个过程。我明白,但我收到一个错误:NameError: name 'BirthCertificate' is not defined。在此之后,我进行了导入,但它不起作用。
  • 介意分享这个错误发生在哪里?我的猜测是它发生在你的views.py中。您可能必须重构您的 views.py,因为 post_save 基本上完成了您的第二个函数所做的事情。
  • 奇怪,因为我明白了:/BirthCertificate/models.py", line 59, in BirthCertificate @receiver(post_save, sender=BirthCertificate, dispatch_uid='generate_social_number') # You can name the dispatch_uid whatever you want NameError: name 'BirthCertificate' is not defined
  • 这可能是一个非常愚蠢的问题,但是您确实将 BirthCertificate 定义为模型并且拼写正确吗?
  • 这可能很愚蠢,但您的脚本应该包含在 models.py 中,对吗?在我的课后BirthCertificate ?而且我不必在我的views.py文件中添加其他东西是吗?
【解决方案2】:

我找到了一个可以更新我的模型的解决方案。

我有这个功能:

@login_required
def BirthCertificate_Resume(request, id) :

    birthcertificate = get_object_or_404(BirthCertificate, pk=id)

    #Homme = 1 / Femme = 2
    sex_number = []
    if birthcertificate.sex == 'Masculin' :
        sex_number = 1
        print sex_number
    else :
        sex_number = 2
        print sex_number

    #Récupère année de naissance
    birthyear_temp = str(birthcertificate.birthday.year)
    birthyear_temp2 = str(birthyear_temp.split(" "))
    birthyear = birthyear_temp2[4] + birthyear_temp2[5]

    #Récupère mois de naissance
    birthmonth_temp = birthcertificate.birthday.month
    if len(str(birthmonth_temp)) == 1 :
        birthmonth = '0' + str(birthmonth_temp)
    else :
        birthmonth = birthmonth_temp

    # #Récupère première lettre nom 
    # lastname_temp = birthcertificate.lastname
    # lastname = lastname_temp[0]
    # print lastname

    # #Récupère première lettre prénom 
    # firstname_temp = birthcertificate.firstname
    # firstname = firstname_temp[0]
    # print firstname


    #Récupère N° Mairie (ici récupère nom mais sera changé en n°)
    birth_mairie = birthcertificate.mairie
    print birth_mairie

    #Génère un nombre aléaloire :
    key_temp = randint(0,999999)
    if len(str(key_temp)) == 1 :
        key = '00000' + str(key_temp)
    elif len(str(key_temp)) == 2 :
        key = '0000' + str(key_temp)
    elif len(str(key_temp)) == 3 :
        key = '000' + str(key_temp)
    elif len(str(key_temp)) == 4 :
        key = '00' + str(key_temp)
    elif len(str(key_temp)) == 5 :
        key = '0' + str(key_temp)
    else :
        key = key_temp
    print key

    social_number = str(sex_number) + ' ' + str(birthyear) + ' ' + str(birthmonth) + ' ' + str(birth_mairie) + ' - ' + str(key) 
    print social_number


    return render(request, 'BC_resume.html', {"birthcertificate" : birthcertificate, "social_number" : social_number})

所以我只添加了两行,它似乎工作得很好:

birthcertificate.social_number = social_number
birthcertificate.save()

你觉得这个方法怎么样?

【讨论】:

    猜你喜欢
    • 2022-01-04
    • 1970-01-01
    • 1970-01-01
    • 2015-11-04
    • 2014-10-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多