queryset in admin.py never gets executed in django 2.2 - django

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()

Related

Formset not submitting uploaded picture?

I have a view to allow courses to created by users on my app, which am currently having a challenge uploading a course cover(pic) when users create a new course, when course is created all the fields of the course detail get submitted to the data base except the picture data, why is the picture not being submitted, can some one please help me. as this has been a challenge for me for the past week!
This is my view to create a new course!.
class OwnerMixin(object):
def get_queryset(self):
qs = super(OwnerMixin, self).get_queryset()
return qs.filter(owner=self.request.user)
class OwnerEditMixin(object):
def form_valid(self, form):
form.instance.owner = self.request.user
return super(OwnerEditMixin, self).form_valid(form)
class OwnerCourseMixin(OwnerMixin):
model = Course
fields = ['subject', 'title', 'slug','overview','pic']
success_url = reverse_lazy('courses:manage_course_list')
class OwnerCourseEditMixin(OwnerCourseMixin):
fields = ['subject', 'title','slug', 'overview','pic']
success_url = reverse_lazy('courses:manage_course_list')
template_name = 'manage/module/formset.html'
class ManageCourseListView(OwnerCourseMixin,ListView):
template_name ='courses/course_list.html'
class CourseCreateView(OwnerCourseEditMixin,OwnerEditMixin,CreateView,):
pass
permission_required = 'courses.add_course'
class CourseModuleUpdateView(TemplateResponseMixin, View):
template_name = 'manage/module/formset.html'
course = None
def get_formset(self, data=None,):
return ModuleFormSet(instance=self.course,data=data,)
def get_form(self, data=None):
return RequirementFormset(instance=self.course,data=data)
def get_forms(self, data=None):
return WhatYouWillLearnFormset(instance=self.course,data=data)
def dispatch(self, request, pk):
self.course = get_object_or_404(Course,id=pk,owner=request.user)
return super(CourseModuleUpdateView, self).dispatch(request, pk)
def get(self, request, *args, **kwargs):
formset = self.get_formset()
form = self.get_form()
forms = self.get_forms()
return self.render_to_response({'course':self.course,
'formset':formset,'form':form,'forms':forms,})
def post(self, request, *args, **kwargs):
formset = self.get_formset(data=request.POST,)
form = self.get_form(data=request.POST,)
forms = self.get_forms(data=request.POST,)
if formset.is_valid():
formset.save()
if form.is_valid():
form.save()
if forms.is_valid():
forms.save()
return redirect('courses:manage_course_list')
return self.render_to_response({'course': self.course,
'formset':formset,})
Here is my model, am using formset to create course and also
class Course(models.Model):
owner = models.ForeignKey(settings.AUTH_USER_MODEL,\
related_name='courses_created', on_delete=models.CASCADE)
subject = models.ForeignKey(Subject,related_name='courses', on_delete=models.CASCADE)
title = models.CharField(max_length=200)
pic = models.ImageField(upload_to="course_pictures", blank=True,null=True)
slug = models.SlugField(max_length=200, unique=True,blank=True)
overview = models.TextField()
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
students = models.ManyToManyField(settings.AUTH_USER_MODEL,related_name='courses_joined',blank=True)
class Meta:
ordering = ['-created']
def __str__(self):
return self.title
Here is my formset
class CourseForm(forms.ModelForm):
class Meta:
model = Course
fields = ['pic']
ModuleFormSet = inlineformset_factory(Course,
Module,
fields=['title','description',],
extra=2,
can_delete=True)
RequirementFormset = inlineformset_factory(Course,
Requirement,
fields=['requirements'],
extra=4,can_delete=True)
WhatYouWillLearnFormset = inlineformset_factory(Course,
WhatYouWillLearn,
fields=['hightlights'],
extra=4,can_delete=True)
I think the attribute enctype="multipart/form-data" is missing in the form tag in the template file.
<form method="post" enctype="multipart/form-data">
...
...
</form>

How to specify a list of values ​in a form in which CheckboxSelectMultiple is used?

