FK question in database structure

In my survey, I am using user, area, question as FK’s for answer, and Area, user for comments (Comments not tied to specific question like answer).

The question I have are FK’s relationships automatically created and stored or do you have to store values to then join/search by them. It appears to be the latter as if I don’t include a specific data value, such as user_id = user_id in the create statement, for the I get an error:

NOT NULL constraint failed: ISO22301_comment.user_id

If I look at the db schema the model results in a field for user_id.

Model

class Answer(models.Model):
    area = models.ForeignKey(
        Area, on_delete=models.CASCADE, null  = True 
    )
    value = models.IntegerField(null = True, blank=False)
    company=models.CharField(max_length=250, null = True)
    timestamp= models.TimeField(auto_now = True)
    question = models.ForeignKey(
        Question, on_delete=models.CASCADE, null  = True, unique=False
    )
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    username = models.CharField(max_length=75, null=True,)

    def __str__(self):
        return f"{self.user_id}  {self.username} answer to {self.question} is {self.value} at {self.timestamp}"

class Comment(models.Model):
    company = models.CharField(max_length=75, null=True,)
    comments = models.CharField(max_length=1000, default="No comment")
    timestamp = models.TimeField(auto_now = True)
    area = models.ForeignKey(
        Area, on_delete=models.CASCADE, null = True, blank=True)
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    username = models.CharField(max_length=75, null=True,)

views.py:

`       questionareas_area_id = Question.objects.values_list('area_id', flat=True) # get area names, Flat retuns just the text list of areas
        user_name=request.user #Get username value as integer id NEW
        user_id=request.user.id
        company = request.user.groups.values_list('name',flat = True)# Get company for user logged in
        Comment.objects.create(comments = results_comments, user_id = user_id, company = company, username=user_name)
       # entry_time = datetime.datetime.now() #set time for data entry
   
        for i in range(len(keys_values)):#fill in answers to SQL table

            Answer.objects.create(question_id = keys_values_int[i],value = answers_values_int[i], area_id = questionareas_area_id[i], user_id=user_id, company=company, username=user_name)
 `

Hello and welcome @jlc1978

When you define a ForeignKey like user = models.ForeignKey(User, on_delete=models.CASCADE), Django automatically creates a corresponding field in the database called user_id. This user_id field stores the actual ID of the User object. That’s why you see user_id in the schema. It’s an alias for the user field when you want to access the raw ID value instead of the related User object.

You can access the full User object with comment.user, and if you need the ID specifically, you can use comment.user_id.

Regarding your code, you can simplify your Comment.objects.create() call by directly using the user object rather than referencing user_id:

Comment.objects.create(comments=results_comments, user=request.user, company=company)

and this is also valid:

some_comment.user = some_user

The username field in your Comment model is redundant, since you can access the username via the user ForeignKey, like this: comment.user.username.

So, your Comment model can be simplified to:

class Comment(models.Model):
    company = models.CharField(max_length=75, null=True)
    comments = models.CharField(max_length=1000, default="No comment")
    timestamp = models.TimeField(auto_now=True)
    area = models.ForeignKey(Area, on_delete=models.CASCADE, null=True, blank=True)
    user = models.ForeignKey(User, on_delete=models.CASCADE)

By doing this, you let Django handle the ForeignKey relationships for you.

I’m not sure if that answers your question?

1 Like

In addition to the excellent answer above -

This depends upon how you’re creating them. If you’re using Django’s facilities such as “inline formsets” for entering data for these related models, then yes, Django takes care of that for you. Otherwise, it is up to you to ensure that field is properly populated.