I would like to define a django model which has many-to-one relationship with itself. It is a user profile, connected as a OneToOne field with the authentication user model. I would like to save which user (if any) was the one who referred the 'current' user to my system. This means I have the following definition:
class UserProfile(models.Model):
user = models.OneToOneField(User, blank=True, related_name='profile')
class Meta:
abstract = True
class SpecificUserProfile(UserProfile):
referrer = models.ForeignKey('self')
I saw the django defaults to naming the set of referenced models by the name of the class with a suffix _set. I believe I will be getting something along the lines of specific_user_profile_set. I would much prefer to have it named u1.referrer and u2.referred or u2.referred_set. Is there any way this can be achieved?
related_name='profile'
This is the argument to define a name for any related field, so:
class SpecificUserProfile(UserProfile):
referrer = models.ForeignKey('self', related_name='referred')
Related
I have a models as
class Doctor(models.Model):
user = models.OneToOneField(
User,
on_delete=models.CASCADE,
primary_key=True,
related_name="user")
# other fields...
In my template, I easily can access the doctor object as request.user.doctor but using it in my views it causes the 'User' object has no attribute 'doctor' Error. so is it possible to access it as templates in my views too.
The related_name=… parameter [Django-doc] is the name of the relation in reverse, so to access the Doctor object from a User, since you have set this to user, you thus access the Doctor object with request.user.user, but that is misleading.
You thus better rename the relation to:
class Doctor(models.Model):
user = models.OneToOneField(
User,
on_delete=models.CASCADE,
primary_key=True,
related_name='doctor'
)
# other fields …
Note: It is normally better to make use of the settings.AUTH_USER_MODEL [Django-doc] to refer to the user model, than to use the User model [Django-doc] directly. For more information you can see the referencing the User model section of the documentation.
I'm making one of my first django apps with sqlite database. I have some models like for example:
class Connection(models.Model):
routeID = models.ForeignKey(Route, on_delete=models.CASCADE)
activityStatus = models.BooleanField()
car = models.ForeignKey(Car, on_delete=models.CASCADE)
class Route(models.Model):
name = models.CharField(max_length=20)
and forms
class RouteForm(ModelForm):
class Meta:
model = Route
fields = ['name']
class ConnectionForm(ModelForm):
class Meta:
model = Connection
fields = ['routeID', 'activityStatus', 'car']
And in my website, in the url for adding new Connection, I have cascade list containing RouteIDs. And I'd like it to contain RouteName, not ID, so it would be easier to choose. How should I change my ConnectionForm, so I could still use foreign key to Route table, but see RouteName instead of RouteID?
For now it's looking like this, but I'd love to have list of RouteNames, while still adding to Connection table good foreign key, RouteID
Update the Route Model's __str__ method:
class Route(models.Model):
name = models.CharField(max_length=20)
def __str__(self):
return self.name
Because the __str__() method is called whenever you call str() on an object. Django uses str(obj) in a number of places like in Modelform. By default it returns id or pk that is why you were seeing ids in model form. So by overriding it with name, you will see the names appear in choice field. Please see the documentation for more details on this.
I want to assign many Region to the UserProfile model, how to do it?
the code
class Region(models.Model):
name = models.CharField(max_length=30)
created_at = models.DateTimeField(auto_now=True)
class UserProfile(models.Model):
user = models.OneToOneField(
region = models.ForeignKey(Region, on_delete=models.CASCADE, null=True, blank=True)
The relation you describe is not a ForeignKey, which means that a UserProfile has (at most) one related Region, but a ManyToManyField [Django-doc].
A ManyToManyField thus means that a region can be related to zero, one, or more UserProfiles, and a UserProfile can be related to zero, one, or more Regions.
You can thus change the models to:
class Region(models.Model):
name = models.CharField(max_length=30)
created_at = models.DateTimeField(auto_now=True)
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
regions = models.ManyToManyField(Region)
In a relational database this is implemented by adding an extra (hidden) table with ForeignKeys to Regions and UserProfiles. But the Django ORM works in a "transparant" way and thus hides the implementation details.
See the documentation for more information on how to "populate" such relation.
from django.contrib.auth.models import AbstractUser
class UserProfile(AbstractUser):
regions = models.ManyToManyField(Region,related_name='User')
I think this is the ideal way to implement what you need. Using ManyToManyField allows you to map userprofile object to more than one region object and vice versa.
Also, Inheriting Abstract User allows you to add region field to Django User Table, which is better than creating another table for linking user to and region field.
So I have been searching all around the internet for a full example of how to user AbstractUser when u have at least 2 different models. Didn't find anything conclusive.. at least that would work on latest version of Django (2.0.1).
I have 2 models, teacher and student, and registration needs to be different. Besides username, email, name and surname, I need for example, for the student, to upload a profile picture, email, phone, student_ID. And for teacher, bio, academic title and website. Did I start good ? What is the right approach ?
class Profile(AbstractUser):
photo = models.ImageField(upload_to='students_images')
email = models.EmailField()
phone = models.CharField(max_length=15, )
class Student(Profile):
student_ID = models.CharField(unique=True, max_length=14,
validators=[RegexValidator(regex='^.{14}$',
message='The ID needs to be 14 characters long.')])
def __str__(self):
return self.name
class Teacher(Profile):
academic_title = models.CharField(max_length=30)
bio = models.TextField()
website = models.URLField(help_text="E.g.: https://www.example.com", blank=True)
Your goals can be accomplished using a 'Profile' pattern. You don't necessarily need to use a custom user model for this. But you need to have a single common model to for authentication; you can use the builtin django user for this or a custom class... Your Student and Teacher models should be OnetoOne relationships. This is the recommended solution per the documentation.
If you wish to store information related to User, you can use a OneToOneField to a model containing the fields for additional information. This one-to-one model is often called a profile model, as it might store non-auth related information about a site user.
In your case, you may do something like this:
class StudentProfile(models.Model):
user = models.OneToOneField('User', related_name='student_profile')
# additional fields for students
class TeacherProfile(models.Model):
user = models.OneToOneField('User', related_name='teacher_profile')
# additional fields for teachers
Then you can create your registration forms based on these profile models.
class StudentResistrationForm(forms.ModelForm):
class Meta:
model = StudentProfile
fields = (...)
class TeacherRegistrationForm(forms.ModelForm):
class Meta:
model = TeacherProfile
fields = (...)
You can create the user instance to which the profile is related to at the same time you create the profile. You might do this with formsets, for example.
add
class Meta:
abstract = True
to profile model
and change AbstractUser to models.Model
I am using Django Rest Framework to provide API to a mobile app. I have two models, Order and User. Order has a foreign key relation to User.
For about 1% or so of all my order objects, the User field is null. I've been testing this behavior using cURL.
If I do a cURL without a user object, it tells me "This field is required".
If done with a wrong user object, it tells me that the object does not exist. Both of these are the intended and expected behaviors.
I'm trying to figure out how it is possible for some of the Order objects to be saved without a user field. Is there something I'm not taking into account?
My views:
class OrderList (generics.ListCreateAPIView):
model = Order
serializer_class = OrderSerializer
And serializer:
class OrderSerializer (serializers.ModelSerializer):
user = serializers.SlugRelatedField(slug_field = 'user')
partial = True
class Meta:
model = Order
Models:
class User (models.Model):
uid = models.CharField(max_length =200, unique=True)
class Order (models.Model):
uid = models.ForeignKey (User, related_name = "orders", verbose_name = "User",blank=True, null=True)
You could use two different ModelSerializer classes, one for creation, that makes sure, that an Order object can't be created without a related User and one for updating orders, that passes required=False to the related field's constructor, so that you still can save existing orders that haven't a related User.
Try adding default=None to your models.ForeignKey declaration. You could also just create an anonymous user in the users table and when the user isn't specified it could set the anonymous user instead.