Django - en línea formset - Cómo configurar usuario actual

0

Pregunta

-Objetivo- Necesito establecer, en un en línea Formset, el usuario actual como automática el contenido de un campo del formulario. (Actualmente no funciona)


Versión Python 3.9.2 - Django 3.2

Contexto: He creado una Lista, donde tengo algunos objetos(Encabezados). De la lista me puede crear nuevos encabezados y acceso al detalle de la página(de la vista de detalles)para cada uno de estos mediante el uso de una clave externa(llamada por PK-primarykey).

En esta página puede ver más información acerca de 1 encabezado específico. Cada encabezado puede tener varias líneas de información que necesitan estar conectados a la misma. Las líneas se crean o actualizan con (max 4 diferentes) específicos en línea Formsets.

-Problema y Error- He creado los formularios que se representa correctamente, pero necesito configurar para cada línea, un campo que automáticamente obtiene el "usuario actual" como su contenido. Yo no puedo guardar y recibir, en cambio,"el Usuario no puede ser nulo".

Yo soy incapaz de encontrar una solución y probado muchas cosas pero pegado con este error.

Amablemente le agradecemos cualquier ayuda sobre cómo solucionar este problema. Gracias de antemano,


A continuación algunas código:

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

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

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


{% 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 %}

1

Mejor respuesta

1

Para la auditoría de los campos como creator y modifier modelo de campos que se suele establecer blank=True, null=True en el modelo de definición de campo. Sólo por hacer lo que el código de trabajo, porque ya el manejo de la configuración de dea_creator y dea_modifier en sus puntos de vista.

Si desea aplicar esto en la base de datos como la que están haciendo ahora, tendrá que pasar a la request.user a su formset y establecer como valor inicial para el dea_creator campo cuando la inicialización de las formas.

Editar:

La alternativa que he mencionado anteriormente, en su HeadfttlogDeafttlogFormseten lugar de fields y widgets, crear una forma concreta a utilizar, por ejemplo DeafttlogFormy establecer el fields y widgets no. A continuación, en su conjunto, se establece form=DeafttlogForm.

En la recién creada DeafttlogForminicializar el dea_creator campo:

def __init__(self, *args, **kwargs):
    user = kwargs.pop('user', None)
    super(DeafttlogForm, self).__init__(*args, **kwargs)
    instance = getattr(self, 'instance', None)
    if not instance.id and user:
        self.initial['dea_creator'] = user

A continuación, en HeadfttlogDeafttlogEditView, añadir un get_form_kwargs método:

def get_form_kwargs(self):
    kwargs = super(HeadfttlogDeafttlogEditView, self).get_form_kwargs()
    kwargs['user'] = self.request.user
    return kwargs
2021-11-24 08:04:48

Gracias! El "conjunto de blank=True, null=True en el modelo de definición de campo" funcionó a la perfección y solucionado el error que tuve, soo, por fin puedo guardar el objeto. Sobre el segundo punto, he probado pero todavía no parece funcionar. Por eso me refiero a que he tratado de cambiar como usted sugiere y algunas variaciones, pero es rechazado o, incluso si aparentemente escrito en la forma correcta, completamente ignorado en el proceso de almacenamiento (aparentemente) incluso durante la inicialización del formulario. ¿Tiene usted alguna idea de por qué sucede esto? Debo buscar en cómo establecer de manera diferente (me refiero a valor inicial), o en otro lugar?
NewDevAsks1

La explicación fue muy clara y útil. Al principio no funcionó de inmediato (al parecer, algunos de los datos de una mala ahorrar durante las pruebas fue la creación de algunas cuestiones), pero tan pronto como me quitan esas y fijo que funcionó de maravillas!!! Gracias de nuevo por la ayuda!
NewDevAsks1

En otros idiomas

Esta página está en otros idiomas

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Slovenský
..................................................................................................................