Rellena automáticamente el campo ForeignKey en Django CreateView.
Aquí está mi escenario. Quiero que uno de los campos de mi modelo se autorellene en función de si el usuario está autenticado o no. Como cuando el usuario envía el formulario, necesito verificar si el usuario está autenticado y luego rellenar el campo created_by
con <User Object>
en caso contrario, dejarlo Null
si es posible.
Aquí está mi modelo:
class Snippet(models.Model):
# ---
create<em>by = models.ForeignKey(
User,
on</em>delete = models.CASCADE,
null=True,
)
# ---
Aquí está mi vista:
class SnippetCreateView(CreateView):
# ---
def save(self, request, *args, **kwargs):
if request.user.is_authenticated:
user = User.objects.get(username=request.user.username)
request.POST['create_by'] = user # --->> TraceBack: debido a la inmutabilidad..
return super().post(request, *args, **kwargs)
# ---
Dado que el objeto QueryDict de request.POST
es inmutable, ¿cómo puedo implementarlo? He intentado varias formas, como crear una copia, pero no sucede nada y no cambia nada.
Pero…
Puedo implementarlo de esta forma y funciona sin problema. Creo que esta solución es lo suficientemente mala como para encontrar una mejor manera. ¿Qué piensas de esta solución?
class Snippet.CreateView(CreateView):
# ---
def save(self, request, <em>args, *</em>kwargs):
if request.user.is<em>authenticated:
user = User.objects.get(username=request.user.username)
data = {
'title': request.POST['title'],
# ---
'create</em>by': user if user else None,
}
snippet = Snippet.objects.create(**data).save()
# redirigiendo a Snippet.get_absolute_url()
# ---
davy.ai
Solución:
Ya que el QueryDict
request.POST
es inmutable, no podemos modificar directamente sus valores. En su lugar, podemos hacer uso del métodocopy()
de QueryDict para crear una copia mutable de él y modificar esa copia. Así es como podemos implementarlo:Explicación:
form_valid()
de CreateView que se llama cuando el formulario se valida correctamente.self.request.user.is_authenticated
. Si es así, entonces creamos una copia mutable del diccionariocleaned_data
del formulario usandodata = form.cleaned_data
. Esto es importante ya que no queremos modificar los datos originales del formulario.create_by
en el diccionariodata
aself.request.user
.self.object = form.save()
, que devuelve la instancia guardada del modelo Snippet.commit=False
al guardar el formulario, lo que crea una instancia no guardada del modelo Snippet. Luego guardamos esta instancia manualmente usandoself.object.save()
.return HttpResponseRedirect(self.get_success_url())
.return self.render_to_response(self.get_context_data(form=form))
.Resultado:
Con esta implementación, el campo
create_by
del modelo Snippet se rellenará automáticamente con el usuario autenticado actualmente, si lo hay, cuando se envíe el formulario. Si el usuario no está autenticado, entonces el campo se dejará nulo.