I have a problem with the form in django. It uses the CheckboxSelectMultiple widget, but I need to set a list of possible choices only for posts created by the currently logged in user.
Any idea?
form:
class CycleForm(BSModalForm):
class Meta:
model = Cycle
fields = ['title', 'description', 'posts']
widgets = {
'posts': forms.CheckboxSelectMultiple(),
}
models
class Cycle(models.Model):
title = models.CharField(max_length=200, unique=True)
description = models.TextField(max_length=500, default="Brak opisu")
date_created = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE)
posts = models.ManyToManyField(Post)
def __str__(self):
return self.title
class Post(models.Model):
title = models.CharField(max_length=50, unique=True)
content = MDTextField()
date_posted = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE)
numbers_of_entries = models.IntegerField(default=0)
views
class CycleCreateView(BSModalCreateView, LoginRequiredMixin):
template_name = 'blog/cycle_form.html'
form_class = CycleForm
def form_valid(self, form, **kwargs):
form.instance.author = self.request.user
return super().form_valid(form)
def get_success_url(self):
reverse_user = self.request.user
return reverse('profile', kwargs={'username': reverse_user})
class CycleUpdateView(BSModalUpdateView):
model = Cycle
template_name = 'blog/cycle_update.html'
form_class = CycleForm
success_message = 'Success: Cycle was updated.'
def get_success_url(self):
reverse_user = self.request.user
return reverse('profile', kwargs={'username': reverse_user})
We can slightly alter the CycleForm form and add a user parameter. If that parameter is set, we filter the queryset of the posts field by only using Posts
class CycleForm(BSModalForm):
def __init__(self, *args, user=None, **kwargs):
super().__init__(*args, **kwargs)
if user is not None:
self.fields['posts'].queryset = Post.objects.filter(author=user)
class Meta:
model = Cycle
fields = ['title', 'description', 'posts']
widgets = {
'posts': forms.CheckboxSelectMultiple(),
}
Now we only need to pass the user to the form, we can override the get_form_kwargs method [Django-doc]:
class CycleCreateView(LoginRequiredMixin, BSModalCreateView):
template_name = 'blog/cycle_form.html'
form_class = CycleForm
def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
kwargs.update(user=self.request.user)
return kwargs
def form_valid(self, form, **kwargs):
form.instance.author = self.request.user
return super().form_valid(form)
def get_success_url(self):
reverse_user = self.request.user
return reverse('profile', kwargs={'username': reverse_user})
You should do the same with the UpdateView. Note that your LoginRequiredMixin likely should be put first in the base classes.

UNIQUE constraint failed: auth_user.username while updating user info

I am trying to give a user the option to change his/her first/last name through a ModelForm. When I press submit, I get hit with the UNIQUE constraint failed: auth_user.username error. Here are my codes:
students/forms.py:
class EditProfileForm(UserChangeForm):
def clean_password(self):
# Overriding the default method because I dont want user to change
# password
pass
class Meta:
model = User
fields = (
'first_name',
'last_name',
)
students/views.py:
User = get_user_model()
def student_profile_view(request, slug):
if request.method == 'GET':
# forms
edit_name_form = EditProfileForm(instance=request.user)
context = {
'edit_name_form': edit_name_form,
}
return render(request, "students/profile.html", context)
class ChangeNameView(SuccessMessageMixin, UpdateView):
template_name = 'students/edit_profile.html'
model = User
form_class = EditProfileForm
success_message = "Your name has been updated"
def post(self, request, *args, **kwargs):
form = self.get_form()
if form.is_valid():
form.instance.student_profile = StudentProfile.objects.get(slug=request.user.student_profile.slug)
return self.form_valid(form)
else:
return self.form_invalid(form)
def form_valid(self, form):
"""If the form is valid, save the associated model."""
form.instance.username = self.request.user
self.object = form.save(commit=False)
return super().form_valid(form)
def get_success_url(self):
return reverse('students:student_profile_view', kwargs={'slug': self.object.student_profile.slug})
also fyi, User model is foreign key with StudentProfile.
students/models.py:
class StudentProfile(models.Model):
user = models.OneToOneField(User, related_name='student_profile', on_delete=models.CASCADE)
slug = models.SlugField(blank=True, unique=True)
avatar = models.ImageField(upload_to='student_profile/', null=True, blank=True)
description = models.CharField(max_length=120, null=True, blank=True)
objects = models.Manager()
def __str__(self):
return self.user.username
def get_absolute_url(self):
return reverse("students:student_profile_view", kwargs={"slug": self.slug})
I am pretty new to class based view so maybe I'm doing something wrong there?
I assume you do not have the user within the form so you need the form
def get_context_data (self, *args, **kwargs)
ctx = super().get_context_data(*args, **kwargs)
if self.request.method == 'POST':
ctx['form'] = EditProfileForm(instance=self.request.user)
and remove def form_valid()

