Double linked list in Django models - django

I am trying to create a music player using Django. on the site I should have playlists with music tracks. I need to create two models: composition and playlist. I have already created the Composition class:
class Composition(models.Model):
title = models.CharField(max_length=500)
artist = models.CharField(max_length=500)
playlist = models.ForeignKey('PlayList', on_delete=models.SET_NULL, null=True, blank=False)
time_length = models.DecimalField(blank=True, max_digits=20, decimal_places=2)
audio_file = models.FileField(validators=[validate_is_audio])
cover_image = models.ImageField()
Now I need to create a playlist model class PlayList(models.Model, LinkedList):, which should, by assignment, be inherited from my base class linked_list, realizing a doubly linked list. This class has methods like init(self, first_item=None), append_left(self, item), append_right(self, item), remove(self, item), insert(self, previous, item), etc. On the site, I will have to have several playlists with a choice. This is my first time using django, so I don't know how to implement it.
I haven't tried creating this model yet because I don't know where to start.

Related

which is the better design of database for article Like function?

I'm using Django to develop a news website.Now I'm developing the like function in news detail page, this function is like that at the bottom of the news, there is a like button, once you click it the amount of like will add 1.
Now I have 2 choices to design the table of the database in django we call it model.I'm not sure which design is better.
First:just use one News model
class News(models.Model):
...code..
is_up = models.BooleanField(default=True)
up_count = models.IntegerField(default=0)
Once is_up ,up_count will add 1.
Sceond:use 2 models,News model and a separate Like model
class News(models.Model):
...code..
up_count = models.IntegerField(default=0)
class Like(models.Model):
"""
点赞表
"""
nid = models.AutoField(primary_key=True)
user = models.ForeignKey('UserInfo', null=True, on_delete=models.CASCADE)
news = models.ForeignKey("News", null=True, on_delete=models.CASCADE)
is_up = models.BooleanField(default=True)
class Meta:
unique_together = [
('news', 'user'),
]
Any friend can tell which design is better ?
If you use the second one, you can know more information, depending on whether you need the data, or you can use ManyToManyField like this:
class News(models.Model):
...code..
likes = models.ManyToManyField('UserInfo')
This will record who liked this news.

How can I display different results onto separate templates from one model in Django, using class based views?

I have one model:
class Product(models.Model):
slug = models.SlugField(unique=True)
image = models.ImageField(upload_to='media')
title = models.CharField(max_length=150)
description = models.TextField()
short_description = models.CharField(max_length=300)
price = models.DecimalField(max_digits=5, decimal_places=2)
discount_price = models.DecimalField(max_digits=5, decimal_places=2, blank=True, null=True)
stock_quantity = models.PositiveIntegerField(default=10)
in_stock = models.BooleanField(default=True)
on_sale = models.BooleanField(default=False)
date_added = models.DateTimeField(auto_now_add=True, blank=True)
main_category = models.CharField(default='FW', choices=CATEGORY_CHOICES, max_length=2)
additional_category = models.CharField(choices=CATEGORY_CHOICES, max_length=2, blank=True, null=True)
brand = models.CharField(choices=CATEGORY_CHOICES, max_length=2, blank=True, null=True)
size = models.CharField(max_length=2, choices=CATEGORY_CHOICES, default='M', blank=True, null=True)
def __str__(self):
return self.title
Within this model will be various types of products for example, clothes and books.
These will be defined by the main_category and additional_category fields within the model.
If the product being entered into the database is a piece of clothing I will enter values for size and brand. For books, these will obviously be blank.
However, if the product is a piece of clothing, I have clothing for women, clothing for men and clothing for children. I will be able to define these by selecting 'for women' in the main_category field.
In my templates, I would like to dynamically display a page that shows all clothes, one that displays 'clothes for women', another page that shows 'clothes for men' etc etc. And then a page that displays all books, books for teens, books for adults etc, based on the main_category and additional_category.
If i enter a product, and the main category is 'for women' and the additional category is 'plus size', I would like a template to dynamically display all products that have either 'for women' selected in main_category OR additional_category. And a template that displays all plus size clothing, where main_category OR additional_category is 'plus size'.
My trouble comes when I am writing the views. Do I need to provide a view for women only clothes, plus size only clothes, children's clothes, books, books for adults, books for teens etc. Or can I write just ONE view, that outputs the correct data to multiple templates. Basically, do I need one view per template?
I have read this:
https://docs.djangoproject.com/en/3.0/topics/class-based-views/generic-display/
and have taken a look at get_context_data. Can I define multiple get_context_data functions to return different filtered information for different templates, and if so how do I differentiate between them?
I am current learning, and building a dummy online store with Django in order to learn as much as possible, but finding this particularly complex?
Thanks
A cleaner way to do that is to create an abstract model called Product and use it as a base class for different product types, like clothes and books.
Being Product an abstract class means that Django's ORM won't create a Product table on database. Instead, it will create tables for each subclass including the common fields you define on Product class. Check the code below for better understanding:
# models.py
from django.db import models
class Product(models.Model):
image = models.ImageField(upload_to='media')
title = models.CharField(max_length=150)
# ... (other common fields)
class Meta:
abstract = True
class Clothes(Product):
size = models.CharField(max_length=2, choices=CATEGORY_CHOICES, default='M', blank=True, null=True)
# ... (other specific fields)
From django docs.

