why is related_name plural for ForeignKey? - django-models

Currently I am reading
Django 4 By Example - Fourth Edition
We are creating a Post model in blog app.
The table is named as blog_post as per the sqlmigrate commands.
But when we add a ForeignKeyfrom Post to User model by
author = models.ForeignKey(User, on_delete=models.CASCADE,
related_name='blog_posts')
the related_name is blog_posts instead of blog_post.
Why is it in plural instead of the actual table name?

The related_name=… parameter [Django-doc] is used to query items in reverse. In this case it means that for a given User (author), you can retrieve all the Posts that author has written with:
my_user.blog_posts.all()
Since there can be zero, one, or more such Posts, this is a collection, and hence it is usually written in plural form. my_user.blog_post.all() would hint that this is a single item, which is not the case.
If you do not specify a name, the default for related_name=… will be modelname_set, with modelname the name of the model in lowercase, so post_set, again to hint that this is a collection of Post objects.
For a OneToOneField [Django-doc] the related_name=… is usually singular, since then there would only be at most one such Post. The default for the related_name=… for a OneToOneField is therefore modelname, so here it would be post.
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.

Related

Field Type of entity-query not working, correctly retrieves list of content-items but incorrectly stores them as 'Empty Slot"

I have an Authors App which has x amount of authors. I have another app and have configured an Field Input-Type entity-query in it which pulls from the Authors App. It does this correctly and I can select multiple authors. However upon save, when I go to retrieve a content item which should contain the selected authors, I am given "empty slot" for the place of each author
Real entity fields are Entity relations, and they enforce validity. So they only work with entities in the same app, as that's kind of a sealed scope. This is important that Apps can ensure export/import and still work for all standard use cases.
To reference entities of another app you must use strings instead. This can be done using the string-query field which has the same functionality.
The only downside is that your code will need to then look up the entity in the other app using the id or guid (whichever you store) in Razor.

Django, relate User with another table

So I got the tables you can see in the image below:
.
What I would like to do is to create a relationship so that each user (of django auth_user) will be enrolled(or able to enrol) to exactly one "course" so that he will be able to see next events for his modules.
Do I have to create another table and place 2 foreign keys or this is a way to do it in 'php' and it's more simple with Django? I was suggested to create 'student' model inheriting from 'User' with extended behavior and one to many relationship on auth. I tried to do that but unfortunately had not results since I'm really new to Django & Python.
If every auth_user (or auth.User) will be or have the opportunity to be enrolled on a course I would create a 'user profile' model that has a 1-to-1 relationship with the django User model. You can store additional User data in this model, including what course they are enrolled on. See https://docs.djangoproject.com/en/dev/topics/auth/customizing/#extending-the-existing-user-model for more details but here is an example:
class UserProfile(models.Model):
user = models.OneToOneField('auth.User')
course = models.ForeignKey('courseapp.Course', null=True)
You would probably need to create a signal that gets fired each time an auth.User object is saved, such that if it is the first time that User object has been saved, it automatically creates the UserProfile:
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from yourusersapp.models import UserProfile
def create_user_profile(sender, instance, created, **kwargs):
# Automatically creates a UserProfile on User creation.
if created:
UserProfile.objects.create(user=instance)
post_save.connect(create_user_profile, sender=User)
When you query a User object, you can then reference the User object's profile like:
user_object.userprofile
You could then create a Course object and link the user_object indirectly via its UserProfile to that Course:
course = Course.objects.create(name='course_name', next_field='whatever')
user_profile = user_object.userprofile
userprofile.course = course
userprofile.save()
Now you have a user object with a UserProfile that is linked to only 1 course. Many users can be on the same course, but a user can only be on 1 course. You can also reference all users on a particular course like:
course = Course.objects.get(name='course_name')
course_users = course.userprofile_set.all()
HTH
I think that you can go about this one of two ways.
Extend the User model. 'Student' would probably be a good name for your new model. It would have a OneToOne relationship with 'User', and a ForeignKey relationship with 'Course'. It can store any other information that is applicable to students only. Documentation for how to do that can be found here https://docs.djangoproject.com/en/1.6/topics/auth/customizing/#extending-the-existing-user-model
Create a custom User model that has a ForeignKey relationship with Course. This approach is a bit more complicated, but yields a slightly cleaner end result. Documentation for that is here. https://docs.djangoproject.com/en/1.6/topics/auth/customizing/#substituting-a-custom-user-model
Sorry if it seems like I'm just sending you to the Django docs, but both of those sections are well written and should explain things pretty clearly. If you'd like to post another question with example code we can try and see why your original attempt at extending the User model didn't work. By the way, your "Student" model shouldn't have to inherit from the User model in order to extend it.

Django ownership foreign key to User or UserExtenstion

I'm quite new with Django, and so far I have a pretty basic setup where I attach an extra model to the default User model from (django.contrib.auth.models). In my accounts.models.py I have something in the line of:
class UserExtension(models.Model):
user = models.OneToOneField(User, primary_key=True)
# more code
I also have another model which needs to be specified an owner. My question is: Which is the better (more django-ish, more readable, more efficient, more flexible) way to signify the owner:
class Owned(models.Model):
# code
owner = models.ForeignKey(User)
# more code
or:
class Owned(models.Model)
# code
owner = models.ForeignKey(UserExtension)
# more code
I'll really appreciate if you mention pros and cons of those approaches.
I'd recommend the first option. The user model is the nontrivial model in the sense that an owned object should not be able to exist without a user, but could exist without a UserExtension.
Also consider that in Django 1.5 you are able to create custom user model, eliminating the need for the UserExtension class. See the documentation for more information.
Consider using UserProfile for any per user add-on information. Check out this blog to see how to do it. Then you can be assured that you are creating UserProfile object every time you create the User.
Now whether you FK on User or UserProfile depends logically on what you are doing within Owned. If Owned works with User's data/field, FK on User; if it works with UserProfile's data, FK on UserProfile.

django related_name for field clashes

I am getting a field clash in my models:
class Visit(models.Model):
user = models.ForeignKey(User)
visitor = models.ForeignKey(User)
Error: One or more models did not validate:
profiles.visit: Accessor for field 'user' clashes with related field 'User.visit_set'. Add a related_name argument to the definition for 'user'.
profiles.visit: Accessor for field 'visitor' clashes with related field 'User.visit_set'. Add a related_name argument to the definition for 'visitor'.
what would be a sensible 'related_field' to use on visitor field? This model
basically represents the visits that take place to a
particular user's profile.
Also should I replace any of the ForeignKey's with a ManyToManyField? The logic is a bit confusing.
Edit:
This seems to fix it, but I am unsure if it's what I want. :)
class Visit(models.Model):
user = models.ForeignKey(User)
visitor = models.ForeignKey(User, related_name='visitors')
When you have a ForeignKey, it creates a property named with the model name plus _set to the referenced model. The problem here is that both foreign keys want to create a property on User named visit_set. The solution is to add related names that are different for each foreign key.
Usually, I use plurals for related names. In cases like these, I add an "as" clause to the related name:
class Visit(models.Model):
user = models.ForeignKey(User, related_name="visitsAsUser")
visitor = models.ForeignKey(User, related_name="visitsAsVisitor")
You don't want a ManyToManyField unless you can have zero or more visitors per Visit, or users per Visit.
If a visit is a strong concept in your application, then it might make sense to have it the way you defined: visit consists of a 'user user' and a 'user visitor'.
If, however, a visit is just a way in which users relate among themselves, then perhaps you should have a ManyToMany relation between users. For that purpose you should probably use ManyToManyField.symmetrical in a User Profile (in which you extend the information that comes with auth.models.User).
In any case, regarding the related_name, you may either disable the backwards relation if you won't be accessing the visits from the user, or use a sensible name such as visits_to_self on user and visits_to_others on visitor, which would allow seeing who visited a user by calling user.visits_to_self and who the user visited by user.visits_to_others.

Elegant way to store anonymous users with nick names in django?

I have a simple Post model in my django app:
class Post(models.Model):
category = models.CharField(max_length=10, choices=choices)
message = models.CharField(max_length=500)
user = models.ForeignKey(User, editable=False)
I'd like to implement the feature of having anonymous users create posts with nick names. Unfortunately django doesn't allow you to save an instance of AnonymousUser as a foreignkey to the Post class.
I was thinking of adding a "dummy" user record into the db that represents the anonymous user(id=0, or some negative number if possible) that would be used for all posts without a user. And if it is present a nullable name field would be used to represent the nickname of the anonymous user.
This solution seems a bit hacky to me. Is there any cleaner more effecient solution?
If you can identify new users by some session information, you could just create normal user accounts, pro forma so to speak - with a flag to identify them as volatile (this may lead to some regular maintenance cleanup).
If, during session lifetime, the user actually want to register, you can reuse the user account on your side and the user can keep all his data on his.
As #slacy commented and #Dominique answered; instead of rolling your own take a look at existing projects, e.g. this:
http://www.stereoplex.com/blog/introducing-django-lazysignup
Not tested , but this can help:
https://github.com/danfairs/django-lazysignup
You can add blank=True and null=True to User ForeignKey and set it to None, if user is anonymous. You just need to store the nickname somewhere.
I am new to Django. A friend told me not to use ForeignKey further stating that using CharField is ok. ForeignKey is slower than CharField, as it has some check for user info.

Resources