django ValueError Cannot query "abcd#gmail.com": Must be "object" instance - python

i am trying to make an app for student but i'm getting this error,
as you can see for convenient i wanted to use like that one i showed bellow but it doesn't work, should i keep using like before? or i could use like that ? what would be best way ?
ValueError at /student/program_structure/
Cannot query "abcd#gmail.com": Must be "Student" instance.
thank you so much :)
models.py
class Student(models.Model):
user = models.ForeignKey(
settings.AUTH_USER_MODEL, on_delete=models.CASCADE, null=True)
status = models.CharField(max_length=10, choices=STATUS, default='active')
class Program(models.Model):
#everything was fine when used
user = models.ForeignKey(
settings.AUTH_USER_MODEL, on_delete=models.CASCADE, null=True) #this one
#but when using this one i started getting this error from views.py
user = models.ForeignKey(
Student, on_delete=models.SET_NULL, null=True)
name = models.CharField(max_length=200, unique=True)
prefix = models.CharField(max_length=20)
class Course(models.Model):
user = models.ForeignKey(Student, on_delete=models.SET_NULL, null=True)
name = models.CharField(max_length=200, unique=True)
prefix = models.CharField(max_length=20)
code = models.CharField(max_length=20)
subject = models.ManyToManyField('Subject', related_name='subject_list',
blank=True)
views.py
class Program_structure(generic.View):
def get(self, *args, **kwargs):
profile = get_object_or_404(Student, user=self.request.user)
program_structure = Course.objects.filter(student=profile)
# program_structure =
Course.objects.filter(student__user=self.request.user)
credit = Course.objects.filter(student__user=self.request.user).
annotate(total_no=Sum('subject__credit'))
total_credit = self.request.user.course_set.aggregate(
total_credit=Sum('subject__credit')
)['total_credit'] or 0
context = {
'test':program_structure,
'credit':credit,
'profile':profile,
'total_credit' : total_credit
}
return render(self.request, 'program_structure.html', context)

The user field of the Course refers to the Student object, not a User object, so you can not user request.user for this.
You can however query for a Course where the user is a Student where the user is request.user with:
class Program_structure(generic.View):
def get(self, *args, **kwargs):
profile = Student.objects.all()
program_structure = Course.objects.filter(user__user=self.request.user)
context = {
'test':program_structure,
'profile':profile,
}
return render(self.request, 'program_structure.html', context)
You probably also want to set profile to the Student object of the user. In that case, you can reuse the profile when you filter the Courses:
from django.shortcuts import get_object_or_404
class Program_structure(generic.View):
def get(self, *args, **kwargs):
profile = get_object_or_404(Student, user=request.user)
program_structure = Course.objects.filter(user=profile)
context = {
'test':program_structure,
'profile':profile,
}
return render(self.request, 'program_structure.html', context)
It might also be better to rename the user field to student:
class Course(models.Model):
student = models.ForeignKey(
Student,
on_delete=models.SET_NULL,
null=True
)
# …
since that makes it clear that this is a Student, not a User. In that case you filter with:
from django.shortcuts import get_object_or_404
class Program_structure(generic.View):
def get(self, *args, **kwargs):
profile = get_object_or_404(Student, user=request.user)
program_structure = Course.objects.filter(student=profile)
context = {
'test':program_structure,
'profile':profile,
}
return render(self.request, 'program_structure.html', context)

Related

How to hide or modify <pk> in url in Django app?

In my url.py I have:
path('gpd/<pk>/', views.gpd, name='gpd'),
my view.py looks like:
#login_required(login_url='login')
def gpd(request,pk):
current_gpd = get_gpd(pk)
context = {'current_gpd ':current_gpd ,
'pk':pk, }
return render(request, 'app/gpd/gpd_form.html', context)
def get_gpd(id):
return GPD.objects.get(id=id)
I have noticed, that when my logined user change manually pk - then he has an access to page with another pk. How to prevent it?
my GPG model:
class GPD(models.Model):
id = models.AutoField(primary_key=True)
employee = models.ForeignKey(Employee, verbose_name='Employee', on_delete = models.CASCADE, related_name='+')
class Employee(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=30, verbose_name='Name')
def get_gpd(id,user):
return GPD.objects.get(id=id, employee=user)
so pass in the request.user

UserCheckout matching query does not exist

