简体   繁体   English

Django - 内联表单集 - 如何设置当前用户

[英]Django - Inline formset - How to set current user

-Objective- I need to set, in a Inline Formset, the current user as automatic content of a field of the form. -目标- 我需要在 Inline Formset中将当前用户设置为表单字段的自动内容。 (Currently not working) (目前不工作)


Version Python 3.9.2 - Django 3.2版本Python 3.9.2 - Django 3.2

Context: I've created a List, where I have some objects(Headers).上下文:我创建了一个列表,其中有一些对象(标题)。 From the list I can create new headers and access to the detail-page(Detailview)for each of these by using a foreign-key(called by PK-primarykey).从列表中,我可以使用外键(由 PK-primarykey 调用)创建新标题并访问每个标题的详细信息页面(Detailview)。

In this page I can see more informations about 1 specific header.在此页面中,我可以看到有关 1 个特定 header 的更多信息。 Each header can have multiple lines of informations that need to be linked to it.每个 header 可以有多行需要链接的信息。 The lines are created or updated with (max 4 different) specific Inline Formsets.这些行是使用(最多 4 个不同的)特定的内联表单集创建或更新的。

-Issue and Error- I created the forms that are correctly rendered, but I need to set for each line, a field that automatically gets "current user" as its content. -问题和错误-我创建了正确渲染的 forms,但我需要为每一行设置一个自动获取“当前用户”作为其内容的字段。 I can't save and receive instead"User cannot be null" .我无法保存和接收“用户不能为空”

I'm unable to find a solutions and tried many things but stuck with this error.我无法找到解决方案并尝试了很多方法,但遇到了这个错误。

Would kindly appreciate any help on how to solve this problem.非常感谢有关如何解决此问题的任何帮助。 Thanks in advance,提前致谢,


Below some code:下面是一些代码:

URLS.PY URLS.PY

from django.urls import path, re_path
from fttlapp import views

app_name= 'fttlapps'

urlpatterns = [
path('fttlapphome2/', views.Fttlapphome2View.as_view(), name='fttlapphome2'),
path('fttlogheader/', views.HeadfttlogListView.as_view(), name='headfttlogs'),
path('fttlogheader/add/', views.HeadfttlogCreateView.as_view(), name='headfttlogcreate'),
path('fttlogheader/<int:pk>/', views.HeadfttlogDetailView.as_view(), name='headfttlogdetail'),
path('fttlogheader/<int:pk>/flights/edit/', views.HeadfttlogDeafttlogEditView.as_view(), name='head_flight_edit'),
]

FORMS.PY FORMS.PY

from django import forms
from django.contrib.auth.models import User
from django.db.models.fields import CharField, DateField
from django.forms import ModelForm, widgets
from django.forms.fields import ChoiceField
from django.forms.models import ModelChoiceField
from django.utils import timezone

# Load necessary to manage Form in Form
from django.forms.models import inlineformset_factory

# Load Tables
from fttlapp.models import Headfttlog, Deafttlog, Debfttlog
###############################################################################
# Forms for Headfttlog                                                        #
###############################################################################


class HeadfttlogcreateForm(ModelForm):
    class Meta:
        model = Headfttlog
        exclude = ['hea_creator', 'hea_modifier']

        widgets = {
            'hea_fttldate' : forms.TextInput(attrs={'type': 'date'}),
            'hea_nxtcheckdate' : forms.TextInput(attrs={'type': 'date'}),
            'hea_transfereddate' : forms.TextInput(attrs={'type': 'date'}),
        }
        ## Calendar widget to work both with Create and Update needs to be TextInput with type date
        ## Calendar widget not compatible with localized_fields !


