Matching query does not exist issue Django - python-3.x

I am trying to create a web app that has a Like button option for the Post. Everything works fine but when I click on the Like button it shows DoesNotExist error.
This is the model part of the code:
class Like(models.Model):
user = models.ForeignKey(Yatru, on_delete=models.CASCADE)
location = models.ForeignKey(Post, on_delete=models.CASCADE)
value = models.CharField(choices=LIKE_CHOICES, max_length=8)
updated = models.DateTimeField(auto_now=True)
created = models.DateTimeField(auto_now_add=True)
def __str__(self):
return f"{self.user}-{self.location}-{self.value}"
This is the views:
def like_unlike(request):
user = request.user
if request.method == 'POST':
location_id = request.POST.get('location_id')
location_obj = Post.objects.get(id=location_id)
profile = Yatru.objects.get(user=user)
if profile in location_obj.liked.all():
location_obj.liked.remove(profile)
else:
location_obj.liked.add(profile)
like, created = Like.objects.get_or_create(user=profile, location_id=location_id)
if not created:
if like.value=='Like':
like.value='Unlike'
else:
like.value='Like'
location_obj.save()
like.save()
return redirect('posts:post_views')
When I try to load the page it shows this error:
DoesNotExist at /posts/liked

Related

Field 'id' expected a number but got <User: ben>

I created a population script for a django website however, after running the script and making migrations, I logged in to the django admin page for my site to access the objects created using the script and could not do it for my Business model. It works fine for my other models.
I get this error when I try to access the registered Businesses in my database from the Django admin page. It does not seem to trace back to any of my code but rather to a template in the admin folder of my python environment. Here's the error message:
error message
Here are my models:
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
profile_pic = models.ImageField(upload_to="profile_images", blank=True, default="profile_images/default.png")
description = models.TextField(max_length=1024, default="")
# boolean flag for identifying business owners
is_business_owner = models.BooleanField(default=False)
def __str__(self):
return self.user.username
class Business(models.Model):
owner_fk = models.ForeignKey(User, on_delete=models.CASCADE)
name = models.CharField(max_length=128)
address = models.CharField(max_length=128)
img = models.ImageField(upload_to="business_images", blank=True)
slug = models.SlugField(unique=True)
class Meta:
verbose_name_plural = 'Businesses'
def save(self, *args, **kwargs):
self.slug = slugify(self.name)
super(Business, self).save(*args, **kwargs)
def __str__(self):
return f"{self.name} owned by {UserProfile.objects.get(pk=self.owner_fk).username}"
Here is how I created the objects through the population script:
def add_user(username, firstname, lastname, password, profile_pic, description,
is_business_owner):
new_user = User.objects.get_or_create(username=username, password=password,
first_name=firstname, last_name=lastname)
if new_user[1]:
new_profile = UserProfile(user=User.objects.get(username=username))
new_profile.profile_pic = profile_pic
new_profile.description = description
new_profile.is_business_owner = is_business_owner
new_profile.save()
def add_business(owner, name, address, img):
new_business = Business(name=name, owner_fk=User.objects.get(username=owner))
new_business.address = address
new_business.img = img
new_business.save()
Any help would be appreciated, thanks.
Your Business class has got __str__ method. You are trying to pass User object to pk (id) key.
class Business(models.Model):
def __str__(self):
return f"{self.name} owned by {UserProfile.objects.get(pk=self.owner_fk).username}"
Instead of searching User object in database Change it to:
return f"{self.name} owned by {self.owner_fk.username}"
because you don't have to search database for related object, just address it directly.

Deny to access to id of user in Foreignkey model

