1

I am newbie in Django, and I can’t figure out how to get username through request. I’m working on vocabulary type site and I need that every entry user creates would have username.

Here is my models.py

from django.db import models

class EngDict(models.Model):

    orig_word = models.CharField(max_length=500, null=False,blank=False, verbose_name='Слово')
    translate = models.CharField(max_length=500,null=False,blank=False, verbose_name="Перевод")
    remarks = models.TextField(null=True, blank=True, verbose_name="Примечания")
    published_by = models.CharField(max_length=50, verbose_name="Добавлено")
    published_date = models.DateTimeField(auto_now_add=True, db_index=True, verbose_name="Дата добавления")
    category = models.ForeignKey('Category', null=True, blank=True, on_delete=models.PROTECT, verbose_name = 'Категория')

    class Meta:
        verbose_name = ("Перевод")
        verbose_name_plural = "Англо-русский словарь"
        ordering = ['-published_date']

This is views.py

from django.shortcuts import render
from django.template import loader
from .models import EngDict, Category
from django.views.generic.edit import CreateView
from .forms import EngDictForm
from django.urls import reverse_lazy
from django.views.generic import TemplateView, ListView, FormView
from django.db.models import Q
from django.contrib.auth.forms import AuthenticationForm
from django.contrib.auth import login

class EngDictCreateView(CreateView):
    template_name = 'dict/create.html'
    form_class = EngDictForm
    success_url = reverse_lazy('index')


    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['categories'] = Category.objects.all()
        return context

I see that I need some function like def user_name(request) , but I can’t understand where i should write it and what must be inside of it. I need that published_by variable was automatically filled in with user login

Added exclude in forms.py

from django.forms import ModelForm
from .models import EngDict
from django import forms


class EngDictForm (ModelForm):
    def clean_orig_word(self):
        data = self.cleaned_data['orig_word']
        if EngDict.objects.filter(orig_word = data).count():
            raise forms.ValidationError("ТАКОЕ СЛОВО УЖЕ ЕСТЬ!")
        return data
    class Meta:
        model = EngDict
        fields = ('orig_word', 'translate', 'remarks', 'published_by')
        exclude =['published_by']
  • Does this answer your question? [How can I get the username of the logged-in user in Django?](https://stackoverflow.com/questions/16906515/how-can-i-get-the-username-of-the-logged-in-user-in-django) – zenka May 31 '20 at 23:57

1 Answers1

0

Please do not use a CharField for that. If later the user changes their username, then it refers to a user that no longer exists. To refer to another object, one uses a relation field like a ForeignKey [Django-doc], OneToOneField [Django-doc], or , ManyToManyField [Django-doc]. Here it looks like a ForeignKey is what you are looking for:

from django.conf import settings

class EngDict(models.Model):
    orig_word = models.CharField(max_length=500, null=False,blank=False, verbose_name='Слово')
    translate = models.CharField(max_length=500,null=False,blank=False, verbose_name='Перевод')
    remarks = models.TextField(null=True, blank=True, verbose_name='Примечания')
    published_by = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.PROTECT,
        editable=False,
        verbose_name='Добавлено'
    )
    published_date = models.DateTimeField(auto_now_add=True, db_index=True, verbose_name='Дата добавления')
    category = models.ForeignKey('Category', null=True, blank=True, on_delete=models.PROTECT, verbose_name = 'Категория')

    class Meta:
        verbose_name = ('Перевод')
        verbose_name_plural = 'Англо-русский словарь'
        ordering = ['-published_date']

In the form you should exclude published_by and in the CreateView, you can then "patch" the object with:

from django.contrib.auth.mixins import LoginRequiredMixin

class EngDictCreateView(LoginRequiredMixin, CreateView):
    template_name = 'dict/create.html'
    form_class = EngDictForm
    success_url = reverse_lazy('index')


    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['categories'] = Category.objects.all()
        return context

    def form_valid(self, form):
        form.instance.published_by = self.request.user
        return super().form_valid(form)

Note: You can limit views to a class-based view to authenticated users with the LoginRequiredMixin mixin [Django-doc].

Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555
  • I updated question. Added exclude in forms.py. Now I have this error "no such column: dict_engdict.published_by_id" – Alexander Gninenko Jun 01 '20 at 07:50
  • I tried to migrate but got this error: django.db.utils.IntegrityError: The row in table 'dict_engdict' with primary key '2' has an invalid foreign key: dict_engdict.published_by_id contains a value 'Alexander' that does not have a corresponding value in auth_user.id. – Alexander Gninenko Jun 01 '20 at 08:08
  • Ok. I've deleted all my entries. Made migration successfully and now it works! So much troubles just to add simple username. Thank you! – Alexander Gninenko Jun 01 '20 at 09:07