-
Notifications
You must be signed in to change notification settings - Fork 899
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Solution #950
base: master
Are you sure you want to change the base?
Solution #950
Conversation
user = models.ForeignKey(to="User", | ||
on_delete=models.CASCADE, | ||
null=True, | ||
blank=True, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i think null and blank dont need here
db/models.py
Outdated
|
||
class Order(models.Model): | ||
created_at = models.DateTimeField(auto_now_add=True) | ||
user = models.ForeignKey(to="User", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the lecture says it's better to access the settings here. (settings.AUTH_USER_MODEL) not to="User"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for your hard work on this project! 😊 While your implementation is mostly correct, there are a few critical issues that need to be addressed before we can proceed:
-
Exception Handling: There are multiple instances where exceptions like
DoesNotExist
are not handled. It's important to handle these exceptions to ensure smooth operation and provide user-friendly error messages. This applies to functions likeget_user
,create_order
, anddelete_movie_session_by_id
. -
Use of
User
instead ofget_user_model()
: Inservices/order.py
, it's best practice to useget_user_model()
instead of directly referencingUser
. This ensures compatibility with custom user models. -
Transaction Decorator: Consider using the
@transaction.atomic
decorator for better readability and to ensure that the entire function executes within a single transaction context. -
Type Annotations: Improve code clarity by specifying the type of
QuerySet
returned in functions likeget_orders
. -
Typo: There's a typo in the
get_taken_seats
function (tiket
should beticket
). Correcting this will prevent potential errors. -
Nullable
user
Field inOrder
Model: The change to allownull
andblank
values for theuser
field in theOrder
model is significant. Ensure this aligns with your application's logic and requirements.
Please address these issues to ensure the code fully meets the task requirements and constraints. Once these are resolved, your code will be in great shape! Keep up the great work! 🚀
✨ Please rate this review in the Platform's notification center. I will be grateful for your feedback! ✨
🔄 Fix the issues, commit the changes, and then re-request my review using the Re-request review
button in the Reviewers tab.
migrations.CreateModel( | ||
name='User', | ||
fields=[ | ||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), | ||
('password', models.CharField(max_length=128, verbose_name='password')), | ||
('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')), | ||
('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')), | ||
('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=150, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='username')), | ||
('first_name', models.CharField(blank=True, max_length=150, verbose_name='first name')), | ||
('last_name', models.CharField(blank=True, max_length=150, verbose_name='last name')), | ||
('email', models.EmailField(blank=True, max_length=254, verbose_name='email address')), | ||
('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')), | ||
('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')), | ||
('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')), | ||
('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.Group', verbose_name='groups')), | ||
('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.Permission', verbose_name='user permissions')), | ||
], | ||
options={ | ||
'verbose_name': 'user', | ||
'verbose_name_plural': 'users', | ||
'abstract': False, | ||
}, | ||
managers=[ | ||
('objects', django.contrib.auth.models.UserManager()), | ||
], | ||
), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The User
model is being created here, but it seems to duplicate the default Django User
model. If you intend to extend the default User
model, consider using a custom user model by extending AbstractUser
or AbstractBaseUser
instead of creating a new model from scratch.
('created_at', models.DateTimeField(auto_now_add=True)), | ||
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='orders', to=settings.AUTH_USER_MODEL)), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Order
model references settings.AUTH_USER_MODEL
for the user
field, which is correct. Ensure that AUTH_USER_MODEL
is set to the correct user model in your settings if you are using a custom user model.
('movie_session', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='db.moviesession')), | ||
('order', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='db.order')), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Ticket
model has a foreign key to Order
. Ensure that the Order
model is correctly defined and migrated before this migration is applied to avoid any dependency issues.
migrations.AddConstraint( | ||
model_name='ticket', | ||
constraint=models.UniqueConstraint(fields=('row', 'seat', 'movie_session'), name='unique_ticket'), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The unique constraint on the Ticket
model ensures that each combination of row
, seat
, and movie_session
is unique. This is a good practice to prevent duplicate tickets for the same seat in a session.
name='user', | ||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='orders', to=settings.AUTH_USER_MODEL), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The user
field in the Order
model is now nullable and can be left blank. This means an Order
can exist without being associated with a User
. Ensure this change is intentional and that your application logic can handle orders without users.
services/order.py
Outdated
raise Exception("No tickets to create") | ||
|
||
with transaction.atomic(): | ||
user = User.objects.get(username=username) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The User.objects.get(username=username)
call can raise a DoesNotExist
exception if the user is not found. Consider handling this exception to provide a more user-friendly error message.
services/order.py
Outdated
except ValidationError as e: | ||
raise ValueError(f"Invalid ticket data: {e}") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Raising a ValueError
with a custom message is a good practice here, as it provides clear feedback about the validation error. Ensure that this exception is handled appropriately where the create_order
function is called.
services/order.py
Outdated
|
||
def get_orders(username: str = None) -> list: | ||
if username: | ||
user = User.objects.get(username=username) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similar to the create_order
function, User.objects.get(username=username)
can raise a DoesNotExist
exception. Consider handling this exception to ensure smooth operation when the user is not found.
services/user.py
Outdated
|
||
|
||
def get_user(user_id: int) -> User: | ||
return User.objects.get(pk=user_id) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The get_user
function uses User.objects.get()
, which will raise a DoesNotExist
exception if no user is found with the given ID. Consider handling this exception or documenting that this function may raise an exception if the user is not found.
services/user.py
Outdated
except ObjectDoesNotExist: | ||
raise ObjectDoesNotExist(f"User with id {user_id} does not exist.") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Raising ObjectDoesNotExist
in the update_user
function is redundant since this exception is already raised by User.objects.get()
. Consider raising a more specific exception or handling it differently to provide clearer feedback.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for your hard work on this Pull Request! 🎉 While the decision is to APPROVE to help you move forward with your learning journey, there are several critical issues that need to be addressed to ensure your code aligns with best practices and application requirements:
-
User Model Creation: Avoid creating a custom
User
model directly in the migration file. Instead, define it inmodels.py
and create migrations to ensure better maintainability and integration with Django's authentication system. -
Order Model's User Field: The
user
field in theOrder
model allowsnull
andblank
values and useson_delete=CASCADE
. Ensure these behaviors align with your application's logic, as they allow orders to exist without an associated user and delete all related orders if a user is deleted. -
Exception Handling: Use
User.DoesNotExist
instead ofObjectDoesNotExist
for clarity and specificity in exception handling. Also, ensure that exceptions are handled in a way that aligns with your application's error handling strategy. -
Type Annotations: Update the type annotations for
genres_ids
andactors_ids
tolist[int]
for consistency and clarity. Also, ensure the return type ofget_orders
is annotated asQuerySet
instead oflist
. -
Use of
get_user_model()
: It's best practice to useget_user_model()
instead of directly referencingUser
to ensure compatibility with custom user models. -
Import Statement: Ensure the import statement for
AUTH_USER_MODEL
isfrom django.conf import settings
for compatibility with Django's settings.
Please review these comments and make the necessary improvements to enhance your code. Keep up the great work, and continue learning from these experiences! 🚀
✨ Please rate this review in the Platform's notification center. I will be grateful for your feedback! ✨
migrations.CreateModel( | ||
name='User', | ||
fields=[ | ||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), | ||
('password', models.CharField(max_length=128, verbose_name='password')), | ||
('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')), | ||
('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')), | ||
('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=150, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='username')), | ||
('first_name', models.CharField(blank=True, max_length=150, verbose_name='first name')), | ||
('last_name', models.CharField(blank=True, max_length=150, verbose_name='last name')), | ||
('email', models.EmailField(blank=True, max_length=254, verbose_name='email address')), | ||
('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')), | ||
('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')), | ||
('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')), | ||
('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.Group', verbose_name='groups')), | ||
('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.Permission', verbose_name='user permissions')), | ||
], | ||
options={ | ||
'verbose_name': 'user', | ||
'verbose_name_plural': 'users', | ||
'abstract': False, | ||
}, | ||
managers=[ | ||
('objects', django.contrib.auth.models.UserManager()), | ||
], | ||
), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Creating a custom User
model directly in the migration file is not recommended. Define the model in models.py
and then create migrations. This ensures better maintainability and integration with Django's authentication system.
('created_at', models.DateTimeField(auto_now_add=True)), | ||
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='orders', to=settings.AUTH_USER_MODEL)), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The user
field in the Order
model uses on_delete=CASCADE
. Ensure this behavior aligns with your application's logic, as deleting a user will also delete all related orders.
name='user', | ||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='orders', to=settings.AUTH_USER_MODEL), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The user
field in the Order
model is now set to allow null
and blank
values. Ensure this change aligns with your application's logic, as it allows orders to exist without an associated user.
db/models.py
Outdated
from django.core.exceptions import ValidationError | ||
from django.db.models import UniqueConstraint | ||
|
||
from settings import AUTH_USER_MODEL |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The import statement for AUTH_USER_MODEL
should be from django.conf import settings
instead of from settings import AUTH_USER_MODEL
. This ensures compatibility with Django's settings.
db/models.py
Outdated
user = models.ForeignKey(AUTH_USER_MODEL, | ||
on_delete=models.CASCADE, | ||
null=True, | ||
blank=True, | ||
related_name="orders") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The user
field in the Order
model allows null
and blank
values. Ensure this behavior is intentional and aligns with your application's logic, as it allows orders to exist without an associated user.
with transaction.atomic(): | ||
try: | ||
user = User.objects.get(username=username) | ||
except ObjectDoesNotExist: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider using User.DoesNotExist
instead of ObjectDoesNotExist
for clarity and specificity in exception handling.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree
if username: | ||
try: | ||
user = User.objects.get(username=username) | ||
except ObjectDoesNotExist: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider using User.DoesNotExist
instead of ObjectDoesNotExist
for clarity and specificity in exception handling.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree
return order | ||
|
||
|
||
def get_orders(username: str = None) -> list: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The return type of get_orders
should be annotated as QuerySet
instead of list
for accuracy.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree
def get_user(user_id: int) -> User: | ||
try: | ||
return User.objects.get(pk=user_id) | ||
except ObjectDoesNotExist: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider using User.DoesNotExist
instead of ObjectDoesNotExist
for clarity and specificity in exception handling.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree
|
||
user.save() | ||
return user | ||
except ObjectDoesNotExist: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider using User.DoesNotExist
instead of ObjectDoesNotExist
for clarity and specificity in exception handling.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree
db/models.py
Outdated
from django.core.exceptions import ValidationError | ||
from django.db.models import UniqueConstraint | ||
|
||
from settings import AUTH_USER_MODEL |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Import settings
from django.conf
services/order.py
Outdated
|
||
with transaction.atomic(): | ||
try: | ||
user = User.objects.get(username=username) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use get_user_model()
, not User
services/order.py
Outdated
for ticket in create_tickets: | ||
try: | ||
ticket.full_clean() | ||
except ValidationError as e: | ||
raise ValueError(f"Invalid ticket data: {e}") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You already have validation on model level for this. Read how save
method works in models
user = User.objects.get(pk=user_id) | ||
if username: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use get_user
method here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mostly correct
with transaction.atomic(): | ||
try: | ||
user = User.objects.get(username=username) | ||
except ObjectDoesNotExist: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree
print(f"Movie session with id {session_id} does not exist.") | ||
|
||
|
||
def get_taken_seats(movie_session_id: int) -> list: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree
if username: | ||
try: | ||
user = User.objects.get(username=username) | ||
except ObjectDoesNotExist: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree
return order | ||
|
||
|
||
def get_orders(username: str = None) -> list: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree
def get_user(user_id: int) -> User: | ||
try: | ||
return User.objects.get(pk=user_id) | ||
except ObjectDoesNotExist: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree
|
||
user.save() | ||
return user | ||
except ObjectDoesNotExist: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree
"db", | ||
"django.contrib.auth", | ||
"django.contrib.contenttypes", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
db should be the last one in the list
No description provided.