首页 文章

Django ModelForm在一个字段中使用两个模型字段的组合

提问于
浏览
0

是否可以将ModelForm中的两个模型字段组合在一个字段中?

我的模特:

class Sample(models.Model):
    request_number = models.PositiveIntegerField()
    year = models.PositiveIntegerField()
    part = models.CharField(max_length=6, null=True, blank=True)

    class Meta:
        db_table = "sample"
        unique_together = (('request_number', 'year', 'part'),)

    def __str__(self):
        sample_id = "%s/%s" %(str(self.request_number), str(self.year)[2:])
        return(sample_id)

因此,样本从模型返回为/或123/18

但是,如果我创建一个ModelForm,我不希望两个字段输入request_number然后输入year . 相反,我希望用户输入123/18的一个字段,我的表单来解析request_number和year,以及要验证的ModelForm .

我已经尝试过这个普通的django表单,但它在我的视图中没有验证 .

形成:

class SingleSampleForm(forms.Form):

    sample_id = forms.CharField(
        required=True,
        label='Sample ID:')

    class Meta:
        fields = ['sample_id']

    def __init__(self, *args, **kwargs):
        super(SingleSampleForm, self).__init__()
        self.helper = FormHelper()
        self.helper.layout = Layout(
            Field('sample_id',
                css_class="search-form-label",
                ),
            Submit('submit', 'Search sample', css_class='upload-btn')
        )

        self.helper.form_method = 'POST'

    def clean(self):
        sample_id = self.cleaned_data['sample_id']
        if sample_id:
            return sample_id
        raise ValidationError('This field is required')

views.py:

class SampleView(View):

    sample_form = SingleSampleForm

    def get(self, request, *args, **kwargs):

        sample_form = self.sample_form()
        self.context = {'sample_form': sample_form,}

        return render(request,
                'results/single_sample_search.html',
                self.context)

    def post(self, request, *args, **kwargs):
        sample_form = self.sample_form(request.POST)

        if sample_form.is_valid():
            print('Valid')
        else:
            print('not valid')

        self.context = {'sample_form': sample_form,}

        return render(request,
                'results/single_sample_search.html',
                self.context)

是否可以使用django ModelForm,并创建一个两者组合的字段,然后可以在“clean_request_number”和clean_year“方法中解析和验证?或者为什么我这个自定义表单出错?

谢谢

1 回答

  • 0

    以下代码在我的机器上运行,即ubuntu18.04 python3.6.5 django2.0 pipenv:

    models.py

    from django.db import models
    from django.urls import reverse
    
    
    class Sample(models.Model):
        request_number = models.PositiveIntegerField()
        year = models.CharField(max_length=4, blank=True)
        part = models.CharField(max_length=6, null=True, blank=True)
    
        class Meta:
            db_table = "sample"
            unique_together = (("request_number", "year", "part"),)
    
        def get_absolute_url(self):
            return reverse("sample-detail", args=[self.pk])
    
        def __str__(self):
            return f"{self.request_number}/{self.year[-2:]}"
    

    forms.py

    from django import forms
    from django.core.validators import RegexValidator
    from .models import Sample
    
    
    class SingleSampleForm(forms.Form):
        sample_str = forms.CharField(
            required=True, label="Sample(request_number/year):",
            validators=[
                RegexValidator(r'^\d+/\d{2,4}$', "Sample should be as `123/18`")
            ]
        )
    
        class Meta:
            model = Sample
    

    views.py

    from django.shortcuts import render
    from django.views.generic.detail import DetailView
    from django.views.generic.edit import FormView
    from .forms import SingleSampleForm
    
    
    class SampleCreateView(FormView):
        template_name = "results/sample_create.html"
        form_class = SingleSampleForm
    
        def get_success_url(self):
            return self.object.get_absolute_url()
    
        def form_valid(self, form):
            request_number, year = form.cleaned_data['sample_str'].split("/")
            if len(year) == 2:
                year = "20" + year
            self.object = form.Meta.model.objects.create(
                request_number=request_number, year=year
            )
            return super().form_valid(form)
    
    
    class SampleDetailView(DetailView):
        template_name = "results/sample_detail.html"
        queryset = SingleSampleForm.Meta.model.objects.all()
    

    结果/ sample_create.html

    <form method="post">{% csrf_token %}
        {{ form }}
        <input type="submit" value="OK">
    </form>
    

    结果/ sample_detail.html

    <p>request number: {{ object.request_number }}</p>
    <p>year: {{ object.year }}</p>
    

相关问题