--WHY I CANT TO ACCESS TO ID OF USER AND PRODUCT WITH user__id and product__id?
i have error: (The view store.views.submit_review didn't return an HttpResponse object. It returned None instead).
<pre><code>
i define some code for rating post for any user user
--#views
def submit_review(request, product_id):
url = request.META.get('HTTP_REFERER')
if request.method == 'POST':
try:
reviews = ReviewRating.objects.get(user__id=request.user.id,Product__id=product_id) #my problem is here
form = Reviewform(request.POST, instance=reviews)
form.save()
messages.success(request, 'Thank you!your review has been updated.')
return redirect(url)
except ReviewRating.DoesNotExist:
form = Reviewform(request.POST)
if form.is_valid():
data = ReviewRating()
data.subject = form.cleaned_data['subject']
data.review = form.cleaned_data['review']
data.rating = form.cleaned_data['rating']
data.ip = request.META.get['REMOTE_ADDR']
data.product_id = product_id
data.user_id = request.user.id
data.save()
messages.success(request, 'Thank you! Your review has been submitted')
return redirect(url)
</code></pre>
this section i define model.I checked this part it work correctly
define model for views in my app
#models
class ReviewRating(models.Model):
Product = models.ForeignKey(product, on_delete=models.CASCADE)
user = models.ForeignKey(Account, on_delete=models.CASCADE)
subject = models.CharField(max_length=100, blank=True)
review = models.TextField(max_length=500, blank=True)
rating = models.FloatField()
ip = models.CharField(max_length=20, blank=True)
status = models.BooleanField(default=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.subject
this part i define url
#urls
define path for html and views
urlpatterns = [
path('submit_review/int:product_id/',views.submit_review,name='submit_review')
]
your model is not clear. It would be better if you could atleast share your full model.py file
if you provide the objective of your service with models.py, serializers.py, views.py I think I will be able to help more specifically
till now, one issue i've found in the the url section is that you need to add < > on int:product_id.
it should be,
urlpatterns = [
path('submit_review/<int:product_id>/',views.submit_review,name='submit_review')
]

NoReverseMatch at /NewListing

I have a form on my webpage for users to create a new listing. The form loads up okay but on submission an error comes up:
NoReverseMatch at /NewListing
Reverse for 'listing' with keyword arguments '{'listing': None}' not found. 1 pattern(s) tried: ['(?P<listing_id>[0-9]+)$']
The form does save the new listing and update the homepage with the new listing but I would like that once the listing is submitted, the user is taken to the new listing page and I can't seem to get that to work without this error popping up.
models.py
class Category(models.Model):
group = models.CharField(max_length=20)
def __str__(self):
return f"{self.group}"
class Listing(models.Model):
title = models.CharField(max_length=64)
description = models.TextField(max_length=64)
price = models.DecimalField(max_digits=9, decimal_places=2, validators=[MinValueValidator(0.99)])
image = models.URLField(max_length=200, blank=True)
category = models.ForeignKey(Category, on_delete=models.CASCADE, related_name="categories")
def __str__(self):
return f"Product: {self.title} \nDescription: {self.description} \nCurrent Price: £{self.price}\nImage: {self.image} \nCategory: {self.category}"
forms.py
class NewListingForm(forms.ModelForm):
class Meta:
model = Listing
fields = ["title", "description", "price", "image", "category"]
title = forms.CharField(widget=forms.TextInput(attrs={'autocomplete':'off'}))
description = forms.CharField(widget=forms.TextInput(attrs={'autocomplete':'off'}))
price = forms.DecimalField(label='Starting Bid Price (£)')
image = forms.URLField(widget=forms.URLInput(attrs={'autocomplete':'off'}))
views.py
def listing(request, listing_id):
listing = Listing.objects.get(pk=listing_id)
return render(request, "auctions/listingPage.html", {
"listing": listing
})
def newListing(request):
if request.method == "POST":
form = NewListingForm(request.POST)
if form.is_valid():
title = form.cleaned_data['title']
description = form.cleaned_data['description']
price = form.cleaned_data.get('price')
image = form.cleaned_data['image']
category = form.cleaned_data['category']
listing = Listing(title=title, description=description, price=price, image=image, category=category)
form.save()
return HttpResponseRedirect(reverse("listing", kwargs={'listing': listing.id}))
else:
return render(request, "auctions/newListing.html", {
"form": form,
})
else:
form = NewListingForm()
return render(request, "auctions/newListing.html", {
"form": form
})
urls.py
urlpatterns = [
path("", views.index, name="index"),
path("login", views.login_view, name="login"),
path("logout", views.logout_view, name="logout"),
path("register", views.register, name="register"),
path("<int:listing_id>", views.listing, name="listing"),
path("NewListing", views.newListing, name="newListing")
]
You're making a new Listing by hand from the form data, but never saving it, so it never gets an ID.
As a result, the URL that your code tries to compute as the redirection destination uses None instead of an integer for the listing ID, which blows up, because it's expecting an integer ID.
(You also save the modelform, but you don't do anything with the data that returns.)
Instead of this:
listing = Listing(title=title, description=description, price=price,image=image, category=category)
form.save()
Try just:
listing = form.save()
to let the ModelForm do all the heavy lifting and return saved object with an ID because it's in the database - that's what model forms are there for :o) https://docs.djangoproject.com/en/3.1/topics/forms/modelforms/#the-save-method

Django3.0 add request.user to form request

Let's say we have this model:
class Creation(models.Model):
title = models.CharField(max_length=DEFAULT_LENGTH)
url = models.CharField(max_length=DEFAULT_LENGTH)
date = models.DateTimeField('date published', default=datetime.date.today)
author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.PROTECT)
def __str__(self):
return self.title
And let's use this view:
def submit(request):
FormSet = modelformset_factory(Creation, fields=('title', 'url'))
if request.method == 'POST':
formset = FormSet(request.POST, request.FILES)
if formset.is_valid():
obj = formset.save(commit=False)
obj.author = request.user
obj.save()
else:
formset = FormSet
return render(request, 'app/submit.html', {'formset': formset})
I saved formset to obj and added request.user and committed it to the database.
This doesn't work, because now django throws an error which says
'list' object has no attribute 'author'
which makes perfectly sense, because there is no author in the fields-list above.
But if I add 'author' to fields, another selectbox would be displayed while rendering the template via {{formset}}.
Maybe I could code my own template-code instead of using {{formset}} and omit the author, but I feel that there must be a more elegant way with Django3.0. Is there any?
All I want to do is to get the foreignkey author (see model above) filled with the logged in user.
Turns out that something is wrong with modelformset_factory(..).
If you use a proper CreationForm in models.py:
class CreationForm(ModelForm):
class Meta:
model = Creation
fields = ['title', 'url']
and use it in your views.py:
formset = CreationForm(request.POST)
if request.method == 'POST':
if formset.is_valid():
f = formset.save(commit=False)
f.author = request.user
f.save()
it works.

Edit user profiles form without using django admin

I am developing a simple LMS system where I have 3 stakeholders Administrator, Faculty Members and Students. Administrator can create, edit, delete, block and list user accounts, with my developement so far I am able to create and list all users.
Now I am stuck at editing user profile, my requirement is when I click on any listed users it should open my extended/customized user profile in a form and I should have the ability to edit any opened user profile.
Below are my code snippets:
MODELS.PY:
from django.contrib.auth.models import User
class UserInformation(models.Model):
user = models.ForeignKey(User, unique=True)
degree = models.ForeignKey(Degree, null=True, blank=True)
stakeholder = models.ForeignKey(Stakeholder)
cell_number = models.CharField(max_length=32, null=True, blank=True)
def __str__(self):
return self.user.username
VIEWS.PY (to create user):
def ad_create_user(request):
if request.method == 'POST':
firstname = request.POST['firstname']
lastname = request.POST['lastname']
username = request.POST['username']
password = request.POST['password']
email = request.POST['email']
group = request.POST['group']
degree = request.POST['degree']
cell_no = request.POST['cell_no']
new_user = User.objects.create_user(username, email, password)
new_user.first_name = firstname
new_user.last_name = lastname
new_user.save()
if group == 'option_one':
set_group = 3
new_user.groups.add(3)
userinfo = UserInformation(user=User.objects.get(username=username), degree=Degree.objects.get(pk=degree),
stakeholder=Stakeholder.objects.get(pk=set_group), cell_number=cell_no)
userinfo.save()
if group == 'option_two':
set_group = 2
new_user.groups.add(2)
userinfo = UserInformation(user=User.objects.get(username=username),
stakeholder=Stakeholder.objects.get(pk=set_group), cell_number=cell_no)
userinfo.save()
if group == 'option_three':
set_group = 1
new_user.groups.add(1)
userinfo = UserInformation(user=User.objects.get(username=username),
stakeholder=Stakeholder.objects.get(pk=set_group), cell_number=cell_no)
userinfo.save()
return HttpResponseRedirect('/administrator/user_management/')
return render(request, 'MobiApp/create_user.html', {'form': CreateUserForm()})
FORMS.PY (to create user):
class CreateUserForm(forms.Form):
firstname = forms.CharField(max_length=64)
lastname = forms.CharField(max_length=64)
username = forms.CharField(max_length=16)
password = forms.CharField(
widget=forms.PasswordInput(),
)
email = forms.EmailField()
group = forms.ChoiceField(
choices=(
('option_one', "Student"),
('option_two', "Faculty Member"),
('option_three', "Administrator"),
),
widget = forms.RadioSelect,
initial = 'option_one',
)
degree = forms.ModelChoiceField(queryset=Degree.objects.all())
cell_no = forms.CharField()
helper = FormHelper()
helper.form_class = 'form-horizontal'
helper.layout = Layout(
Field('firstname', css_class='input-xlarge'),
Field('lastname', css_class='input-xlarge'),
Field('username', css_class='input-xlarge'),
Field('password', css_class='input-xlarge'),
Field('email', css_class='input-xlarge'),
'group',
'degree',
Field('cell_no', css_class='input-xlarge'),
FormActions(
Submit('create', 'Create!', css_class="btn-primary"),
)
)
I found many questions similar to this but none of them helped me and my requirement is also little different as user is not editing his/her profile but administrator is editing profile of any user.
Just for your information:
I am using Django-Crispy-Forms
When I click on any user of edit profile, its URL will be something like this http://myapp.com/administrator/edit_user/11
where 11 is the user id
Thanks in advance, let me know if you need any further information.
EDIT:Here's my final proposed solution (charlesliam also made a reference to this in his comment)
We will subclass AbstractUser to add extra fields to the user. Obviously, there's other ways of doing this, but using AbstractUser should suffice your requirements. You'd have to syncdb for model changes to propagate.
SETTINGS.PY
AUTH_USER_MODEL = 'app.UserInformation' # Points to our custom User model which we will define in models.py
MODELS.PY
from django.contrib.auth.models import AbstractUser
class UserInformation(AbstractUser):
# user = models.ForeignKey(User, unique=True) <---- Remove this field
degree = models.ForeignKey(Degree, null=True, blank=True)
stakeholder = models.ForeignKey(Stakeholder)
cell_number = models.CharField(max_length=32, null=True, blank=True)
FORMS.PY
class EditUserForm(forms.ModelForm): #fixed typo. It's forms.ModelForm, not models.ModelForm
class Meta:
model = UserInformation
VIEWS.PY
from forms.py import EditUserForm
def edit_user (request, id):
user = User.objects.get(id=11)
if request.method == 'POST': #If form has been submitted
form = EditUserForm(request.POST, instance=user)
if form.is_valid(): #All good. Validation passed
form.save()
return HttpResponseRedirect('/your-view/') # Redirect after POST
else:
form = EditUserForm(instance=user) # Unbound form
return render(request, 'MobiApp/edit_user.html', {'form': form})
edit_user.html
{% load crispy_forms_tags %}
{% crispy form %}
will give you a pre-populated form with the user instance, which you can edit and POST back.
Now with regards to user authentication, you can check if the currently logged in user is superuser (administrator), and proceed with the form editing logic.
So in your VIEWS.PY:
def edit_user (request, id):
current_user = request.user
if current_user.is_superuser:
...
Alternatively, you can assign the currently logged-in user to any group and then check if the user is member of that group, then proceed with form editing.
I hope that helps.
REFERENCES:
https://docs.djangoproject.com/en/1.6/topics/forms/modelforms/
https://github.com/django/django/blob/master/django/contrib/auth/models.py#L353
https://docs.djangoproject.com/en/dev/topics/auth/customizing/
When to use the Custom User Model in Django 1.5

Resources