django class view Overlapping

I am not good at English.
Please understand me.
I'm creating a blog in Django.
I am making it into class view, but I want to see a reple list and form in the post details view.
like this
enter image description here
POST detailview has already been implemented and I don't know how to add comments.
Should I be function view?
Give me some advice.
code
views.py
class BlogLV(LoginRequiredMixin,ListView):
model = Blog
def get_queryset(self):
return Blog.objects.exclude(user=self.request.user)
class BlogCV(LoginRequiredMixin,CreateView): # blog_form.html
model = Blog
fields = ['name','description','image']
success_url = reverse_lazy('blog:index')
def form_valid(self, form): #오류
form.instance.user = self.request.user #user 설정
form.instance.slug = self.request.user
return super(BlogCV,self).form_valid(form)
class BlogDV(LoginRequiredMixin,DetailView):
model = Blog
class PostCreateView(LoginRequiredMixin,CreateView):
model = Post
fields = ['title', 'content']
success_url = reverse_lazy('blog:index')
template_name = 'blog/post_form.html'
def get_context_data(self, **kwargs):
context = super(PostCreateView, self).get_context_data(**kwargs)
context['blog'] = Blog.objects.get(slug=self.kwargs['slug'])
return context
def form_valid(self, form):
form.instance.user = self.request.user
form.instance.slug = self.request.user
return super(PostCreateView, self).form_valid(form)
class PostDV(LoginRequiredMixin,DetailView):
model = Post
fields =['title','content']
def get_context_data(self, **kwargs):
context = super(PostDV, self).get_context_data(**kwargs)
context['blog'] = Blog.objects.get(slug=self.kwargs['slug'])
return context
class PostLV(LoginRequiredMixin,ListView):
model = Post
paginate_by = 5
def get_context_data(self, *, object_list=None, **kwargs):
context = super(PostLV,self).get_context_data(**kwargs)
context['blog'] = Blog.objects.get(slug=self.kwargs['slug'])
return context
def get_queryset(self):
return Post.objects.filter(slug=self.kwargs['slug'])
class PostDeleteView(LoginRequiredMixin,DeleteView):
model = Post
success_url = reverse_lazy('blog:index')
def get_context_data(self, *, object_list=None, **kwargs):
context = super(PostDeleteView,self).get_context_data(**kwargs)
context['blog'] = Blog.objects.get(slug=self.kwargs['slug'])
return context
class PostUV(LoginRequiredMixin,UpdateView):
model = Post
fields = ['title','content']
success_url = reverse_lazy('blog:index')
def get_context_data(self, *, object_list=None, **kwargs):
context = super(PostUV,self).get_context_data(**kwargs)
context['blog'] = Blog.objects.get(slug=self.kwargs['slug'])
return context
urls.py
urlpatterns = [
url(r'^$',BlogLV.as_view(),name="index"),
url(r'^create/$',BlogCV.as_view(),name='blog_create'),
url(r'^(?P<slug>[-\w]+)/$',BlogDV.as_view(),name='blog_detail'),
url(r'^(?P<slug>[-\w]+)/post/create/$',PostCreateView.as_view(),name='post_create'),
url(r'^(?P<slug>[-\w]+)/post/$',PostLV.as_view(),name='post_list'),
url(r'^(?P<slug>[-\w]+)/post/(?P<pk>[0-9]+)/$', PostDV.as_view(), name='post_detail'),
url(r'^(?P<slug>[-\w]+)/update/(?P<pk>[0-9]+)/$', PostUV.as_view(), name='post_update'),
url(r'^(?P<slug>[-\w]+)/delete/(?P<pk>[0-9]+)/$', PostDeleteView.as_view(), name='post_delete'),
]
models.py
#python_2_unicode_compatible
class Blog(models.Model): # 유저 당 하나
name = models.CharField(max_length=20)
description = models.CharField(max_length=30)
image = models.ImageField(upload_to='blog/profile')
create_date = models.DateTimeField(auto_now_add=True)
slug = models.SlugField(unique=True,allow_unicode=True)
# 블로그 생성한 시각
# 저장 경로: MEDIA_ROOT/blog/projile/xxx.jpg 파일 저장
# DB 필드 'MEDIA_URL/blog/profile/xxx.jpg' 문자열 저장
user = models.OneToOneField(User)
class Meta:
ordering = ['-create_date']
# 생성된 날짜의 내림차순으로 정렬
def __str__(self):
return self.name
#python_2_unicode_compatible
class Post(models.Model):
title = models.CharField(max_length=30)
content = models.TextField()
create_date = models.DateTimeField(auto_now_add=True)
modify_date = models.DateTimeField(auto_now=True)
user = models.ForeignKey(User)
slug = models.SlugField(allow_unicode=True,default='slug')
class Meta :
ordering = ['-create_date']
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('blog:post_detail',args=(self.id,))
# post.get_absolute_url args
# 객체가 지칭하는 url 반환
def get_previous_post(self):
return self.get_previous_by_create_date()
#create_date 기준으로 이전 포스트 반환
# get_previous_by_column 내장객체 호출
def get_next_post(self):
return self.get_next_by_create_date()
#python_2_unicode_compatible
class Reple(models.Model):
content = models.TextField()
user = models.ForeignKey(User)
Post = models.IntegerField() # post_id
create_date = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ['-create_date']
def __str__(self):
return self.content
It's my first time writing, so I don't know how to Indent. Sorry
And if my code is not effective, tell me how to fix it.
thank you!
It might be easier to write the view from scratch as a function, but you can also override the existing post method to return additional data.

