UserCheckout matching query does not exist - python

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)

Related

Unable to POST the data using rest Django - NOT NULL constraint failed: author_id

I have the following error, and I guess the problem with how can I add the author id to the post automatically.
And also I tried to add null=True
author = models.ForeignKey(User, null=True, blank=True)
The error disappeared, but unfortunately, the author's id is still null.
IntegrityError at /auctions/api/addAuction/
NOT NULL constraint failed: auctions_auction.author_id
Request Method: POST
Request URL: http://127.0.0.1:8000/auctions/api/addAuction/
Django Version: 3.1.5
Exception Type: IntegrityError
Exception Value:
NOT NULL constraint failed: auctions_auction.author_id
/auctions/api/serializers.py
class AddAuctionsSerializer(serializers.ModelSerializer):
print("AddA uctionsSerializer Function call")
class Meta:
model = Auction
# Get the current user from request context
def validate_author(self, value):
return self.context['request'].user
author_id = serializers.Field(source='author.id')
fields = ["title", "desc", "image","location","min_value","date_added","author_id"]
read_only_fields = ('author','id','author_id','author.id')
/auctions/api/view.py
class addAuction(APIView):
#permission_classes = [permissions.IsAuthenticated]
#authentication_classes = [SessionAuthentication, BasicAuthentication]
def pre_save(self, obj):
obj.owner = self.request.user
def post(self, request, format=None):
auction = Auction()
auction.author = request.user
serializer = AddAuctionsSerializer(data=request.data)
print(serializer)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
/auctions/api/url.py
path('addAuction/', addAuction.as_view()),
/auctions/model.py
class Auction(models.Model):
location = LocationField()
author = models.ForeignKey(User, on_delete=models.CASCADE,null=False)
# author = models.ForeignKey(User, null=True, blank=True)
title = models.CharField(max_length=300)
desc = models.CharField(max_length=2000, blank=True)
image = models.ImageField(upload_to='auction_images/', blank=True, default = 'auction_images/default/default.svg')
min_value = models.IntegerField()
#date_added = models.DateTimeField()
date_added = models.DateTimeField(auto_now_add=True)
is_active = models.BooleanField(default=True)
winner = models.ForeignKey(User, on_delete=models.SET("(deleted)"),
blank=True,
null=True,
related_name="auction_winner",
related_query_name="auction_winner")
final_value = models.IntegerField(blank=True, null=True)
def resolve(self):
if self.is_active:
# If expired
if self.has_expired():
# Define winner
highest_bid = Bid.objects.filter(auction=self).order_by('-amount').order_by('date').first()
if highest_bid:
self.winner = highest_bid.bidder
self.final_value = highest_bid.amount
self.is_active = False
self.save()
# Helper function that determines if the auction has expired
def has_expired(self):
now = datetime.now(timezone.utc)
expiration = self.date_added + timedelta(minutes=AUCTION_DURATION)
if now > expiration:
return True
else:
return False
# Returns the ceiling of remaining_time in minutes
#property
def remaining_minutes(self):
if self.is_active:
now = datetime.now(timezone.utc)
expiration = self.date_added + timedelta(minutes=AUCTION_DURATION)
minutes_remaining = ceil((expiration - now).total_seconds() / 60)
return(minutes_remaining)
else:
return(0)
Try using SlugRelatedField instead of Field.
Like so:
class AddAuctionsSerializer(serializers.ModelSerializer):
# instead of this:
# author_id = serializers.Field(source='author.id')
# do this:
author = serializers.SlugRelatedField(queryset=User.objects.all(), slug_field='id', write_only=True)
class Meta:
model = Auction
fields = ["title", "desc", "image","location","min_value","date_added","author"]
# don't put 'author_id' in read_only, because creating is "writing"
# also note that 'author.id' is invalid field
# read_only_fields = ('author','id','author_id','author.id')
read_only_fields = ('id')
# Get the current user from request context
def validate_author(self, value):
return self.context['request'].user
I had the same problem.
You can solve it by overwriting the create method of AddAuctionsSerializer and manually defining instance.author, or by passing the parameter author = request.user, to the save method of AddAuctionsSerializer,

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

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)

what am I doing wrong at the moment to validate my lesson class?