###############################################################################
# Forms for Headfttlog with Deafttlog details view Management                 #
###############################################################################
HeadfttlogDeafttlogFormset = inlineformset_factory(Headfttlog, Deafttlog, 
    fields=('dea_linetype', 'dea_fttlcode', 'dea_airportfrom', 'dea_airportto',
            'dea_instrtimestart', 'dea_instrtimeend', 'dea_instrtimetot',
            'dea_blocktimestart', 'dea_blocktimeend', 'dea_blocktimetot',
            'dea_flighttimestart', 'dea_flighttimeend', 'dea_flighttimetot', 
            'dea_approach', 'dea_landing', 'dea_external', 'dea_fuel', 'dea_oil',
            'dea_lessonnotes', 'dea_preflightsignature', 'dea_invoiceaccount',
            'dea_transfered', 'dea_transfereddate',
            'dea_reccanceled', 'dea_creator', 'dea_modifier'),
    widgets={
            'dea_instrtimestart' : forms.TimeInput(format= '%H:%M', attrs={'type': 'time'}),
            'dea_instrtimeend' : forms.TimeInput(format= '%H:%M', attrs={'type': 'time'}),
            'dea_instrtimetot' : forms.TimeInput(format= '%H:%M', attrs={'type': 'time'}),
            'dea_blocktimestart' : forms.TimeInput(format= '%H:%M', attrs={'type': 'time'}),
            'dea_blocktimeend' : forms.TimeInput(format= '%H:%M', attrs={'type': 'time'}),
            'dea_blocktimetot' : forms.TimeInput(format= '%H:%M', attrs={'type': 'time'}),
            'dea_flighttimestart' : forms.TimeInput(format= '%H:%M', attrs={'type': 'time'}),
            'dea_flighttimeend' : forms.TimeInput(format= '%H:%M', attrs={'type': 'time'}),
            'dea_flighttimetot' : forms.TimeInput(format= '%H:%M', attrs={'type': 'time'}),
            'dea_reccanceled' : forms.HiddenInput,
            'dea_creator' : forms.HiddenInput,
            'dea_modifier' : forms.HiddenInput,
        }, extra=1, max_num=8)


VIEWS.PY意见.PY

from django.shortcuts import render
from django.http import HttpResponseRedirect
from django.urls import reverse
# Load necessary view
from django.views.generic import (
    TemplateView, ListView, CreateView, DetailView, FormView)
from django.views.generic.detail import SingleObjectMixin
# Load for security and access management
from django.contrib.auth.decorators import login_required
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.auth.mixins import PermissionRequiredMixin
# Load functions and tools for search bar management
from fttlapp.filters import HeadfttlogFilter
import operator
from functools import partial, reduce
from django.db.models import Q
# Load functions for messages management
from django.contrib import messages
# Load Tables & Forms
from fttlapp.models import Headfttlog
from fttlapp.forms import HeadfttlogcreateForm
from fttlapp.forms import HeadfttlogDeafttlogFormset


###############################################################################
# FTTL home page management                                                   #
###############################################################################


@login_required
def fttlapphome(request):
    context = {}
    return render(request, 'fttlapp/fttlapphome.html', context)


###############################################################################
# FTTL home page 2 management                                                 #
###############################################################################

class Fttlapphome2View(TemplateView, LoginRequiredMixin):
    template_name = 'fttlapp/fttlapphome2.html'

###############################################################################
# Headfttlog - List view Management                                           #
###############################################################################


class HeadfttlogListView(ListView, LoginRequiredMixin, PermissionRequiredMixin):
    permission_required = 'fttlapp.view_headfttlog'

    model = Headfttlog
    template_name = 'fttlapp/headfttlog_list.html'
    paginate_by = 10

    def get_context_data(self, *args, **kwargs):
        context = super().get_context_data(*args, **kwargs)
        context['myFilter'] = HeadfttlogFilter(
            self.request.GET, queryset=self.get_queryset())
        return context

    # Following redefintion necessary to obtain correct pagination after Filter plugin
    def get_queryset(self):
        queryset = super().get_queryset()
        return HeadfttlogFilter(self.request.GET, queryset=queryset).qs


###############################################################################
# Headfttlog - Create view Management Headfttlog                              #
###############################################################################


class HeadfttlogCreateView(LoginRequiredMixin, PermissionRequiredMixin, CreateView):
    permission_required = 'fttlapp.add_headfttlog'

    model = Headfttlog
    template_name = 'fttlapp/headfttlogcreate_form.html'
    form_class = HeadfttlogcreateForm

    def form_valid(self, form):
        form.instance.hea_creator = self.request.user
        form.instance.hea_modifier = self.request.user
        messages.add_message(
            self.request,
            messages.SUCCESS,
            'The LOG has been created'
        )
        return super().form_valid(form)


###############################################################################
# Headfttlog - Detail view Management Headfttlog                              #
###############################################################################

class HeadfttlogDetailView(LoginRequiredMixin, PermissionRequiredMixin, DetailView):
    permission_required = 'fttlapp.view_headfttlog'

    model = Headfttlog
    template_name = 'fttlapp/headfttlogdetail.html'