I'm trying to display all orders matching each logged in user, I dont understand why it gives me issues when trying to filter for users as it gives me that UserCheckout does not have any matching queries:
orders/views.py
class OrderList(LoginRequiredMixin, ListView):
queryset = Order.objects.all()
def get_queryset(self):
user_check_id = self.request.user.id
user_checkout = UserCheckout.objects.get(id=user_check_id)
return super(OrderList, self).get_queryset().filter(user=user_checkout)
orders/mixins.py
class LoginRequiredMixin(object):
#method_decorator(login_required)
def dispatch(self, request, *args, **kwargs):
return super(LoginRequiredMixin, self).dispatch(request,*args, **kwargs)
orders/models.py
class UserCheckout(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL, null=True, blank=True, on_delete = models.CASCADE) # not required as to allow guests to checkout too
email = models.EmailField(unique=True) # required, unique as if there the guest already has an authentication just one email needed
def __str__(self):
return self.email
class Order(models.Model):
status = models.CharField(max_length=120, choices=ORDER_STATUS_CHOICES, default='created')
cart = models.ForeignKey(Cart, on_delete=models.CASCADE)
user = models.ForeignKey(UserCheckout, null=True, on_delete=models.CASCADE)
billing_address = models.ForeignKey(UserAddress, related_name='billing_address', null=True,on_delete=models.CASCADE)
shipping_address = models.ForeignKey(UserAddress, related_name='shipping_address', null=True, on_delete=models.CASCADE)
shipping_total_price = models.DecimalField(max_digits=50, decimal_places=2, default=5.99)
order_total = models.DecimalField(max_digits=50, decimal_places=2)
def __str__(self):
return str(self.cart.id)
Error it gives me:
DoesNotExist at /orders/
UserCheckout matching query does not exist.
You are getting an error because you are trying to use the User's primary key (id) as the UserCheckout's primary key i.e. the lines:
user_check_id = self.request.user.id
user_checkout = UserCheckout.objects.get(id=user_check_id)
Change these lines to:
user = self.request.user
user_checkout = UserCheckout.objects.get(user=user)
Also this can throw an Exception if a UserCheckout instance doesn't exist you can catch that using try-except or use django's shortcut function get_object_or_404:
from django.shortcuts import get_object_or_404
user_checkout = get_object_or_404(UserCheckout, user=user)

How to add request.user to manytomanyfield for team members in django?

