Пользовательский набор форм: - Назначение значения внешнего ключа и ввод поля только один раз [Зарегистрированный пользователь] - PullRequest
0 голосов
/ 13 мая 2019

У меня есть набор моделей для заполнения модели расписания.

Модель

class Timetable(models.Model):
    day = models.ForeignKey('Day',on_delete=models.CASCADE)
    start = models.IntegerField()
    end = models.IntegerField()
    period = models.CharField(max_length=12)
    classteacher = models.ForeignKey('Class_teacher',on_delete=models.SET_NULL)

class Class_teacher(models.Model):
    first_name = models.CharField(max_length=200)
    last_name = models.CharField(max_length=200)
    empid = models.CharField(max_length=10)
    email = models.CharField(max_length=30)

Просмотры

class Timetableadding(CreateView):
    model =  Timetable
    success_url = '/dashboard'
    form_class = Timetableform
    template_name = 'newtest.html'

    def get_context_data(self, **kwargs):
        context = super(Timetableadding, self).get_context_data(**kwargs)
        context['formset'] = TimetableFormSet(queryset=Timetable.objects.none())
        return context

    def post(self, request, *args, **kwargs):
        formset = TimetableFormSet(request.POST)
        if formset.is_valid():
            return self.form_valid(formset)

    def form_valid(self, formset):
        formset.classteacher = get_object_or_404(Class_teacher, email=self.request.user.email)
        formset.save()
        # return super().form_valid(formset)
        return HttpResponseRedirect('/dashboard')

Формы

class Timetableform(ModelForm):
    class Meta:
        model = Timetable
        fields = ( 'start', 'end', 'period')

TimetableFormSet = modelformset_factory(Timetable, fields=('start', 'end', 'period'),extra=8,)

Template

<form class="form-material m-t-40 floating-labels" method="post" enctype="multipart/form-data">
     {% csrf_token %}
     {{ formset.management_form }}
     {% for form in formset %}
          {{ form }}<br><br>
     {% endfor %}
     <div class="form-group row">
          <button type="submit" class="btn waves-effect waves-light btn-rounded btn-success">
                Submit
          </button>

      </div>
</form>

При заполнении формы расписания с использованием представления createview поля start end period в Timetable модели выполняются как общая форма.

Требования

  1. В веб-приложении есть функция входа в систему. Когда пользователь (classteacher) авторизуется, он может добавить расписание. То, что я хочу, это то, чтобы поле classteacher в Timetable (модель Form) было автоматически установлено как пользователь, который является учителем класса. (Classteacher) и должны быть сохранены в БД после создания расписания. Модель Classteacher обновлена ​​соответствующими полями.

Я пытался передать классного учителя в formset, но он был выполнен так, как мне нужно

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

  1. Поле дня в Timetable должно быть выбрано только один раз, поэтому будет предоставлено 8 форм для start end и period, но должна быть только одна форма для day. Мне удалось получить 8 форм для start end и period, но я не знал о day.

Ответы [ 2 ]

2 голосов
/ 15 мая 2019

Есть лучшие способы сделать это:

  • Если вы используете inlineformset_factory, вы можете передать экземпляр учителя, которому принадлежит набор форм, непосредственно при инициализации набора форм.См. Пример здесь .
  • Или вы можете перебирать формы для изменения экземпляров перед их сохранением:

    instances = formset.save(commit=False)
    for instance in instances: 
        instance.classteacher = ...
        instance.save()
    

Если вы хотите, чтобы пользователь отправлял дополнительное поле, общее для всех экземпляров, вы можете добавить другую форму к вашему представлению:

class DayForm(forms.Form):
    day = ModelChoiceField(queryset=Day.objects.all())

def get_context_data(self, **kwargs):
    ...
    context['day_form'] = DayForm()
    return context

def post(self, *args, **kwargs):
    ...
    day_form = DayForm(data=request.POST)
    if formset.is_valid() and day_form.is_valid():
        return self.form_valid(formset, day_form)

def form_valid(self, formset, day_form):
    day = day_form.cleaned_data['day']
    instances = formset.save(commit=False)
    for instance in instances:
        instance.day = day
        instance.teacher = ...
        instance.save()
    return HttpResponseRedirect(...)

Шаблон для визуализации

<form class="form-material m-t-40 floating-labels" method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ day_form }} <br>
{{ formset.management_form }}
{% for form in formset %}
     {{ form }}<br><br>
{% endfor %}
     <div class="form-group row">
          <button type="submit" class="btn waves-effect waves-light btn-rounded btn-success">
    Submit
          </button>

     </div>
</form>
0 голосов
/ 13 мая 2019

В вашем CreateView вы можете переопределить метод get_initial:

def get_initial(self):
    self.initial = CreateView.get_initial(self)
    self.initial["classteacher"] = self.request.user
return self.initial.copy()

Затем вам нужно добавить это поле в форму

class Timetableform(ModelForm):
    class Meta:
        model = Timetable
        fields = ( 'start', 'end', 'period', “classteacher”)


, если вы не хотите показывать это поле в вашемЕсли вы добавляете classteacher в качестве текущего пользователя, вы можете использовать виджет Hiddeninput с этим полем:

class Timetableform(ModelForm):
    class Meta:
        model = Timetable
        fields = ( 'start', 'end', 'period', “classteacher”)
           widgets = {"classteacher": HiddenInput}

в наборе форм, вы также можете использовать виджет hiddeninput или использовать аргумент form = Timetableform в конструкторе.Та же идея

...