I'm trying to build the right models for my Django app. I'm trying to build something that will allow a user to save a URL into one (or more) playlist(s) that is tied to that user. Before I implement this, I want to make sure that this is the best way to structure my models.py.
class UserProfile(models.Model):
user = models.ForeignKey(User, primary_key=True) #what is the difference between ForeignKey and OneToOne? Which one should I use?
Playlist = models.CharField('Playlist', max_length = 2000) #1 user should be able to have multiple playlists and the default playlist should be "Favorites"
def __unicode__(self):
return self.User
class Videos(models.Model):
Video_url = models.URLField('Link to video', max_length = 200, null=True, blank=True)
Playlist = models.ManyToManyField(Playlist) #this should connect to the playlists a user has. A user should be able to save any video to any plalist, so perhaps this should be ManyToMany?
def __unicode__(self):
return self.Video_url
Woah. Firstly the question is probably too "localised" for SO. Anyway. I'd do it like this:
class PlayList(models.Model):
playlist = models.CharField(max_length=2000)
class UserProfile(models.Model):
# do you want each `User` to only have one `UserProfile`? If so then OneToOne
# primary keys are automatically formed by django
# how django handles profiles: https://docs.djangoproject.com/en/dev/topics/auth/#storing-additional-information-about-users
user = models.ForeignKey(User)
def __unicode__(self):
return self.User
class UserPlayList(models.Model):
# don't capitalise attributes, if you haven't seen PEP8 before, do now: http://www.python.org/dev/peps/pep-0008/
profile = models.ForeignKey(User)
playlist = models.ForeignKey(PlayList)
class Video(models.Model):
video_url = models.URLField(max_length=200, null=True, blank=True, help_text="Link to video")
def __unicode__(self):
return self.video_url
class VideoPlayList(models.Model):
video = models.ForeignKey(Video)
play_list = models.ForeignKey(UserPlayList)
Related
I searched through stackoverflow about this particular scenario, but could not find a concrete answer, so i'm posting this.
So my problem is that i need to display specific records to a specific user in Django Admin. I'm aware that i can get the concrete logged in user through the get_queryset method extracting it from the request object. But the issue is i need to look through 6 tables to get to the information about the user of the recommendations so i could know which recommendation to display to him.
For example, if the records i need to display come from a Recommendation table, it has a reference to TableA, which has a reference to TableB .... which has a reference to TableF which has a reference to the User.
I'm aware i could do this by executing a plain SQL query with multiple joins, but my guess is that there must be a pythonic or Django sophisticated solution to this. But i may be wrong.
The model is unfortunately not in my control, nor i can change it, so i'm left to work with the state of the model that there is.
Thanks in advance.
EDIT: Unfortunately, i can't share details of it, but i can share the general look of it. So i think this should be enough to have a picture of my problem.
from django.db import models
from django.contrib.auth.models import User
class TableF(models.Model):
information = models.CharField(max_length=256, null=False)
user = models.ForeignKey(User, on_delete=models.CASCADE)
class TableE(models.Model):
information = models.CharField(max_length=256, null=False)
tableF = models.ForeignKey(TableF, on_delete=models.CASCADE)
class TableC(models.Model):
information = models.CharField(max_length=256, null=False)
tableEs = models.ManyToManyField(TableE, through='TableD')
class TableD(models.Model):
information = models.CharField(max_length=256, null=False)
tableC = models.ForeignKey(TableC, on_delete=models.CASCADE)
tableE = models.ForeignKey(TableE, on_delete=models.CASCADE)
class TableA(models.Model):
information = models.CharField(max_length=256, null=False)
tableCs = models.ManyToManyField(TableC, through='TableB')
class TableB(models.Model):
information = models.CharField(max_length=256, null=False)
tableA = models.ForeignKey(TableA, on_delete=models.CASCADE)
tableC = models.ForeignKey(TableC, on_delete=models.CASCADE)
class Recommendation(models.Model):
information = models.CharField(max_length=256, null=False)
tableA = models.ForeignKey(TableA, on_delete=models.CASCADE)
you can use a middleware to include de user to the thread locals and catch this user from get_queryset in the model manager.
from threading import local
_thread_locals = local()
def get_current_user():
return getattr(_thread_locals, 'user', None)
class ThreadLocals(object):
#staticmethod
def process_request(request):
_thread_locals.user = getattr(request, 'user', None)
in the settings
MIDDLEWARE = [
...
'path.to.file.ThreadLocals',
]
from your.path import get_current_user
class TableFManager(models.Manager):
def get_queryset(self):
return super().get_queryset().filter(creator=get_current_user())
class TableF(models.Model):
information = models.CharField(max_length=256, null=False)
user = models.ForeignKey(User, on_delete=models.CASCADE)
objects = TableFManager()
another less invasive option could be to rewrite the get_queryset in the admin class. there you already have the user in the request
def get_rec_user(user):
tes = TableE.objects.filter(tableF__in=TableF.objects.filter(user=user))
aes = TableB.objects.filter(tableE__in=tes).values_list('tableA_id', flat=True)
return Recommendation.objects.filter(
tableA__in=TableA.objects.filter(id__in=aes)
)
I'm currently working on a site with Django on Python 3. The site allows users to follow projects that they like, and they can follow as many as you want, as long as the thot projects exist. Here are my models of the site.
This is my Team model, which is the model for all the projects you can follow
class Team(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='team')
created_at = models.DateTimeField(auto_now_add=True)
modified_at = models.DateTimeField(auto_now=True)
title = models.CharField(max_length=255)
description = models.TextField()
image = models.ImageField(upload_to='images/team_images', blank=True)
roster = models.TextField(blank=True, default='')
current_raise = models.IntegerField(blank=True, default=0)
# current_backers = models.IntegerField(blank=True, default=0)
time_left = models.DateTimeField(blank=True, default=timezone.now)
raising_minimum = models.PositiveIntegerField(blank=False)
raising_maximum = models.PositiveIntegerField(blank=False)
duration = models.DateTimeField(blank=False)
def __str__(self):
return self.title
This is the user profile mode, I have a Many-to-Many field in this model.
class UserProfile(models.Model):
user = models.OneToOneField('accounts.User')
following = models.ManyToManyField(Team, related_name='user_following', blank=True)
def __str__(self):
return self.user.first_name
def save(self, *args, **kwargs):
if self.pk:
for team in self.following:
team.save()
super(UserProfile, self).save(*args, **kwargs)
The problem is, when I check the database, all the teams I've created for testing are in the field following even though the user hasn't requested to follow them, yet.
All the teams I have created showed up under 'following' in admin page.
enter image description here
Options displayed in the m2m multiple choice field of admin site are just options you can choose from. It is expected behavior of Django admin. To choose some options you can just click on the item or if you want to choose multiple click with CTRL pressed.
I have this model in Django, where a person has the same information from the user provided by Django plus a little bit more information. When I create a new person it requires to create a new user also, that's fine. But when I delete a person the user still remains on my database. What am I missing here ? I would like to delete the user too.
class Person(models.Model):
user = OneToOneField(User)
gender = CharField(max_length=1, choices=GenderChoices, blank=True, null=True)
birth_date = DateField(blank=True, null=True)
def __unicode__(self):
return self.user.username
Try to override the delete method on the model (code not tested):
class Person(models.Model):
user = OneToOneField(User)
gender = CharField(max_length=1, choices=GenderChoices, blank=True, null=True)
birth_date = DateField(blank=True, null=True)
def __unicode__(self):
return self.user.username
def delete():
theuser = User.objects.get(id=user)
theuser.delete()
I have found some relevant documentation about CASCADE usage in Django here.
I'm trying to create a directory of sites, I'm new in Django. What I need is: one site can have many payment processors and one payment processors (Paypal, Payza, etc) can belong to many sites. I'm trying to create a table relationship to represents this. My models are like this:
# Models.py
class Sites(models.Model):
name = models.CharField(max_length=75)
link = models.CharField(max_length=150)
description = models.TextField(blank=True, null=True)
def __str__(self):
return self.name
class PaymentProcessors(models.Model):
name = models.CharField(max_length=75)
def __str__(self):
return self.name
class Sites_PaymentProcessors(models.Model):
site = models.ManyToMany(Sites)
payment_processor = models.ManyToMany(PaymentProcessors)
First, I'd like to know if my models are right. If not, how can I fix it?
Second, I'm using Django Admin site to create the sites and payment processors, how can I populate automatically my Sites_PaymentProcessors table with the relation between Sites and Payment_Processors when I add a new Site?
I would slightly change the models to accomodate ManyToManyFields like this:
class Sites(models.Model):
name = models.CharField(max_length=75)
link = models.CharField(max_length=150)
description = models.TextField(blank=True, null=True)
def __str__(self):
return self.name
class PaymentProcessors(models.Model):
name = models.CharField(max_length=75)
sites = models.ManyToManyField('Sites', related_name='payment_processors')
def __str__(self):
return self.name
Now, if you want custom fields or store more information along with the relationship, you can make use of the through table
For example, if you want to associate the amount limit or something more custom:
class Sites(models.Model):
name = models.CharField(max_length=75)
link = models.CharField(max_length=150)
description = models.TextField(blank=True, null=True)
def __str__(self):
return self.name
class PaymentProcessors(models.Model):
name = models.CharField(max_length=75)
sites = models.ManyToManyField('Sites', related_name='payment_processors', through='SitePaymentProcessor')
def __str__(self):
return self.name
from django.core.validators import MaxValueValidator
class SitePaymentProcessor(models.Model):
site = models.ForeignKey('Site')
payment_processors = models.ForeignKey('PaymentProcessors')
amount_limit = models.IntegerField(default=1000,
validators=[
MaxValueValidator(100)
])
Now, again this is just an example.
Now, registering the admin classes would enable you to populate data into the models via the admin interface.
To auto-populate a large dataset, I would consider using fixtures rather than populating elements individually.
My Models:
class PromoNotification(models.Model):
title = models.CharField(_('Title'), max_length=200)
content = models.TextField(_('Content'))
users = models.ManyToManyField(User, blank=True, null=True)
groups = models.ManyToManyField(Group, blank=True, null=True)
I want to publish there items to templates with some permissions. The template is only show the notifications for users who are in list (users or/and group). What should I do? Thank you for any help. Please show me some codes if you can.
You might use a custom manager, which makes it easier to do this user filtering in multiple views.
class PromoNotificationManager(models.Manager):
def get_for_user(self, user)
"""Retrieve the notifications that are visible to the specified user"""
# untested, but should be close to what you need
notifications = super(PromoNotificationManager, self).get_query_set()
user_filter = Q(groups__in=user.groups.all())
group_filter = Q(users__in=user.groups.all())
return notifications.filter(user_filter | group_filter)
Hook up the manager to your PromoNotification model:
class PromoNotification(models.Model):
...
objects = PromoNotificationManager()
Then in your view:
def some_view(self):
user_notifications = PromoNotification.objects.get_for_user(request.user)
You can read more about custom managers in the docs: http://www.djangoproject.com/documentation/models/custom_managers/