###############################################################################
# Headfttlog with Deafttlog details view Management                             #
###############################################################################

class HeadfttlogDeafttlogEditView(LoginRequiredMixin, PermissionRequiredMixin, SingleObjectMixin, FormView):
    permission_required = ('fttlapp.add_headfttlog','fttlapp.change_headfttlog',
                             'fttlapp.add_deafttlog', 'fttlapp.change_deafttlog')

    model = Headfttlog
    template_name = 'fttlapp/head_flight_edit.html'

    ### 1. Identification of the single Headfttlog we will work with
    def get(self, request, *args, **kwargs):
        self.object = self.get_object(queryset=Headfttlog.objects.all())
        return super().get(request, *args, **kwargs)
    
    def post(self, request, *args, **kwargs):
        self.object = self.get_object(queryset=Headfttlog.objects.all())
        return super().post(request, *args, **kwargs)

    ### 2. FormSet creation - instance is the link to the above data. 
    def get_form(self, form_class=None):
        return HeadfttlogDeafttlogFormset(**self.get_form_kwargs(), instance=self.object)

    def formset_valid(self, form):
        form.dea_creator = self.request.user
        form.dea_modifier = self.request.user

        form.save()

        messages.add_message(
            self.request,
            messages.SUCCESS,
            'Changes were saved.'
        )

        return HttpResponseRedirect(self.get_success_url())
        
    def get_success_url(self):
        return reverse('fttlapps:headfttlogdetail', kwargs={'pk': self.object.pk})



###############################################################################
# End of view Management                                                      #
###############################################################################

HTML HTML


{% extends 'base/dibase3.html' %}
{% load static %}

{% load crispy_forms_tags %}
{% crispy formset %}

{% block title %}Editing Flights and Instructions for {{ headfttlog.fttlcode }}{% endblock %}

{% block content %}


<style>

    .box{
        max-width: fit-content;
        margin: auto;

    }
</style>
 
</div>

<nav class="navbar navbar-expand-lg navbar-light bg-light">
    <div class="container-fluid">
      
        <div class="text-start">
          <a class="btn btn-outline-info " href="{% url 'fttlapps:headfttlogdetail' pk=headfttlog.pk %}">Back to Detail</a>
          
        </div>

     </div>
    </nav>
<hr>

<div class="container"> 

  <form action="" method="post" enctype="multipart/form-data">

    {% for hidden_field in form.hidden_fields %}
      {{ hidden_field.errors }}
      {{ hidden_field }}
    {% endfor %}

    {% csrf_token %}

    {{ form.management_form }}
    {{ form.non_form_errors }}

    <h3>Update Collection</h3>
    {% for deafttlog_form in form.forms %}
      <hr>
      <h5>
        {% if deafttlog_form.instance.id %}
          Deafttlog: {{ deafttlog_form.instance.dea_linetype }}
        {% else %}
          {% if form.forms|length > 1 %}
            Add another deafttlog
          {% else %}
            Add a deafttlog
          {% endif %}
        {% endif %}
      </h5>
      {% for hidden_field in deafttlog_form.hidden_fields %}
        {{ hidden_field.errors }}
      {% endfor %}
      <table>
        {{ deafttlog_form }}
      </table>
    {% endfor %}
    <hr>
    <p>
      <button type="submit" value="Update Flight" class="btn btn-primary w-100 mb-3">Update Flight</button>
      <a href="{{ author.get_absolute_url  }}" role="button" class="btn btn-secondary w-100">Return</a>
    </p>
  </form>

{% endblock content %}

For audit fields like creator and modifier model fields I will usually set blank=True, null=True in the model field definition.对于creatormodifier者 model 字段等审计字段,我通常会在 model 字段定义中设置blank=True, null=True Just by doing that your code will work, because you are already handling setting of dea_creator and dea_modifier in your views.只需这样做,您的代码就可以工作,因为您已经在视图中处理dea_creatordea_modifier的设置。

If you want to enforce this in the database like you are doing now, you will have to pass the request.user to your formset and set it as the initial value for the dea_creator field when initializing the forms.如果您想像现在这样在数据库中强制执行此操作,则必须在初始化 forms 时将request.user传递给您的表单集并将其设置为dea_creator字段的初始值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM