How can I automatically add user's info to a model in Django?
I have a status and user apps in my project and all the statuses are obviously created by particular users. I want to keep info about statuses creators (id) in my db, but I don't know how to add it automatically - without having a field in a form. Like I'm just authenticated, I create a status and my db knows it was me. I tried to do this with an initial parameter but it didn't work out. Files that I attached are from the status app
views.py
...
class StatusCreateView(View):
def get(self, request, *args, **kwargs):
form = StatusForm()
return render(request, "statuses/create.html", {"form": form})
def post(self, request, *args, **kwargs):
form = StatusForm(request.POST)
if form.is_valid():
form.save()
return redirect("statuses_list")
return render(request, "statuses/create.html", {"form": form})
...
urls.py
...
urlpatterns = [
path("", views.IndexView.as_view(), name="statuses_list"),
path("create/", views.StatusCreateView.as_view(), name="statuses_create"),
...
]
models.py
from django.db import models
# Create your models here.
class Status(models.Model):
name = models.CharField(max_length=200)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
author = models.ForeignKey(
"user.CustomUser",
on_delete=models.CASCADE,
related_name='status_related_author'
)
forms.py
from django.forms import ModelForm
from .models import Status
class StatusForm(ModelForm):
class Meta:
model = Status
fields = ["name"]
templates/statuses/create.html
{% if form.errors %}
<div>
<ul>
{% for error in form.errors %}
<li><strong>{{ error|escape }}</strong></li>
{% endfor %}
</ul>
</div>
{% endif %}
<form action="{% url 'statuses_create' %}" method="post">
{% csrf_token %}
<table border="1">
{{ form }}
</table>
<input type="submit" value="Создать">
</form>
First I would advise to make the author non-editable then:
class Status(models.Model):
name = models.CharField(max_length=200)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
author = models.ForeignKey(
'user.CustomUser',
editable=False,
on_delete=models.CASCADE,
related_name='status_related_author',
)
although not necessary, it makes your life easier, because it will not show up in ModelForms now, even if fields = __all__.
Next in the view, you can inject the author to the .instance of the form, so:
class StatusCreateView(View):
def get(self, request, *args, **kwargs):
form = StatusForm()
return render(request, 'statuses/create.html', {'form': form})
def post(self, request, *args, **kwargs):
form = StatusForm(request.POST)
if form.is_valid():
form.instance.author = self.request.user
form.save()
return redirect('statuses_list')
return render(request, 'statuses/create.html', {'form': form})
This will of course require that the person is authenticated, and we can scrap a lot of boilerplate with a CreateView:
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic.edit import CreateView
class AuthorCreateView(LoginRequiredMixin, CreateView):
model = Status
fields = ['name']
template_name = 'statuses/create.html'
success_url = reverse_lazy('statuses_list')
def form_valid(self, form):
form.instance.author = self.request.user
return super().form_valid(form)
Note: It is normally better to make use of the
settings.AUTH_USER_MODEL[Django-doc] to refer to the user model, than to use theUsermodel [Django-doc] directly. For more information you can see the referencing theUsermodel section of the documentation.