get current user for 'created_by' field in model class - django

I'm currently working on a Django app, and I'm trying to set the current user as default on a model, but it doesn't work.
created_by = models.ForeignKey(User, default=request.user, null=True, blank=True, on_delete=models.DO_NOTHING, related_name='created_by')
I tried to override the save() method but it doesn't work either, anyone has any experience on this matter ?
Thanks a lot in advance for your help

Refer official doc. It explained it pretty well. An example is also there
from django.views.generic.edit import CreateView
from myapp.models import Author
class AuthorCreate(CreateView):
model = Author
fields = ['name']
def form_valid(self, form):
form.instance.created_by = self.request.user
return super().form_valid(form)
https://docs.djangoproject.com/en/2.1/topics/class-based-views/generic-editing/#models-and-request-user

If anyone encounters this problem I followed the advice of a_k_v and did it in views.
Here is how I did it :
I added two fields in my class :
class Class(models.Model):
created_by = models.ForeignKey(User, on_delete=models.DO_NOTHING, blank=True, null=True, related_name='create')
updated_by = models.ForeignKey(User, on_delete=models.DO_NOTHING, blank=True, null=True, related_name='update')
then created a function :
def created_updated(model, request):
obj = model.objects.latest('pk')
if obj.created_by is None:
obj.created_by = request.user
obj.updated_by = request.user
obj.save()
to get it into my views.py :
if request.method == 'POST':
form = AddVacation(request.POST)
if form.is_valid:
form.save()
created_updated(Vacation, request)

If your model is like below model.py
class Post(models.Model):
title = models.CharField(max_length=500)
created_by = models.ForeignKey(User, on_delete=models.SET_NULL, null= True)
In model admin class in admin.py add the following method
class PostAdmin(admin.ModelAdmin):
readonly_fields = ('created_by',)
list_display = ('title', 'created_by')
def save_model(self, request, obj, form, change):
if obj.id == None:
obj.created_by = request.user
super().save_model(request, obj, form, change)
else:
super().save_model(request, obj, form, change)
admin.site.register(Post, PostAdmin)

Related

Django form in form

I wonder if it is possible to make form in form by using django.
For example:
class Category(models.Model):
title = models.CharField(max_length=200)
icon = models.ImageField(upload_to="icons", default="icons/dot.png")
def __str__(self):
return self.title
def get_posts(self):
return Post.objects.filter(category__title=self.title)
class Post(models.Model):
author = models.ForeignKey(Account, on_delete=models.CASCADE)
title = models.CharField(max_length=200)
category = models.ForeignKey(Category, on_delete=models.CASCADE)
description = models.CharField(max_length=400)
date_posted = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.title
While I was working with forms based on these models I was splitting CategoryForm and PostForm into two forms (category had to be made before post to make user able to choose new category during making new post) and then into two views.
class PostForm(forms.ModelForm):
class Meta:
model = Post
exclude = ('author',)
class CategoryForm(forms.ModelForm):
class Meta:
model = Catergory
fields = '__all__'
def newPostView(request):
if request.method == 'POST':
form = PostForm(request.POST)
if form.is_valid():
obj = form.save(commit=False)
obj.author = request.user
obj.save()
return redirect('home')
form = PostForm()
context = {'form':form}
return render(request, 'blog/post_form.html', context)
def newCategoryView(request)
...
...
...
I'd like to make one newPost form which will have Category form implemented - I mean I'd like to be make it possible to choose category from already made categories or make new one if its needed without using another view
How can I make it ?

show only what admin add to DB django admin

Help please. There are several admins who have different rights. There is a model where they can add a product. I want to make sure that every administrator sees what they have added themselves. In the database table there is a row сreated_by. For example, I add my books to the database and another administrator adds his books. each administrator have to sees what he added.
Thow do I do this?
model.py
class MyBooks(models.Model):
book = models.ForeignKey(Books, on_delete=models.CASCADE, blank=True, null=True, default=None)
fomil = models.CharField('Фомил',max_length=100, blank=True, null=True, default=None)
name= models.CharField('Ном',max_length=100, blank=True, null=True, default=None)
is_active = models.BooleanField('Ичозати таблиг (фаъол)',default=True)
created = models.DateTimeField('Санади сохташуда', auto_now_add=True, auto_now=False, )
updated = models.DateTimeField('Санади азнавшуда',auto_now_add=False, auto_now=True)
admin.py
class BooksAdmin(admin.ModelAdmin):
list_display = [field.name for field in MyBooks._meta.fields]
def save_model(self, request, obj, form, change):
if not obj.created_by:
obj.created_by = request.user
obj.save()
class Meta:
model = MyBooks
Just need to override the queryset function in your ModelAdmin to filter out those that weren't created by the requesting user.
#admin.Register(MyBooks)
class BooksAdmin(admin.ModelAdmin):
list_display = [field.name for field in MyBooks._meta.fields]
def get_queryset(self, request):
qs = super().get_queryset(request)
return qs.filter(created_by=request.user)
def save_model(self, request, obj, form, change):
obj.created_by = request.user
super().save_model(request, obj, form, change)
class Meta:
model = MyBooks
here are more conditions for filtering.
def get_queryset(self, request):
qs = super().get_queryset(request)
if request.user.groups.filter(name='useradmin').exists():
return qs.filter(created_by=request.user)
else:request.user.groups.filter(name='mainadmin').exists()
return qs

