This is a 2 problem post, which i suspect are somehow connected. My posts app on Django doesn't migrate properly (I think), and adding the 'author' (Users AbstractUser model) breaks my code with the error:
str returned non-string (type tuple)
whenever I try to add a row.
I changed the name of the table using db_table
(so it will change Postss to Posts on the admin page) and added an output to the __str__
function, I tried a few variations of output for the str function but non of them worked. I even tried to comment it out. and still. no changes in the table name or the error. I tried changing my str functions a few times and got the same result. when deleting the str function, I still get that same result.
I have a few wild guesses about this situation:
author=...
row resolves this problem but doesn't change the table name, but I do need the user fk there).Python 3.9.1
(?).python manage.py migrate
and python manage.py makemigrations
.posts/models.py:
from django.db import models
from users.models import Users
class Posts(models.Model):
content = models.TextField(max_length=255)
author = models.ForeignKey('users.Users', on_delete=models.CASCADE, null=True)
timestamp = models.DateTimeField(auto_now_add=True, null=True)
class Meta:
db_table = 'Posts'
def __str__(self):
return self.content + " " + self.author.email + " " + self.timestamp
I will add my users model too:
from django.db import models
from django.contrib.auth.models import AbstractUser
# https://rahmanfadhil.com/django-login-with-email/
class Users(AbstractUser):
USERNAME_FIELD = 'email'
email = models.EmailField(unique=True)
REQUIRED_FIELDS = ['username'] # removes email from REQUIRED_FIELDS
def __str__(self):
return (self.email, self.username)
You are trying return a tuple
, it must be a string
.
def str(self): return (self.email, self.username)
Use the new-style formatting in Python
Try this instead:
class Users(AbstractUser):
...
def __str__(self):
template = '{0.email} {0.username}'
return template.format(self)
class Posts(models.Model):
...
def __str__(self):
template = '{0.content} {0.author.email} {0.timestamp}'
return template.format(self)
or
def __str__(self):
return '{} {} {}'.format(self.content, self.author.email, self.timestamp)
Second Question:
If I understand your question correctly, then to change the label for the model, you need to use verbose_name
:
class Meta:
verbose_name = 'Post'
verbose_name_plural = 'Posts'
With option db_table you change the name of the database table to use for the model.
And see explanation how it works, from Django: if you have an app bookstore
(as created by manage.py startapp bookstore
), a model defined as class Book
will have a database table named bookstore_book
.
Then db_table
must be:
class Meta:
# your desired table name can you find in your database
db_table = 'appLabel_modelName'
To list the tables in the current database for PostgreSQL, you can run:
python manage.py dbshell
\dt
See also Django db_table