I've created models for the logic of friend list and friend request. In the FriendRequest I've defined a method which adds User relation to FriendList if accept method is called. However I'm unable to do so because of the error shown below.
I don't understand the error as I'm adding the User in the model.
views.py
friend_request = FriendRequest.objects.get(id=request_id)
if request_option == 'accept':
friend_request.accept()
if request_option == 'decline':
friend_request.decline()
models.py
class FriendList(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name="user")
friends = models.ManyToManyField(User, blank=True, related_name="friends")
def add_friend(self, account):
if not account in self.friends.all():
self.friends.add(account)
self.save()
class FriendRequest(models.Model):
sender = models.ForeignKey(User, on_delete=models.CASCADE, related_name="sender")
receiver = models.ForeignKey(User, on_delete=models.CASCADE, related_name="receiver")
is_active = models.BooleanField(blank=False, null=False, default=True)
timestamp = models.DateTimeField(auto_now_add=True)
def accept(self):
receiver_friend_list = FriendList.objects.get(user=self.receiver)
if receiver_friend_list:
receiver_friend_list.add_friend(self.sender)
sender_friend_list = FriendList.objects.get(user=self.sender)
if sender_friend_list:
sender_friend_list.add_friend(self.receiver)
self.is_active = False
self.save()
def decline(self):
self.is_active = False
self.save()
File "C:\Users\models.py", line 77, in accept
receiver_friend_list = FriendList.objects.get(user=self.receiver)
File "C:\Python310\lib\site-packages\django\db\models\manager.py", line 85, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "C:\Python310\lib\site-packages\django\db\models\query.py", line 496, in get
raise self.model.DoesNotExist(
friends.models.FriendList.DoesNotExist: FriendList matching query does not exist.
You are querying for a non-existing object. To avoid that error use get_or_create:
def accept(self):
receiver_friend_list, created = FriendList.objects.get_or_create(user=self.receiver)
if receiver_friend_list:
receiver_friend_list.add_friend(self.sender)
sender_friend_list = FriendList.objects.get(user=self.sender)
if sender_friend_list:
sender_friend_list.add_friend(self.receiver)
self.is_active = False
self.save()
This is what Django Docs shows and there is a pythonic way also taken from Django Docs.
try:
receiver_friend_list= FriendList.objects.get(user=self.receiver)
except FriendList.DoesNotExist:
receiver_friend_list = FriendList(user=self.receiver)
receiver_friend_list.save()
Related
I am creating a quiz application using a guide. My application works perfectly fine in development with both sqlite3 and postgresql databases. But when pushed to production, I am faced with errors using a postgresql database. So I tried using my development sqlite3 database in production to test things out. My sqlite3 database works fine in production, but postgresql does not work in production. Initially, I thought the error is on the views level, but now I am seeing the error coming from the postgresql. Could be errors in my views or models schema. I really can't tell. The corresponding error I get when using a postgresql database in production using a linux server with gunicorn and nginx is here below, and the whole models design and views are here below too. Thanks, I appreciate your time in giving me a suitable answer to my question.
models.py
from django.db import models
import random
from account.models import Profile
from django.urls import reverse
import datetime
from django.utils import timezone
from ckeditor_uploader.fields import RichTextUploadingField
class PublishedBookManager(models.Manager):
def get_queryset(self):
return super(PublishedBookManager, self).get_queryset().filter(publish_book=True)
class Book(models.Model):
name = models.CharField(max_length=120)
description = models.TextField()
created_by = models.ForeignKey(Profile, default=1, null=True, on_delete=models.SET_NULL)
number_of_questions = models.IntegerField()
number_of_sections = models.IntegerField()
time = models.IntegerField(help_text="duration of the quiz in minutes")
required_score_to_pass = models.IntegerField(help_text="required score in %")
start_date = models.DateTimeField(default=timezone.now)
publish_book = models.BooleanField(default=False)
date_created = models.DateTimeField(auto_now_add=True)
last_updated = models.DateTimeField(auto_now=True)
objects = models.Manager()
published = PublishedBookManager()
def __str__(self):
return f"{self.name}"
def get_absolute_url(self):
return reverse('quiz:book-detail-view', args=[self.pk])
class PublishedQuizManager(models.Manager):
def get_queryset(self):
return super(PublishedQuizManager, self).get_queryset().filter(publish_quiz=True)
class Quiz(models.Model):
book = models.ForeignKey(Book, on_delete=models.CASCADE, blank=True, null=True)
name = models.CharField(max_length=120)
description = models.TextField()
created_by = models.ForeignKey(Profile, default=1, null=True, on_delete=models.SET_NULL)
number_of_questions = models.IntegerField()
time = models.IntegerField(help_text="duration of the quiz in minutes")
required_score_to_pass = models.IntegerField(help_text="required score in %")
completed_users = models.ManyToManyField(Profile, blank=True, related_name='completed_users_quiz')
publish_quiz = models.BooleanField(default=False)
start_date = models.DateTimeField(default=timezone.now)
deadline_date = models.DateTimeField(default=timezone.now)
date_created = models.DateTimeField(auto_now_add=True)
last_updated = models.DateTimeField(auto_now=True)
objects = models.Manager()
published = PublishedQuizManager()
def __str__(self):
return f"{self.book.name} = {self.name}"
def get_questions(self):
questions = list(self.question_set.all())
random.shuffle(questions)
return questions[:self.number_of_questions]
class Meta:
verbose_name_plural = 'Quizes'
def get_absolute_url(self):
return reverse('quiz:quiz-view', kwargs={'book_pk': self.book.pk, "pk": self.pk})
class Question(models.Model):
# text = models.TextField()
text = RichTextUploadingField(unique=True)
second_text = models.TextField()
quiz = models.ForeignKey(Quiz, on_delete=models.CASCADE)
date_created = models.DateTimeField(auto_now_add=True)
def __str__(self):
return str(self.text)
def get_answers(self):
return self.answer_set.all()
# def get_absolute_url(self):
# return reverse('quiz:quiz-view', kwargs={'question_pk': self.pk,})
class Answer(models.Model):
text = models.CharField(max_length=255)
correct = models.BooleanField(default=False)
question = models.ForeignKey(Question, on_delete=models.CASCADE)
date_created = models.DateTimeField(auto_now_add=True)
def __str__(self):
return f"question: {self.question.text}, answer: {self.text}, correct: {self.correct}"
class Result(models.Model):
quiz = models.ForeignKey(Quiz, on_delete=models.CASCADE)
user = models.ForeignKey(Profile, on_delete=models.CASCADE)
score = models.FloatField()
date_created = models.DateTimeField(auto_now_add=True)
def __str__(self):
return str(self.pk)
views.py
def save_quiz_view(request, pk, book_pk):
# if request.user in
quiz = Quiz.objects.get(pk=pk)
# Submition of result only occurs if a user is not in the completed users field. If they are already
# in the completed users ManyToMany field, then it won't save. But if not, it will save.
if request.is_ajax() and not request.user.profile in quiz.completed_users.all():
questions = []
data = request.POST
data_ = dict(data.lists())
data_.pop('csrfmiddlewaretoken')
for _k in data_.keys():
if Question.objects.all():
# print('key: ', k)
k = _k
question = Question.objects.get(text=k)
questions.append(question)
user = request.user.profile
quiz = Quiz.objects.get(pk=pk)
if request.user.is_authenticated:
if not user in quiz.completed_users.all():
quiz.completed_users.add(user)
score = 0
multiplier = 100 / quiz.number_of_questions
results = []
correct_answer = None
for q in questions:
a_selected = request.POST.get(q.text)
if a_selected != "":
question_answers = Answer.objects.filter(question=q)
for a in question_answers:
if a_selected == a.text:
if a.correct:
score += 1
correct_answer = a.text
else:
if a.correct:
correct_answer = a.text
results.append({str(q): {'correct_answer': correct_answer, 'answered': a_selected}})
else:
results.append({str(q): 'not answered'})
score_ = score #* multiplier
Result.objects.create(quiz=quiz, user=user, score=score_)
if score_:#>= quiz.required_score_to_pass:
return JsonResponse({'passed': True, 'score': score_, 'results': results})
else:
return JsonResponse({'passed': False, 'score': score_, 'results': results})
Error
django#UniqueAsf2:~/src$ python3 manage.py runserver 0.0.0.0:8000
Watching for file changes with StatReloader
Performing system checks...
System check identified no issues (0 silenced).
October 26, 2021 - 03:57:12
Django version 3.2.8, using settings 'asf.settings'
Starting development server at http://0.0.0.0:8000/
Quit the server with CONTROL-C.
[26/Oct/2021 03:57:18] "GET /quiz/1/1/ HTTP/1.1" 200 8065
Not Found: /quiz/1/1/assets/vendors/boxicons/css/boxicons.min.css
[26/Oct/2021 03:57:18] "GET /quiz/1/1/assets/vendors/boxicons/css/boxicons.min.css HTTP/1.1" 404 5612
[26/Oct/2021 03:57:18] "GET /quiz/1/1/data/ HTTP/1.1" 200 101
Internal Server Error: /quiz/1/1/save/
Traceback (most recent call last):
File "/home/django/.local/lib/python3.9/site-packages/django/core/handlers/exception.py", line 47, in inner
response = get_response(request)
File "/home/django/.local/lib/python3.9/site-packages/django/core/handlers/base.py", line 181, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/django/src/quiz/views.py", line 108, in save_quiz_view
question = Question.objects.get(text=_k)
File "/home/django/.local/lib/python3.9/site-packages/django/db/models/manager.py", line 85, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/home/django/.local/lib/python3.9/site-packages/django/db/models/query.py", line 435, in get
raise self.model.DoesNotExist(
quiz.models.Question.DoesNotExist: Question matching query does not exist.
Your data in Question is not stored in simple text because you are using RichTextUploadingField which converts text into HTML format for handling text fomatting. Because of this you can't directly compare two strings or run search over it.
Try using icontains for checking string in your field. This might not work in all cases so you'll have to handle that accordingly.
questions = Question.objects.filter(text__icontains=k)
for question in questions:
# Handle questions here
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)
I have a model named Post, and want to save the full name of the admin automatically who created(or edited) that post.
I read about get_full_name() in django documentation, but I cannot understand how to call this method.
Here is my Post model
class Post(models.Model):
post_id = models.AutoField
postname = models.CharField(max_length=50)
description = models.CharField(max_length=1000)
location = models.CharField(max_length=30)
user = // I want to store the logged in admin full name here
Try the steps below.
Create a middleware that will store the context of the current user to a local thread. Add this middleware to the bottom of middlewares list in settings.
import threading
local = threading.local()
class BaseMiddleware(object):
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
local.user = request.user
response = self.get_response(request)
return response
Use local thread to get current user and store it in db white creating and updating post.
from .middleware import local
class Post(models.Model):
post_id = models.AutoField
postname = models.CharField(max_length=50)
description = models.CharField(max_length=1000)
location = models.CharField(max_length=30)
created_by = models.ForeignKey(
User,
on_delete=models.CASCADE,
related_name="%(class)s_created_by_user",
)
updated_by = models.ForeignKey(
User,
on_delete=models.CASCADE,
related_name="%(class)s_updated_by_user",
)
def save(self, *args, **kwargs):
if (
self.pk is None
and hasattr(local, "user")
and local.user.__class__ != AnonymousUser
):
self.created_by = local.user
elif (
self.pk
and hasattr(local, "user")
and local.user.__class__ != AnonymousUser
):
self.updated_by = local.user
return super().save(*args, **kwargs)
Having an issue when running makemigrations/migrate with my Django project.
Getting this error:
Traceback (most recent call last):
File "manage.py", line 10, in <module>
execute_from_command_line(sys.argv)
File "C:\Users\crstu\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\core\management\__init__.py", line 353, in execute_from_command_line
utility.execute()
File "C:\Users\crstu\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\core\management\__init__.py", line 345, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "C:\Users\crstu\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\core\management\base.py", line 348, in run_from_argv
self.execute(*args, **cmd_options)
File "C:\Users\crstu\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\core\management\base.py", line 399, in execute
output = self.handle(*args, **options)
File "C:\Users\crstu\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\core\management\commands\migrate.py", line 139, in handle
plan = executor.migration_plan(targets)
File "C:\Users\crstu\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\db\migrations\executor.py", line 60, in migration_plan
for migration in self.loader.graph.forwards_plan(target):
File "C:\Users\crstu\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\db\migrations\graph.py", line 149, in forwards_plan
self.ensure_not_cyclic(target, lambda x: (parent.key for parent in self.node_map[x].parents))
File "C:\Users\crstu\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\db\migrations\graph.py", line 241, in ensure_not_cyclic
raise CircularDependencyError(", ".join("%s.%s" % n for n in cycle))
django.db.migrations.exceptions.CircularDependencyError: accounts.0001_initial, projects.0001_initial
I have two apps---one called Accounts and another called Projects
for my Accounts app, here is the model:
from django.contrib.auth.models import (
AbstractBaseUser,
BaseUserManager,
PermissionsMixin
)
from django.db import models
from django.utils import timezone
from django.conf import settings
from django.db.models.signals import post_save
import os
from projects.models import Skill, Project
def avatar_upload_path(instance, filename):
return os.path.join('avatars', 'user_{0}', '{1}').format(
instance.user.id, filename)
class UserManager(BaseUserManager):
def create_user(self, email, username=None, password=None):
if not email:
raise ValueError("Users must have an email address")
if not username:
username = email.split('#')[0]
user = self.model(
email=self.normalize_email(email),
username=username,
)
user.set_password(password)
user.save()
return user
def create_superuser(self, email, username, password):
user = self.create_user(
email,
username,
password,
)
user.is_staff = True
user.is_superuser = True
user.save()
return user
class User(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(unique=True)
username = models.CharField(max_length=40, unique=True, default='')
date_joined = models.DateTimeField(default=timezone.now)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
objects = UserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['username']
def __str__(self):
return "#{}".format(self.username)
def get_short_name(self):
return self.username
def get_long_name(self):
return "#{} ({})".format(self.username, self.email)
class UserProfile(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL)
first_name = models.CharField(max_length=40, default='', blank=True)
last_name = models.CharField(max_length=40, default='', blank=True)
bio = models.TextField(blank=True, default='')
avatar = models.ImageField('Avatar picture',
upload_to=avatar_upload_path,
null=True,
blank=True)
skills = models.ManyToManyField(Skill)
def __str__(self):
return self.user.username
#property
def get_avatar_url(self):
if self.avatar:
return '/media/{}'.format(self.avatar)
return 'http://www.gravatar.com/avatar/{}?s=128&d=identicon'.format(
'94d093eda664addd6e450d7e9881bcad'
)
def create_profile(sender, **kwargs):
if kwargs['created']:
user_profile = UserProfile.objects.create(user=kwargs['instance'])
post_save.connect(create_profile, sender=User)
and for my Projects app here is the model. I thought that maybe since I was using a many to many field from the UserProfile to the Skill class in another app that maybe that was the issue...so i tried to run makemigrations separately on the two apps---while commenting out 'skill' from UserProfile. Didn't work. So not sure what to do now.
from django.conf import settings
from django.db import models
from django.core.urlresolvers import reverse
class Skill(models.Model):
"""User skills class."""
ANDROID = 1
DESIGNER = 2
JAVA = 3
PHP = 4
PYTHON = 5
RAILS = 6
WORDPRESS = 7
IOS = 8
SKILL_CHOICES = (
(str(ANDROID), 'Android Developer'),
(str(DESIGNER), 'Designer'),
(str(JAVA), 'Java Developer'),
(str(PHP), 'PHP Developer'),
(str(PYTHON), 'Python Developer'),
(str(RAILS), 'Rails Developer'),
(str(WORDPRESS), 'Wordpress Developer'),
(str(IOS), 'iOS Developer')
)
name = models.CharField(max_length=140, choices=SKILL_CHOICES, default='unknown')
def __str__(self):
return self.get_name_display()
class Project(models.Model):
owner = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='project', null=True)
created_at = models.DateTimeField(auto_now_add=True)
title = models.CharField(max_length=255)
description = models.TextField()
requirements = models.TextField(default='')
timeline = models.CharField(max_length=255, blank=True)
complete = models.BooleanField(default=False)
#property
def open_positions(self):
return self.positions.exclude(filled=True)
def __str__(self):
return self.title.title()
def get_absolute_url(self):
return reverse("projects:project_detail", kwargs={"pk": self.pk})
class Position(models.Model):
project = models.ForeignKey(Project, default='',related_name='positions')
name = models.CharField(max_length=140)
description = models.TextField()
skill = models.ForeignKey(Skill, default='', null=True)
filled = models.BooleanField(default=False)
def __str__(self):
return '{} - {}'.format(self.project.title.title(), self.name.title())
Your 2 migrations have a dependency on each other. Look at the generated migration for your account app and you will probably see something like this
class Migration(migrations.Migration):
dependencies = [
('projects', '0001_initial'),
]
There is probably something similar in your projects migration
You need to delete these two migration files and run makemigrations again without specifying an app name
When you have this type of problem that means you are importing classes from each other. You are using each other app model classes in Foreignkey and ManytoMany fields.
So use below way to define fields in your models.py of both app.
field = models.ForeignKey('app_name.ModelClassName',)
field = models.ManyToManyField('app_name.ModelClassName',)
So i have this two models in django:
class Course(models.Model):
def get_image_path(self, filename):
return os.path.join('courses', str(self.slug), filename)
def __str__(self):
return self.name
def save(self, *args, **kwargs):
self.slug = slugify(self.name)
super(Course, self).save(*args, **kwargs)
name = models.CharField(max_length=255, verbose_name="Nombre")
description = models.CharField(max_length=255, verbose_name="DescripciĆ³n")
price = models.DecimalField(max_digits=12,decimal_places=2, verbose_name="Precio")
slug = models.SlugField(blank=True, max_length=255)
icon_img = models.ImageField(upload_to=get_image_path, blank=True, null=True, verbose_name="Imagen")
background_color = ColorField(default="#026085")
class Meta:
verbose_name = "curso"
verbose_name_plural = "cursos"
class UserCourse(models.Model):
user = models.ForeignKey(User)
course = models.ForeignKey(Course)
So whenever a user "buys" a course, it is stored in UserCourse. I have a view where the system shows a list of all the courses the user has bought. This is the view code:
def user_course_list_view(request, username):
context_dict = {}
try:
user_courses = UserCourse.objects.filter(user=request.user).course_set
context_dict['courses'] = user_courses
context_dict['heading'] = "Mis cursos"
except:
context_dict['courses'] = None
context_dict['heading'] = "Mis cursos wey"
return render(request, 'courses/course_list.html', context=context_dict)
I dont know where is the error and I cant seem to catch the exception (im using django with docker)
tl;dr
Something like this should work.
usercourse_objects = UserCourse.objects.filter(user=request.user).select_related('course')
user_courses = [x.course for x in usercourse_objects]
Explanation
There are multiple ways to do this, but one way would be to first get all the UserCourse objects for the current user:
usercourse_objects = UserCourse.objects.filter(user=request.user)
Then, for each UserCourse object, get the related Course:
user_courses = [x.course for x in usercourse_objects]
Now, the second line causes N database queries (one for each time we follow the course foreign key relation. To prevent this, the first line can be changed to:
usercourse_objects = UserCourse.objects.filter(user=request.user).select_related('course')
This pre-populates the course attribute of the UserCourse objects. More info about select_related() can be found here.