django - different inlines for different users

I have these models
class Office(models.Model):
name = models.CharField(max_length=255)
class User(models.Model):
name = models.CharField(max_length=255)
status = models.SmallIntegerField()
office = models.ForeignKey(Office, on_delete=models.SET_NULL, null=True)
class Inspection(models.Model):
place = models.CharField(max_length=255, null=True, blank=True)
class Jobs(models.Model):
inspection = models.ForeignKey(Inspection, on_delete=models.CASCADE)
inspector = models.ForeignKey(User, on_delete=models.SET_NULL)
cost = models.DecimalField(max_digits=20, decimal_places=2)
I have different users: common users(status=1) and admins(status=2).
Common users can make and see Jobs only with Inspectors from the same office.
Admins can put any user into Inspectors and see all Jobs.
I can filter job list for users in the same office:
class JobAdmin(admin.StackedInline):
model = Job
extra = 0
def get_queryset(self, request):
qs = super(JobAdmin, self).get_queryset(request)
if request.user.status in [1]:
qs = qs.filter(inspector__office=request.user.office)
return qs
class InspectionAdmin(ModelAdmin):
list_display = ['place']
inlines = [JobAdmin]
But how can I add additional filters for editing?
If it was not an inline form I would do it this way:
class JobAdminForm(ModelForm):
def __init__(self, *args, **kwargs):
super(JobAdminForm, self).__init__(*args, **kwargs)
if self.user.status == 1: #common user
self.fields['inspector'].queryset = Inspector.objects.filter(office=self.user.office)
class Meta:
model = Jobs
fields = '__all__'
class JobAdmin(ModelAdmin):
form = JobAdminForm
def get_form(self, request, obj=None, **kwargs):
form = super(JobAdmin, self).get_form(request, **kwargs)
form.user = request.user
return form
Maybe this code will be helpfull:
class JobAdmin(admin.StackedInline):
model = Job
extra = 0
def get_queryset(self, request):
qs = super(JobAdmin, self).get_queryset(request)
if request.user.status in [1]:
qs = qs.filter(inspector__office=request.user.office)
return qs
def formfield_for_foreignkey(self, db_field, request=None, **kwargs):
if db_field.name == "inspector" and request.user.status == 1:
kwargs['queryset'] = Inspector.objects.filter(office=request.user.office)
return super().formfield_for_foreignkey(db_field, request, **kwargs)
P.S. Link to Django documentation: formfield_for_foreignkey