Django - Take username of logged user as default value to another model

I have the model "Account" below:
class Account(models.Model):
email=models.EmailField(verbose_name="email", max_length=60, unique=True)
username=models.CharField(max_length=30, unique=True)
data_inscricao=models.DateTimeField(verbose_name='Data de Inscrição', auto_now_add=True)
ultimo_login=models.DateTimeField(verbose_name='ùltimo Login', auto_now_add=True)
def __str__(self):
return self.username
and this other "PersonalData"...
class PersonalData(models.Model):
id_user=models.OneToOneField(Account, on_delete=models.CASCADE)
nome_completo=models.CharField(max_length=56, unique=True, null=True)
email=models.EmailField(max_length=60, verbose_name="Email", unique=True, null=True)
cpf=models.CharField(max_length=14, unique=True, null=True, verbose_name="CPF")
rg=models.CharField(max_length=12, unique=True, null=True, verbose_name="RG")
idade=models.IntegerField(null=True)
data_nascimento=models.DateField(verbose_name="Data de Nascimento", null=True)
genero=models.CharField(max_length=8, choices=GENERO, null=True)
estado_civil=models.CharField(max_length=13, null=True, choices=ESTADO_CIVIL, verbose_name="Estado Civil")
def __str__(self):
return self.nome_completo
views.py
def cadastro_curriculo(request):
form = InsereDadosPessoais(request.POST or None, request.FILES or None)
if form.is_valid():
form.save()
return redirect("vagas")
return render(request, "personal/curriculo.html", {'form': form,})
forms.py
class InsereDadosPessoais(forms.ModelForm):
class Meta:
model = PersonalData
fields = '__all__'
I'ld like PersonalData.id_user use by default the Account.username of the loged user and I don't know how do that.
Just to exemplify, In Django Admin, my PersonalData model allows me to choose the user, but I want it to happen automatically and not manually.
Can someone help me?
at admin.py add the admin class as per the docs
assign exclude as per the docs
exclude = ('user',)
and at save_model
def save_model(self, request, obj, form, change):
obj.user = request.user
super().save_model(request, obj, form, change)
Check docs here
If you want to add this to normal views
forms.py
class XXForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
self.user = kwargs.pop('user', None)
super(XXForm, self).__init__(*args, **kwargs)
def save(self, commit=True):
obj = super(XXForm, self).save(commit=False)
obj.user = self.user
if commit:
obj.save()
return obj
views.py
def xxview(request, *args, **kwargs): # your args
if request.POST:
#your stuff
form = XXForm(request.POST......., user=request.user)
else:
# your stuff
Check views here
I think you are Brazilian too :) Welcome! I learned this from this site.
models.py
from django.contrib.auth import User
class PersonalData(models.Model):
id_user = models.OneToOneField(User, on_delete=models.PROTECT, null=True, blank=True)
cpf = models.CharField(max_length=14, unique=True, null=True, verbose_name="CPF")
rg = models.CharField(max_length=12, unique=True, null=True, verbose_name="RG")
idade = models.IntegerField(null=True)
data_nascimento = models.DateField(verbose_name="Data de Nascimento", null=True)
genero = models.CharField(max_length=8, choices=GENERO, null=True)
estado_civil = models.CharField(max_length=13, null=True, choices=ESTADO_CIVIL, verbose_name="Estado Civil")
data_inscricao = models.DateTimeField(verbose_name='Data de Inscrição', auto_now_add=True)
ultimo_login = models.DateTimeField(verbose_name='ùltimo Login', auto_now_add=True)
def __str__(self):
return '{} {}'.format(id_user.first_name, id_user.last_name)
def save_model(self, request, obj, form, change):
if not obj.id_user:
# Only set added_by during the first save.
obj.id_user = request.user
super().save_model(request, obj, form, change)
admin.py
from .models import PersonalData
class PersonalDataAdmin(admin.ModelAdmin):
readonly_fields = ('id_user',)
admin.site.register(PersonalData, PersonalDataAdmin)
Important notes:
You don't have to create a field that saves the full name, Django itself can do it for you.
If you are going to use Django-Admin you can work with permissions within it by own User models. Click here and read a little about.
I recommend you use the built-in User model, it would look like this. Feel free to access my profile and get my contact information, I would be happy to help you with your project!
I'd suppose you have to make id_user field a foreign key to Account identifier which you should add to your model. In your described scenario id_user will "use" Account.username which is not obligated to be unique among all the users registered in the system. So, I suggest you to create an id field for Account and utilize it as a numeral identifier for that model.
Also, if I do not mistake, Django has an intrinsic User model which is intended for usage in such cases. Of course, you can extend that model for adding specific attributes.

Saving modelform with user id?