I was trying to create a custom team model having a manytomanyfield for team members, now i have a form that allows users to create their own team(s), but i dont understand how i can add request.user to the members of the team. Below are the codes:
models.py
class Team(models.Model):
name = models.CharField(max_length=64, unique=True)
description = models.CharField(max_length=1024)
created_at = models.DateTimeField(auto_now_add=True)
members = models.ManyToManyField(User, through='Member')
def __str__(self):
return f"Team: {self.name} created on {self.created_at}\nMember(s): {self.members}"
class Member(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
team = models.ForeignKey(Team, on_delete=models.CASCADE, blank=True)
forms.py
class TeamRegistrationForm(ModelForm):
class Meta:
model = Team
fields = ["name", "description"]
views.py
#login_required(login_url="/login/")
def teamregister(request):
if request.method == "POST":
form = TeamRegistrationForm(request.POST)
if form.is_valid():
form.save()
form.instance.members.add(request.user) # doesn't work :[
print(form.save())
messages.success(request, "Your team has been successfully registered!")
return redirect("dashboard")
else:
form = TeamRegistrationForm()
return render(request, "users/team.html", {"form": form})
I tried to use form.instance.members.add(request.user) to add the logged in user to the member of the team but it didn't work. Please help :[
It is added to the relation, but you do not print the items in the relation. You print the manager. Indeed, you write {self.members}, and that is the manager, you should rewrite this to {self.manager.all()}. A Manager will, unless you implement it otherwise return ModelName.None:
class Team(models.Model):
# …
def __str__(self):
return f'Team: {self.name} created on {self.created_at}\nMember(s): {self.members.all()}'

UpdateView does not show existing data when using filter

I am quite new with Django and I need help.
My problem is quite similar what Mike had in his case:
UpdateView not populating form with existing data, but I have not found solution yet.
My goal is to view owner dropdown selection list only those users who are members of the organization.
models.py
# organizations.models.py
...
from accounts.models import User
from core.models import TimeStampModel
...
class Organization(TimeStampModel, models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
name = models.CharField(
verbose_name=_('Name'),
max_length=255,
unique=True
)
code = models.CharField(
verbose_name=_('Code'),
max_length=255,
null=True,
blank=True
)
owner = models.ForeignKey(
User,
on_delete=models.PROTECT,
verbose_name=_('Owner'),
related_name='owner',
help_text=_('Organization Owner and Contact Person'),
)
slug = models.SlugField(verbose_name=_('Organization key'), unique=True)
...
class Meta:
verbose_name = _('Organization')
verbose_name_plural = _('Organization')
ordering = ['name', 'code']
def __str__(self):
return f'{self.name}, {self.code}'
# Create automatically slug value from organization name field.
# In case similar is exist then add extra count digit end of slug.
def _get_unique_slug(self):
slug = slugify(self.name)
unique_slug = slug
num = 1
while Organization.objects.filter(slug=unique_slug).exists():
unique_slug = '{}-{}'.format(slug, num)
num += 1
return unique_slug
def save(self, *args, **kwargs):
if not self.slug:
self.slug = self._get_unique_slug()
self.next_update = timezone.now() + relativedelta(
months=self.update_interval)
super(Organization, self).save(*args, **kwargs)
def get_absolute_url(self):
kwargs = {
'slug': self.slug
}
return reverse('organization_main_page', kwargs=kwargs)
class OrganizationMembers(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
organization = models.ForeignKey(
Organization,
on_delete=models.CASCADE,
verbose_name=_('Organization')
)
member = models.ForeignKey(
User,
on_delete=models.CASCADE,
verbose_name=_('Member'),
null=True,
blank=True
)
organization_admin = models.BooleanField(
verbose_name=_('Organization admin'),
default=False
)
class Meta:
verbose_name = _('Organization: Member')
verbose_name_plural = _('Organization: Members')
ordering = ['organization', 'member']
unique_together = ('organization', 'member')
def __str__(self):
return f'{self.member}'
def get_absolute_url(self):
kwargs = {
'slug': self.slug
}
return reverse('organization_detail', kwargs=kwargs)
forms.py
# organizations.forms.py
....
from accounts.models import User
from .models import Organization, OrganizationMembers
...
class OrganizationUpdateForm(forms.ModelForm):
class Meta:
model = Organization
fields = '__all__'
exclude = ('date_created', 'created_by', 'created_by_id',
'last_updated', 'last_updated_by', 'last_updated_by_id',
'next_update', 'slug')
# Restrict user selection lists to view only members of the organization
def __init__(self, *args, **kwargs):
inst = kwargs.get('instance', None)
super(OrganizationUpdateForm, self).__init__(*args, **kwargs)
self.fields['owner'].queryset = OrganizationMembers.objects.\ # <--- !!!
filter(organization_id=inst.id)
In the forms.py, if I comment out self.field['owner]... line, then owner field will show saved value from database, but then I can see all users in the dropdown list. When queryset is enabled then selection list show correct users, but saved value is not visible.
views.py
# organizations.views.py
from .forms import OrganizationUpdateForm
from accounts.models import User
from .models import Organization, OrganizationMembers
class OrganizationUpdateView(LoginRequiredMixin, UpdateView):
model = Organization
form_class = OrganizationUpdateForm
template_name = 'organizations/organization_update.html'
success_url = reverse_lazy('organizations')
# Save data and set current user to last updated by fields
def form_valid(self, form):
object = form.save(commit=False)
object.last_updated_by = self.request.user.get_full_name()
object.last_updated_by_id = self.request.user
return super(OrganizationUpdateView, self).form_valid(form)
def get_queryset(self):
criteria1 = Q(owner=self.request.user)
criteria2 = Q(organizationmembers__member=self.request.user)
criteria3 = Q(organizationmembers__organization_admin=1)
org_list = Organization.objects.\
filter(criteria1 | (criteria2 & criteria3)).distinct()
if org_list.count() != 0:
return org_list
else:
raise Http404('You don\'t have permissions!')
In Mikes case Chiheb has commented that "With UpdateView it's a little bit tricky. So, in order to initialize your form's data, you need to do it in the view itself not in the form."
What is the reason that cannot add filter to UpdateView?
Please can someone help me to solve my problem. Thanks.
UPDATE
Not filtered. Value from database is visible
Not filtered. Dropdown list show all users in the system
Filter enabled. Value is not visible
Filter enabled. Dropdown list show correct valeus
The problem is that owner in your models is a FK to User model, but you are filtering queryset in form by OrganizationMembers. Make it the same and the problem should be gone.

Django model foreignkey always defaults no matter what user is logged in

I have this django model for questions.
class Question(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, default=1, null=True, on_delete=models.SET_NULL)
question_id = models.CharField(max_length=150, null=False, default=get_id, unique=True, editable=False)
question = models.CharField(max_length=150, null=False)
question_description = FroalaField()
created_at = models.DateTimeField(auto_now=False, auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True, auto_now_add=False)
question_image = models.ImageField(upload_to=get_upload_path, blank=True, null=True)
height_field = models.IntegerField(default=0)
width_field = models.IntegerField(default=0)
dynamic_link = models.CharField(max_length=225, null=False, default="")
question_type = models.CharField( max_length=50, null=False, choices=QUESTIONSTYPE_LIST)
question_status = models.CharField(max_length=150, null=False, default="unapproved")
is_active = models.BooleanField(default=False)
objects = QuestionManager()
class Meta:
ordering = ['-updated_at']
def __str__(self):
return self.question_id
def get_absolute_url(self):
kwargs = {
'questiontype': slugify(self.question_type),
'questionid': self.question_id,
'slug': slugify(self.question)
}
return reverse("questions:detail", kwargs=kwargs)
Everything seems to be working okay, except that the user user = models.ForeignKey(settings.AUTH_USER_MODEL, default=1, null=True, on_delete=models.SET_NULL)
always saves but the default which is 1. So no matter which user is logged in and in session, it always defaults to 1.
I am using classed-based-views and the user is a CustomUser.
I have the customUser set in settings.py auth_model_user as:
AUTH_USER_MODEL = 'users.CustomUser'
Here is the form for Question:
class QuestionCreationUpdateForm(forms.ModelForm):
question = forms.CharField(widget=forms.TextInput(attrs={
'class': 'frm-input',
'placeholder': _('Enter question title'),
'autocomplete': 'off'
}))
question_type = forms.ChoiceField(choices=QUESTIONSTYPE_LIST, widget=forms.Select(attrs={'class': 'frm-input'}))
question_description = forms.CharField(widget=FroalaEditor)
def __init__(self, *args, **kwargs):
super(QuestionCreationUpdateForm, self).__init__(*args, **kwargs)
class Meta:
model = Question
fields = ('question', 'question_description', 'question_type')
And the question CreateView:
# Add Question View
#method_decorator(login_required, name='dispatch')
class AskQuestionView(CreateView):
template_name = 'ask_question.html'
form_class = QuestionCreationUpdateForm
model = Question
def form_valid(self, form):
try:
return super(AskQuestionView, self).form_valid(form)
except IntegrityError:
context = {
'msg': _('We don\'t allow continues posting! Take a break. Try again later!')
}
return render(self.request, "500.html", context)
def get_success_url(self):
return self.object.get_absolute_url()
If I do a request.user in the views.py file, I always get the right user.
So why is my model behaving this odd?
As I can see, you need to assign the User object to form instance. Like this:
#method_decorator(login_required, name='dispatch')
class AskQuestionView(CreateView):
...
def form_valid(self, form):
try:
obj = form.save(commit=False)
obj.user = self.request.user
return super(AskQuestionView, self).form_valid(obj)
except IntegrityError:
context = {
'msg': _('We don\'t allow continues posting! Take a break. Try again later!')
}
return render(self.request, "500.html", context)
# ^^ consider using a 400 error response, as 500 is for server error response. 400 is for bad request
...
You are not assigning any user to Question.user. You need to assign the current user to that field.
#method_decorator(login_required, name='dispatch')
class AskQuestionView(CreateView):
template_name = 'ask_question.html'
form_class = QuestionCreationUpdateForm
model = Question
def form_valid(self, form):
try:
form.instance.user = self.request.user
return super(AskQuestionView, self).form_valid(form)
except IntegrityError:
context = {
'msg': _('We don\'t allow continues posting! Take a break. Try again later!')
}
return render(self.request, "500.html", context)
Further read Models and request.user

Categories

Resources