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
Related
My code was originally implemented for Django 1.8 now (after necessary changes) I'm running it with Django 2.2. Seems that the following was planned to show non-super-user only his/her own files:
class Tiedostot3Admin(admin.ModelAdmin):
fields = ['otsikko', 'kuvaus', 'tiedosto']
list_display = ('otsikko','paivitetty')
inlines = [
Liitet3Inline,
]
def queryset(self, request):
print("queryset, request.user", request.user)
qs = super(Tiedostot3Admin, self).queryset(request)
if request.user.is_superuser:
return qs
return qs.filter(owner=request.user)
def save_model(self, request, obj, form, change):
print("save_model, request.user", request.user)
obj.owner = request.user
obj.save()
When saving new files I can see save_model() executed, but I don't know how to get queryset() executed. It seems that it always shows the same list for all users.
models.py:
class Tiedostot3(models.Model):
otsikko = models.CharField(max_length=250)
kuvaus = RichTextField(blank=True)
paivitetty = models.DateTimeField(auto_now_add=True, verbose_name="Päivitetty")
tiedosto = models.FileField(upload_to='poytakirjat', verbose_name="Tiedosto", blank = True)
owner = models.ForeignKey(User, null=True, blank=True, on_delete=models.CASCADE)
class Meta:
ordering = ['-paivitetty']
verbose_name = "tiedosto"
verbose_name_plural="tiedostot"
def __unicode__(self):
return unicode(self.otsikko)
class Liite3(models.Model):
otsikko = models.CharField(max_length=250)
tiedosto = models.FileField(upload_to='poytakirjat')
doku = models.ForeignKey(Tiedostot3, related_name="liitteet", on_delete=models.CASCADE)
class Meta:
verbose_name_plural="Liitteet"
def __unicode__(self):
return unicode(self.otsikko)
the page:
Implement get_queryset method:
class Tiedostot3Admin(admin.ModelAdmin):
fields = ['otsikko', 'kuvaus', 'tiedosto']
list_display = ['otsikko','paivitetty']
inlines = [Liitet3Inline]
def get_queryset(self, request):
qs = super(Tiedostot3Admin, self).get_queryset(request)
if request.user.is_superuser:
return qs
return qs.filter(owner=request.user)
def save_model(self, request, obj, form, change):
print("save_model, request.user", request.user)
obj.owner = request.user
obj.save()
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.
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)
I get Integrity with the below defined model.It occurs when I make changes and save the data again from the django admin.
The error is triggered by obj.save() .
The error is as follows:
Exception Type: IntegrityError at /admin/users/data/1/change/
Exception Value: UNIQUE constraint failed: users_data.id
How can I make this right.
class Data(models.Model):
author = models.ForeignKey(User, null=True, editable=False, on_delete=models.CASCADE)
address = models.CharField(max_length=300,blank=True,null=True,help_text=("enter the address"))
contact = models.IntegerField(blank=True,null=True,help_text=("enter the contact"))
username = models.CharField(max_length=100,blank=True,null=True,help_text=("enter the username"))
password = models.CharField(max_length=100,blank=True,null=True,help_text=("enter the strong password"))
creation_date = models.DateTimeField(editable=False,null=True)
last_modified = models.DateTimeField(editable=False,null=True)
def save(self,*args, **kwargs):
if not self.creation_date:
self.creation_date = timezone.now()
self.last_modified = timezone.now()
return super(Data, self).save(self,*args, **kwargs)
def __str__(self):
return (self.username)
#receiver(post_save,sender=Data)
def datasaver(sender, instance, **kwargs):
address = instance.address
contact = instance.contact
username = instance.username
user_password = instance.password
class CustomAdmin(admin.ModelAdmin):
search_fields = ('first_name', 'email', 'username', )
def save_model(self, request, obj, form, change):
obj.author = request.user
obj.password = ''
obj.save()
def get_queryset(self, request):
qs = super(CustomAdmin, self).get_queryset(request)
if request.user.is_superuser:
return qs
return qs.filter(author=request.user)
Don't do this. Django provides a better way to save the modified date and creation date. Use this instead and remove the overridden save method and post save signal.
Replace
creation_date = models.DateTimeField(editable=False,null=True)
last_modified = models.DateTimeField(editable=False,null=True)
with
creation_date = models.DateTimeField(auto_now_add=True)
last_modified = models.DateTimeField(auto_now=True)
See django datefield optional arguments
I have a model with two date fields, for submitted and published and a boolean field for approved.
class BlogModel(models.Model):
title = models.CharField(max_length=100)
article = models.CharField(max_length=255)
pub_date = models.DateTimeField('date published')
submitted_date = models.DateTimeField('date submitted')
author = models.CharField(max_length=255)
approved = models.BooleanField(default=False)
def __str__(self): # __unicode__ on Python 2
return 'approved, ' + str(self.approved) + ' article, ' + self.article
I have included this model in admin.py. Admin can approve the article, but is it possible to have the pub_date be the current time when the article is approved in admin?
UPDATE These models work for me in forms.py as suggested by Raja Simon
class BlogForm(forms.ModelForm):
class Meta:
model = BlogModel
fields = '__all__'
# fields = ('id', 'title', 'article')
def save(self, force_insert=False, force_update=False, commit=True):
m = super(BlogForm, self).save(commit=False)
# do custom stuff
m.pub_date = timezone.now()
if commit:
m.save()
return m
and admin.py
class BlogModelAdmin(admin.ModelAdmin):
form = BlogForm
fields = ('title', 'article', 'pub_date', 'submitted_date', 'author', 'approved')
# fields = '__all__' won't work here, each field needs to be added individually as above
pass
admin.site.register(BlogModel, BlogModelAdmin)
Thanks
You can override form save in admin
class BlogModelAdmin(admin.ModelAdmin):
form = BlogModelForm
pass
admin.site.register(BlogModel, BlogModelAdmin)
And in forms
class BlogModelForm(ModelForm):
class Meta:
model = BlogModel
fields = '__all__'
def save(self, force_insert=False, force_update=False, commit=True):
m = super(BlogModelForm, self).save(commit=False)
# do custom stuff
m.pub_date = timezone.now()
if commit:
m.save()
return m
Possible by over riding the save_model method in your admin
def save_model(self, request, obj, form, change):
if obj.approved:
obj.pub_date = timezone.now()
This is probably superior to overriding the save method in the model itself.