I have a question concerning a new project I'm creating. To put it simply, the website has user accounts, and each user has the ability to create a simple paragraph. The form is functioning perfectly, but I can't seem to assign the user's ID to the saved form.
model.py
class UserProfile(models.Model):
user = models.OneToOneField(User)
class Thoughts(models.Model):
user = models.ForeignKey(UserProfile, null=True)
title = models.CharField(max_length=150, default='')
description = models.CharField(max_length=5000, default='')
forms.py
class ThoughtForm(ModelForm):
class Meta:
model = Thoughts
fields = ['title', 'description']
views.py
#login_required(login_url='sign_in')
def add_thought(request):
context = {}
populateContext(request, context)
user_details = UserProfile.objects.get(user=request.user)
context.update(user_details=user_details)
if request.method == 'POST':
new_thought_form = ThoughtForm(request.POST)
if new_thought_form.is_valid():
new_thought_form.save()
return HttpResponse('Hurray, saved!')
else:
new_thought_form = ThoughtForm()
c = {'new_thought_form': new_thought_form,}
c.update(csrf(request))
return render_to_response('lala/add_new_thought.html', c)
Whenever I try adding "instance=user_details.id", it says that the 'int' object has no attribute '_meta'. Any thoughts?
You can simplify the models by removing the UserProfile model:
# models.py
class Thoughts(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
title = models.CharField(max_length=150, default='')
description = models.CharField(max_length=5000, default='')
Your forms.py looks good.
Change your views:
# views.py
#login_required(login_url='sign_in')
def add_thought(request):
if request.method == 'POST':
form = ThoughtForm(request.POST)
if form.is_valid():
thought = form.save(commit=False)
thought.user = request.user
thought.save()
return HttpResponse('Hurray, saved!')
else:
form = ThoughtForm()
return render(request, 'lala/add_new_thought.html', {
'form': form
})

Django - ModelForm initial data from database

In my Django project i create an app to have additional information about registered users. So my model looks like this:
class UserProfile(models.Model):
class Meta:
verbose_name_plural = u'User Profile'
user = models.OneToOneField(User)
birthday = models.DateField(blank=True, null=True)
avatar = models.ImageField(upload_to='media/profile/avatar', blank=True, null=True)
name = models.CharField(blank=True, null=True, max_length=20)
surname = models.CharField(blank=True, null=True, max_length=50)
phone = models.CharField(blank=True, null=True, max_length=12)
def __unicode__(self):
return '%s' % self.user
In user profile i create modelform where user can fill or edit the fields from UserProfile model:
class ExtraProfileDataForm(ModelForm):
name = forms.CharField(label=(u'Enter your name'))
surname = forms.CharField(label=(u'Enter your surname'))
phone = forms.CharField(label=(u'Enter your phone'))
birthday = forms.DateField(label=(u'Enter birthday'))
avatar = forms.ImageField(label=(u'Enter avatar'))
class Meta:
model = UserProfile
fields = ('name', 'surname', 'phone', 'birthday', 'avatar')
def __init__(self, *args, **kwargs):
super(ExtraProfileDataForm, self).__init__(*args, **kwargs)
for key in self.fields:
self.fields[key].required = False
This is the view of the model form:
#login_required
def UserFullDataForm(request):
if request.method == 'POST':
form = ExtraProfileDataForm(request.POST)
if form.is_valid():
profile_user = request.user
user_profile = UserProfile(user=profile_user)
user_profile.name = form.cleaned_data['name']
user_profile.surname = form.cleaned_data['surname']
user_profile.phone = form.cleaned_data['phone']
user_profile.birthday = form.cleaned_data['birthday']
user_profile.avatar = form.cleaned_data['avatar']
user_profile.save()
return HttpResponseRedirect('/profile/')
else:
return render(request, 'profiles/extra_profile.html', {'form':form})
else:
form = ExtraProfileDataForm()
context = {'form':form}
return render (request, 'profiles/extra_profile.html', context)
But i want to load on ExtraProfileDataForm initial data from model UserProfile if the fields not empty. I searched how to do that on Django documentation website, but nothing found. Can somebody help me to understand how to do it? Thanks a lot.
You use the instance parameter.
Note that you are doing much more work than necessary here; most of your view can be cut.
#login_required
def UserFullDataForm(request):
try:
profile = request.user.userprofile
except UserProfile.DoesNotExist:
profile = UserProfile(user=request.user)
if request.method == 'POST':
form = ExtraProfileDataForm(request.POST, instance=profile)
if form.is_valid():
form.save()
return HttpResponseRedirect('/profile/')
else:
form = ExtraProfileDataForm(instance=profile)
return render(request, 'profiles/extra_profile.html', {'form':form})
Similarly, in your form, you don't need the overridden __init__ method because you're manually specifying all the fields anyway; you can add required=False on each one there. However, you could make this even shorter by adding the labels in the model definition; then your entire modelform could just be:
class ExtraProfileDataForm(ModelForm):
class Meta:
model = UserProfile
fields = ('name', 'surname', 'phone', 'birthday', 'avatar')
One final note: you're consistently using three-space indentation, which is a bit, well, odd. Most Python programmers prefer two or four.