2đź‘Ť
You can use a one-to-one relation the other way around:
class Vote(models.Model):
voter = models.ForeignKey(User)
...# some additional fields
class Question(models.Model):
title = models.CharField(max_length=150)
detail = models.TextField()
submitter = models.ForeignKey(User)
date_added = models.DateTimeField(auto_now_add = True)
vote = models.OneToOneField(Vote)
...# some additional fields such as tags
class Answer(models.Model):
detail = models.TextField()
submitter = models.ForeignKey(User)
date_added = models.DateTimeField(auto_now_add = True)
vote = models.OneToOneField(Vote)
...
0đź‘Ť
Have a look at abstract base classes
You can put the common fields/functionality in there (submitter
, detail
, etc) and then inherit it in your Question
and Answer
models
Edit:
Based on the other answers and me looking at your problem a bit more I’m changing my answer. You’re currently walking the line between “DRY” and “good readability/maintainability” and different developers come down on different sites of the line, so you’re likely just going to have to pick the one you like best.
On that note, here’s how I’d lay it it out:
##############################
# Question and Answer Models #
##############################
class QuestionAnswerBase(models.Model): # Choose a better name :)
detail = models.TextField()
submitter = models.ForeignKey(User)
date_added = models.DateTimeField(auto_now_add = True)
... # More common fields here
class Meta:
abstract = True
class Question(QuestionAnswerBase):
title = models.CharField(max_length=150)
...# some additional fields such as tags etc
class Answer(QuestionAnswerBase):
... # No extra fields needed but you'll prob want a custom __unicode__ method etc
###############
# Vote Models #
###############
class VoteBase(models.Model):
voter = models.ForeignKey(User)
... # Other shared fields etc
class Meta:
abstract = True
class AnswerVote(VoteBase):
answer = models.ForeignKey(Answer)
class QuestionVote(VoteBase):
question = models.ForeignKey(Question)
(comment blocks are for readability in this instance.)
“But now I have even more models!”
Yes you do, but there are no duplicated fields on any of them, and the abstraction means you have the power to add different behaviour to- for example- a QuestionVote
and an AnswerVote
(say you want the ability to retract AnswerVote
s if a better Answer
comes along, but don’t want to be able to retract QuestionVote
s) without the need to have “Is this X a Y or a Z? If it’s a Z do this else do this” clauses in every model method you write.
“It looks ugly!”
It’s both readable and explicit, which means that it’s beautiful 🙂
“I want to do it another way!”
That’s fine, there are already other good answers that show how to do that. This is just my suggestion as someone that is quite keen on best practices and readable code.
- [Answered ]-Nested Json with multipart/form-data in AFNetworking 2.x
- [Answered ]-Django access m2m field attribute from a queryset
- [Answered ]-Edit form in Django 1.6
- [Answered ]-Model person with several first names and one primary first name in Django?
- [Answered ]-Django1.8 and Mongoengine NameError: name 'IntegerField' is not defined
0đź‘Ť
I personally feel that DRY is pretty important, so I would be willing to sacrifice some elegance to achieve it. For example, in this case, I might do this:
class QuestionOrAnswer(models.Model):
is_question = models.BooleanField()
title = models.CharField(max_length=150)
detail = models.TextField()
submitter = models.ForeignKey(User)
date_added = models.DateTimeField(auto_now_add = True)
question_specific_field = ...
def clean(self):
# Make sure that question_specific_field is set only if is_question is true.
class Vote(models.Model):
target = models.ForeignKey(QuestionOrAnswer)
...
- [Answered ]-Got an unexpected keyword argument 'pk' on genric view
- [Answered ]-Minimal developer setup of sorl-thumbnail with Django 1.7