Q: Database design for upvote/downvote in discussion forum? I have a webite where there is a discussion forum. All questions have unique ID and answers have also unique ID with a foreign key referencing to question ID.
I have a user logged in. Using ajax, I can send the data(upvote/downvote,QID/AID, username).But there are few problems.


*

*Whenever user logs back in, I want that when he opens a question, his previous upvotes and downvotes should be displayed.

*A user cannot upvote/downvote a same question multiple times. Like if he upvoted a question to +1, he can only downvote it, not upvote it again.
Solution according to me. I am thinking of maintaining a table where username is the primary key and another attribute is a list of all the upvotes and downvotes he has done. Example:
(username, array)
(baqir, up_A001 up_A050 down_Q011 up_Q123)

Whenever the user logs in, I take this array and make sure all the previous upvotes and downvotes of the user are as it is. If there is a new vote,I add it to the array.
Is there any better solution?
P.S. Not necceassary but my current database structure.
class Question(models.Model):
    QID = models.CharField( default="",max_length=1000, primary_key=True)
    title = models.CharField(max_length=30, default="")
    description = models.CharField(max_length=1055, default="")
    date = models.DateTimeField(default=datetime.now, blank=True)
    username = models.CharField(max_length=6, default="")
    votes = models.IntegerField(default=0)
    approved = models.BooleanField(default=False)

    def __str__(self):
        return self.title

class Answer(models.Model):
    AID = models.CharField(max_length=1000, default="", primary_key=True)
    QID = models.ForeignKey(Question,on_delete=None)
    description = models.CharField(max_length=1055, default="")
    date = models.DateTimeField(default=datetime.now, blank=True)
    username = models.CharField(max_length=6, default="")
    votes = models.IntegerField(default=0)
    approved = models.BooleanField(default=False)

    def __str__(self):
        return self.AID

I am using Django. And I basically want whatever stackoverflow has implemented for their voting of questions and answers.

A: What array people, what are you talking about? You make another table per Q/A or per user, or a table where you just link two things, i.e. user and Q/A and its votes where keys can be repeated (no primary keys for this table).
Any array-like thing is loss of time and energy and it is against good DB design rules anyway.
Example of table keeping votes:
Table votes:
    UID | QID | AID | VOTE

So you connect each user with each question or answer he/she voted. QID or AID can be NULL. When you come to some question, you just check whether table votes has anything to say about it and answers tied to it. If current QID and UID match and you get result, you just act accordingly.
This has a potential of being slow if you have a lot of users, but essentially will work nice.
Second solution is to tie your question/answer with another table keeping in only users that did something (up/down voted it). This will make DB look messier but when your user comes to given Q and its answers you just check whether this table has something to say aboutsaid visitor or not. If I am not clear enough I repeat, new table per each Q and/or A.
You can apply same technique in reverse, i.e. connect user to a table that holds all Q/A that the user voted, which will perhaps be the best way of keeping order and efficiency. So each time the user comes to any Q page you check if he/she have any history for that Q.
No arrays, no nonsense. Just one extra request to check status for currently viewed Q/A.

A: CREATE TABLE QuestionVotes (
    UID ...,  -- User id
    QID ...,  -- Question id
    vote ENUM('up', 'down'),
    PRIMARY KEY(QID, UID)  -- for finding voting status of a question
    INDEX(UID, QID)  -- if you need the votes by a user
) ENGINE=InnoDB;   -- to get benefit of clustered PK

Ditto for AnswerVotes.
Upvote/downvote:  See if the row exists, if not, create the row.  If row exists, either delete the row or complain that the user is up/downvoting twice.
Do not use arrays.  It will become too painful.
If Django won't let you have composite PRIMARY KEYs, abandon Django.
Do not have 1000-char keys in the table.  Disk space and performance will suffer.
User can be only 6 characters.  Not optimistic about scaling big?

A: Upvote and Downvote scenario can be handled using code,If the last vote is a upvote user have permission only to downvote, if the user downvote he has permission to upvote, but for keeping status as you told you can keep a history in a array.

A: the first approach suggested by Dalen seems best
make a separate table for storing votes, and before performing any up/downvote action, check if the user has done any similar action before.
In case he has done opposite action before, delete/deactivate his previous entry in table and make a new entry.
And in case he has already performed the same action for the question before, do nothing, as his up/downvote has already been accounted.
Making a table for such tasks is highly encouraged, as it will not only make your task easier, it will give you a lot more flexibility, like you can add a timestamp with each action to track history or you can hit a count query on the table to find the total  actions performed on a question 