I want to validate if my lesson material belongs to a xyz user with pro right it will show the correct conent, but if not it will display become a member , but however I am getting if I change id membership to pro or vice versa it always true the statement
def get(self, request):
template = loader.get_template(self.template_name)
template_member = loader.get_template(self.template_payment)
#rendering the template in HttpResponse
lesson = Lesson.objects.first()
user_membership = UserMembership.objects.filter(user=self.request.user).first()
user_membership_type = user_membership.membership.membership_type
lesson_allowed_mem_types = lesson.allowed_memberships.all()
if lesson_allowed_mem_types.filter(membership_type=user_membership_type).exists():
return HttpResponse(template.render())
else:
return HttpResponse(template_member.render())
models
class Lesson(models.Model):
allowed_memberships = models.ManyToManyField(Membership)
class Membership(models.Model):
membership_type = models.CharField(
choices=MEMBERSHIP_CHOICES,
default='Free',
max_length=30)
def __str__(self):
return self.membership_type
class UserMembership(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
membership = models.ForeignKey(Membership, on_delete=models.SET_NULL, null=True)
def __str__(self):
return self.user.email
Aren't you just trying to see if the user has a Membership?
if UserMembership.objects.filter(
user=request.user,
membership__membership_type="PAID MEMBER",
).exists():
# user is member
return HttpResponse(template.render())
else:
# user is not a member
return HttpResponse(template_member.render())

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.

post list of device id in a group

The design of my api is
{
"id": "667c476ca953483493afa265e5d500b0",
"name": "Home"
}
This is the result of GET API. In posting, i want the list of devices to be posted. For example, if user want to post devices to Home group, then the url i have designed is /group/group_token/add(/group/667c476ca953483493afa265e5d500b0/add). The data sending format is
{
"devices":[<device_id1>, <device_id2>]
}
i.e
{
"devices":"[5ac41ba7e6ae4628982b2c81c99343a8], [7nu21ba7e6ae4628982b2c81c99343a8]"
}
Here is my model, serializer and APIView i have done so far
class BaseDevice(PolymorphicModel):
name = models.CharField(max_length=250, blank=False, null=False)
owner = models.ForeignKey(User, blank=False, null=False)
token = models.UUIDField(default=uuid.uuid4, unique=True, editable=False)
group = models.ForeignKey('DeviceGroup', related_name="groups", null=True, blank=True)
class Device(BaseDevice):
description = models.TextField(blank=True, null=True)
class DeviceGroup(models.Model):
token = models.UUIDField(default=uuid.uuid4, unique=True, editable=False)
name = models.CharField(max_length=250, blank=False, null=False)
owner = models.ForeignKey(User, blank=False, null=False)
class DeviceGroupSerializer(serializers.ModelSerializer):
id = serializers.UUIDField(source='token', format='hex', read_only=True)
class Meta:
model = DeviceGroup
fields = ['id','name']
class DevicesGroupsAPIView(APIView):
permission_classes = (permissions.IsAuthenticated,)
def get_serializer_class(self):
if self.request.user.is_staff:
return DeviceGroupSerializer
def get_object(self, user, token):
try:
return BaseDevice.objects.filter(owner=user).get(token=token)
except ObjectDoesNotExist:
return error.RequestedResourceNotFound().as_response()
def get(self, request, format=None):
reply = {}
try:
groups = DeviceGroup.objects.filter(owner=request.user)
reply['data'] = DeviceGroupSerializer(groups, many=True).data
except:
reply['data'] = []
return Response(reply, status.HTTP_200_OK)
def post(self, request, token=None, format=None):
device_group_instance = DeviceGroup.objects.get(token=token)
for device_token in request.data['devices']:
device = Device.objects.get(token=device_token, owner=request.user)
device.group = device_group_instance
device.save()
How can i do the posting? I get an error on token part. It says
DeviceGroup matching query does not exist.
How should my posting be?
UPDATE
Frist screenshot
The url is device_group/ . When i try to post from there. i get above error not matching query one
Second Screenshot
The url is in the screenshot browser. I dont get device list to post rather i see name field.
I'm not sure how this is supposed to work, but for whatever reason your post() function is not obtaining a valid token that matches an existing DeviceGroup.
Make sure that DeviceGroup is the model you are intending to call.
If you are manually instantiating post() somewhere else, check to see that a valid token is being passed to it.
Otherwise you will need to retrieve it in the function itself. For example, if the token is stored in a session variable, you can do:
def post(self, request, token=None, format=None):
token = request.session.token
device_group_instance = DeviceGroup.objects.get(token=token)
for device_token in request.data['devices']:
device = Device.objects.get(token=device_token, owner=request.user)
device.group = device_group_instance
device.save()

Categories

Resources