Django MPTT filter on related model

Let's say I have a model Album:
class Genre(MPTTModel):
name = models.CharField(max_length=50, unique=True)
parent = TreeForeignKey('self', null=True, blank=True, related_name='children', db_index=True)
And a model called Album like this
class Album(models.Model):
name = models.CharField(..)
...
genre = models.ForeignKey(Genre)
Let's also assume I have the following Genres:
Rock
- Hard Rock
- Classic Rock
Pop
....
Is it possible to filter all albums that have genres (or ancestor genres) ids in a list?
Basically, what I want to do:
Album.objects.filter(genre__ancestors__in=[id_of_rock, id_of_classical])
The closest thing I found is this:
genre_list = []
for id in genres:
genre_list.append(Genre.objects.get(pk=id).get_ancestors(include_self=True)
Album.objects.filter(genre__in=genre_list)
But that's pretty expensive. I'm sure it can be done in a single query using some MPTT strategy, but I couldn't find a thing online. Any help?

order_with_respect_to for reverse relationship

Suppose I have the following models:
class Playlist(models.Model):
name = models.TextField()
songs = models.ManyToManyField(Song)
class Song(models.Model):
title = models.TextField()
So a Playlist can have multiple songs and a song can be in multiple playlists.
I want to add an "order" field so that a user can reorder songs in a playlist. I found order_with_respect_to, which appears to be a perfect solution. However, I would need to add that meta option to the Song model, e.g.:
class Song(models.Model):
title = models.TextField()
class Meta:
order_with_respect_to = 'playlists'
Obviously, there is no playlist field specified on Song since I've got the relationship specified in the Playlist model. Is there a way to specify the reverse relationship for order_with_respect_to using related_name? Or could I slap a ForeignKey reference to playlists in the Song model?
order_with_respect_to is (arguably) useful when you have a ForeignKey, but not a ManyToManyField. It works by adding an extra field to the model, but in your case the order varies depending on the Playlist.
The straightforward way to do this in Django is to put the order on an explicitly created through table.
class Playlist(models.Model):
name = models.TextField()
songs = models.ManyToManyField(Song, through='PlaylistSong')
class Song(models.Model):
title = models.TextField()
class PlaylistSong(models.Model):
playlist = models.ForeignKey(Playlist)
song = models.ForeignKey(Song)
order = models.PositiveSmallIntegerField()
So to get the Songs in a Playlist in the right order, you would do something like:
Song.objects.filter(playlistsong__playlist_id=1)
.order_by('playlistsong__order')

Is it a good practice to do reverse navigation for model objects in a django template?

I am building a small learning management system. It has courses, activities for courses and activity responses for activities. The relationships between these objects is as shown below.
In a view I want to list in tabular form all activities for a course and all responses received for that activity. If I gave only the course object to my template then it would have to do reverse navigation from course to activities and subsequently from each activity to the ActivityResponse.
My question is what is the right way to navigate such a relationship? Is reverse navigation possible / advisable from templates, or should I pass appropriate dicts from the view to the template, so it can simply iterate over all the objects and display data.
class Course(models.Model):
users = models.ManyToManyField(User, null=True, blank=True)
title = models.CharField(max_length=128)
contents = models.TextField()
start_date = models.DateField()
end_date = models.DateField()
class Activity(models.Model):
course = models.ForeignKey(Course)
placement = models.IntegerField()
title = models.CharField(max_length=128)
contents = models.TextField()
class ActivityResponse(models.Model):
user = models.ForeignKey(User)
activity = models.ForeignKey(Activity)
when = models.DateTimeField(default=datetime.datetime.now)
contents = models.TextField()
Keep all knowledge about the structure of your model graph in your views. Templates should only be for formatting. The reason is that templates are fiddly to adapt to change - you will hate yourself if you tweak your models, then have to change all of your templates.