These are my models and one user can upload multiple videos but one video belongs only to one user. How do I use the foreign key concept over here? When I add a user, does this automatically add a username in the Video model? If not, how do I do that? I'm very new to django over here
class User(models.Model):
first_name=models.CharField(max_length=20)
last_name=models.CharField(max_length=20)
username=models.CharField(max_length=25, primary_key=True)
password=models.CharField(max_length=15)
email_id=models.CharField(max_length=30, default='NULL')
profile_pic=models.ImageField(upload_to='profilepics/%Y/%m/%d/',default='')
def __str__(self):
return self.username
class Video(models.Model):
username=models.ForeignKey(User,on_delete=models.CASCADE,default="")
video=models.FileField(upload_to='videos/%Y/%m/%d/',default='')
videotitle=models.CharField(max_length=100)
likes=models.PositiveIntegerField(default=0)
dislikes=models.PositiveIntegerField(default=0)
def __str__(self):
return self.video
Try the following
from django.db import models
from django.conf import settings
class Video(models.Model):
...
username = models.ForeignKey(settings.AUTH_USER_MODEL)
Instead of referring to User directly, you should reference the user model using django.contrib.auth.get_user_model(). This method will return the currently active User model – the custom User model if one is specified, or User otherwise.
More info can be found here: https://docs.djangoproject.com/en/1.8/topics/auth/customizing/#referencing-the-user-model
Not, it won't do it automatically -- and how would it do that. You need to pass user. Also you definitely don't want to add a username, but a reference to a User object. This is misleading in the code as you have a "username" in the Video class, which acutally is not just a name (string), but a ForeignKey -- a reference to an object User when adding the new video. So what you need to do when adding a video is something along the lines of:
def add_new_video(username, filename, title):
owner = User.objects.get(username=username)
newvid = Video(username=owner, video=filename, videotitle=title)
newvid.save()
assuming that likes and dislikes will be added later on...
Related
Actually I'm creating an employee management system project using django rest api.
Now i have created my own custom models like shown below, i want to create the register employee with the below models. But how can i set the password field for login, since I haven't included in my fields. I've attached my models and serializer. Please do help for me. I'm beginner
Class Employee (models.Model):
name = models.CharField(max_length=50, unique=True, verbose_name='None')
email = models.EmailField(verbose_name='Email')
department = models.CharField(max_length=30, unique=False, verbose_name='Departamento')
(And many more details like personal email,contact, and many)
# Function used to display the employee's name in the admin page
def __str__(self):
return self.name
My serializer class is
class Employee DetailsSerializer(serializers.ModelSerializer):
class Meta:
model = Employee
Fields = [__all__]
My views be like, i want to create register view, since i dont have password in my model, how to create password field to my above shown register field,
Whatever maybe my register field should contain all those above details. I'm scratching my head here.please someone help
Yes, you can add a password field in your Employee model but you are requested not to do it because Django already provided this type of facility. Just you have to know How to use it. Try to extend the existing User model from django.contrib.auth.models.User.Let's organize your Employee model.
from django.contrib.auth.models import User
class Employee(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
#name = models.CharField(max_length=50, unique=True,
verbose_name='None')
#email = models.EmailField(verbose_name='Email')
department = models.CharField(max_length=30, unique=False,
verbose_name='Departamento')
#property
def name(self):
return "{0} {1}".format(self.user.first_name,
self.user.last_name)
No need to add an email field because this field already exists in the User model and the name field can be a property that retrieves data from the user model and the rest of the code will be unchanged. So you are concerned about the password field and it also exists in the User model.
Please check out this repo and it might help you.
I have a simple ForeignKey relationship between two models:
class Ticket(models.Model):
description = models.CharField(max_length=1000)
created_by = models.ForeignKey(User, related_name="created_ticket")
class User(models.Model):
username = models.CharField(max_length=64, unique=True, primary_key=True)
email = models.CharField(max_length=255)
I have a serialiser for each, with the user serialized within the ticket as a nested serialiser. What I would ideally like is
in an update view of Tickets on the Browsable API, being able to choose from a dropdown list of extant users, and
when entering a username and an e-mail, the application should check if users exist with those parameters, and if so, assign them to the ticket, and if not, raise a validation error (the validation part I got working, the rest... not so much).
So far, I've tried to follow overriding the update/create methods, but when I enter a code, the application always tries to create a new object, then complains that an object with the same username (the pkey) already exists. I have tried getting some sense out of the documentation on the subject, but with not much luck.
EDIT: My update method is
def update(self, instance, validated_data):
usr_data = validated_data.pop('created_by')
instance.created_by_id = usr_data.id
return instance
I know that superusers and regular users are both just django's User objects, but how can I write a custom user class that requires some fields for plain users and doesn't require those fields for superusers?
No structure in the database is tricky. JSONFields for example may prove to be extremely hard to tame when the app grows.
I would go and try to make it "simple" - more maintainable (I imagine if you need to do stuff like that you may want to extend the model in the future). If this is a new project you can easily change the default user model. But that may or may not help you with your case.
You can always make two models:
from django.db import models
from django.contrib.auth.models import AbstractBaseUser
class Mortal(AbstractBaseUser):
is_superuser = False
username = models.CharField(max_length=256)
first_name = models.CharField(max_length=256)
last_name = models.CharField(max_length=256)
class Admin(AbstractBaseUser):
is_superuser = True
username = models.CharField(max_length=256)
and then make your own authentication backend:
class MyBackend(object):
"""
Danger! A backend to authenticate only via username
"""
def authenticate(self, username=None):
try:
return Mortal.objects.get(username=username)
except Mortal.DoesNotExist:
try:
return Admin.objects.get(username=username)
except Admin.DoesNotExist:
return None
You can have a profile class (say UserProfile) with foreign key to the user that is to be created only when user signs up using the website's registration form. That way, superuser which is created on admin site or through command line wouldn't need an extra profile instance attached to it.
I'm a beginner to the Django Rest Frame work. I want to create a custom user but I have a problem from a long period i try to find a solution through many forums but unfortunately i didn't succeed. hope you help me
models.py
class Account(models.Model):
user=models.OneToOneField(User,on_delete=models.CASCADE)
image=models.ImageField(upload_to='Images/',default='Images/user.png')
date=models.DateField(auto_now=True,auto_now_add=False)
Serializers.py
class AccountCreateUpdateSerializer(serializers.ModelSerializer):
user=UserListSerializers()
image=serializers.ImageField()
class Meta:
model= Account
fields=['id','user','image']
def create(self,validated_data):
user_data=validated_data.pop('user')
account=Account.objects.create(**validated_data)
User.objects.create(account=account,**user_data)
return account
the error :
enter image description here
Your problem is here:
user_data = validated_data.pop('user')
account = Account.objects.create(**validated_data)
User.objects.create(account=account, **user_data)
You're trying to create an Account before creating a User, which won't work because an Account requires a value for user_id. If your User model had a foreign key to Account, instead of the other way around, then creating the account first would be the right way to do it.
Switching to:
user_data = validated_data.pop('user')
user = User.objects.create(**user_data)
account = Account.objects.create(user=user, **validated_data)
should fix the problem as long as your UserListSerializers() is providing the correct data to create a User instance.
Hope that helps.
I have made Custom User model in my Django project. Here it is:
class CustomUser(User):
avatar = models.ImageField(upload_to='avatars')
about_myself = models.TextField(max_length=300)
USERNAME_FIELD = 'username'
def __str__(self):
return self.username
def is_author(self):
return 'blog.change_post' and 'blog.add_post' in self.get_all_permissions()
And after it, I changed all Foreign Keys of user to new CustomUser model. It works OK. But I make one new migration and django cause error, when I want to migrate it:
ValueError: Lookup failed for model referenced by field blog.Comment.author: main.CustomUser
My blog.Comment model:
class Comment(models.Model):
content = models.TextField()
author = models.ForeignKey(CustomUser)
date_create = models.DateTimeField(auto_now_add=True)
post = models.ForeignKey(Post)
What should I do?
Thanks!
Judging from the code you posted, you might be might be better served by extending the user model rather than replacing it. This pattern is usually called a profile model and works via a one-to-one relationship with User.
Profiles provides application specific fields and behaviors, while allowing User to go about it's usual business unchanged. It doesn't require you to muck around with rewriting auth or even necessarily change your foreign keys.
Here's an example of your code written as a profile:
class Profile(models.Model):
# Link to user :
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
avatar = models.ImageField(upload_to='avatars')
about_myself = models.TextField(max_length=300)
def __str__(self):
return self.user.username
def is_author(self):
return 'blog.change_post' and 'blog.add_post' in self.user.get_all_permissions()
Comment model:
class Comment(models.Model):
content = models.TextField()
author = models.ForeignKey(settings.AUTH_USER_MODEL)
date_create = models.DateTimeField(auto_now_add=True)
post = models.ForeignKey(Post)
# How to access the profile:
def check_author(self):
self.author.profile.is_author()
You'll also want to add a signal to create a new profile when a user is registered:
#receiver(post_save, sender=settings.AUTH_USER_MODEL)
def create_profile_for_new_user(sender, created, instance, **kwargs):
if created:
profile = Profile(user=instance)
profile.save()
Django docs on extending users.
If a profile approach doesn't work for you, try inheriting from AbstractUser or AbstractBaseUser instead of User. The abstract models provide the same basic functionality as User and are the preferred technique for recent Django versions.
There are a handful of additional steps however, check out the docs on creating custom users for a run down.