Django Admin Inline objects - django

I'm completely new to Django coming from PHP and therefore struggling a little with the terminology. This makes searching for an answer quite hard. Hopefully, somebody can tell me if this can be done within the excellent Django admin.
Ok, so the idea is that I have a questionaire which will be filled in by members of the design world. The questionaire class has very few fields, title, introduction, date.
The questions have their own class, there is a limited number in this case 20 and they are the same on each questionaire.
Therefore I have an answers class, the answer belongs to both a questionaire and a question.
class Questionaire(models.Model):
title = models.CharField(max_length=255)
intro = models.TextField(max_length=4000)
date_entered = models.DateField()
date_modified = models.DateField()
def __unicode__(self):
return self.title
class Question(models.Model):
title = models.CharField(max_length=255)
number = models.IntegerField()
def __unicode__(self):
return self.title
class Answer(models.Model):
response = models.TextField(max_length=4000)
questionaire = models.ForeignKey('articles.Questionaire')
question = models.ForeignKey('articles.Question')
def __unicode__(self):
return self.response
Sorry about the formatting above
What I am needing in the Questionaire admin is for each question, an answer field is available inline. If possible with the question name as the form field name.
Is this possible within Django admin?
Would be most grateful for any assistance

See: https://docs.djangoproject.com/en/dev/ref/contrib/admin/#inlinemodeladmin-objects
class AnswerInlineAdmin(admin.StackedInline):
model = Answer
extra = 1
class QuestionAdmin(admin.ModelAdmin):
...
inlines = [AnswerInlineAdmin]

Related

QuerySets are lazy in template

I am working on one question and answer website.I think i have mess with code.I am sending querysets all objects when only one needed.
Like sending all answer of one question when only one needed.
I print only one.
So at that time will it affect database's all record or only record which i will print in template?
View.py
questions = Question.objects.all()
context = {
'questions':questions
}
return render(request,'index.html',context=context)
template_tag.py
#register.simple_tag
def getmostvotedanswer(answers):
answer = answers.order_by('-vote')[0]
return answer.answer
index.html
<p>{% getmostvotedanswer question.answer_set.all %}</p>
In this i am sending all answers but only needed so will it affect database's performance?
Question Model
class Question(models.Model):
question = models.CharField(max_length=400)
uid = models.ForeignKey("User",on_delete=models.SET_DEFAULT,default=1,related_name='user_q_id_set')
vote = models.IntegerField(default=0)
created_at = models.DateTimeField(auto_now_add=True)
catitle = models.ForeignKey("Category", on_delete=models.CASCADE)
editUser = models.ManyToManyField("User",related_name='user_q_edit_set',null=True,blank=True)
Answer Model
class Answer(models.Model):
answer = models.TextField()
qid = models.ManyToManyField("Question")
uid = models.ForeignKey("User",on_delete=models.CASCADE,related_name='user_a_id_set')
vote = models.IntegerField(default=0)
created_at = models.DateTimeField(auto_now_add=True)
editUser = models.ManyToManyField("User",related_name='user_a_edit_set',null=True,blank=True)
In your templates, you are iterating through questions, passing all the answers to your custom template tag and find the one with the most vote.
If that's what you want, you can simply put ordering into your answers model like this:
class Answer(models.Model):
vote = models.IntegerField(default=0)
# ...
class Meta:
ordering = ['-vote']
This way, when you call question.answer_set, it will automatically sort the answers by the vote field.
So you can say question.answer_set.first to get the top voted answer.

Tag system for Django

I am building a Quiz app where a user (Content Creator or Author) can create quizzes (choice based questions and their solutions) from a specific domain. These quiz can be attempted by other users (Consumers - not yet implemented).
To allow quiz consumers to be able to search questions based on specific domains of their interest (and to add granularity to the quiz content), I am implementing a tagging system attached to the questions.
Here are my models:
class question(models.Model):
ques_id = models.AutoField(primary_key=True)
ques_text = models.TextField(max_length=1024, blank=False)
ques_author = models.ForeignKey('author')
ques_created = models.DateField(auto_now_add=True)
ques_dscore = models.IntegerField()
ques_bloom = models.CharField(max_length=3)
ques_subject = models.CharField(max_length=3)
ques_type = models.CharField(max_length=1)
ques_flags = models.CharField(max_length=16)
ques_quiz = models.ManyToManyField('quiz')
def __unicode__(self):
return self.ques_text
class choice(models.Model):
choice_id = models.AutoField(primary_key=True)
choice_text = models.CharField(max_length=256, blank=False)
choice_ques = models.ForeignKey('question')
choice_ans = models.BooleanField(default=False)
choice_tags = models.CharField(max_length=32)
def __unicode__(self):
return self.choice_text
class answer(models.Model):
answer_id = models.AutoField(primary_key=True)
answer_text = models.TextField(max_length=1024)
answer_ques = models.ForeignKey('question')
answer_choice = models.ForeignKey('choice')
answer_tags = models.CharField(max_length=128)
class author(models.Model):
user = models.OneToOneField(User)
domain = models.CharField(max_length=16)
def __unicode__(self):
return self.user.username
# a table for storing all the tags
class tags(models.Model):
tags_id = models.AutoField(primary_key=True)
tags_text = models.CharField(max_length=16)
def __unicode__(self):
return self.tags_text
# table that connects tags with question attached to the tag
# from all the research on the web, it can be infered that
# 3NF tagging (Toxi Solution) is the best way to go
# good for inserts but slow on selects
class tagcon(models.Model):
tagcon_id = models.AutoField(primary_key=True)
tagcon_tags = models.ForeignKey('tags')
tagcon_ques = models.ForeignKey('question')
I have currently applied the 3NF tagging Toxi solution. The issue is that a denormalized system would help in faster selects and a 3NF would be faster inserts but slow searches.
I am confused if I should use ManyToMany field type for tags. Could someone enlighten if it would be better to use a ManyToMany field inbuilt in Django or implement the 3NF system as done?
This is already exactly the same as a ManyToManyField. The only difference is that adding the field would give you an explicit accessor from question to tag.
(Note, your models are very odd. There is absolutely no benefit in prefixing every field name with an abbreviated version of the model name; you can only ever access the field via the model anyway, so you would always be doing question.ques_text, which is redundant. And you shouldn't be defining your own PK fields unless you have a very good reason.)
In my opinion I suggest you try these 2 projects
django-tagging.
django-taggit.

how to query to get the user from m2m relation

I have a model for forum. Its just the basics, and I am trying the grasp the relationship and how to query with them. So, I have a forum with field for question, body, published date, image, and likes. I guess my model design is correct, if not please correct me. So, everything is works as I wanted. Just that, how do I get all the Users who liked the forum and count the likes? How can i query it? Please guide me through.
Thank you.
models.py:
class Forum(models.Model):
question = models.CharField(max_length=150)
body = models.TextField()
pub_date = models.DateTimeField(default=datetime.now)
image = models.ImageField(upload_to=get_upload_file_name)
creator = models.ForeignKey(User, related_name="creator_set")
likes = models.ManyToManyField(User, through="Like")
def __unicode__(self):
return self.question
class Like(models.Model):
forum = models.ForeignKey(Forum)
liked = models.ForeignKey(User)
liked_date = models.DateTimeField(default=datetime.now)
def __unicode__(self):
return "%s likes %s" % (self.liked, self.forum)
Isn't this suppose to work?:
Forum.objects.get(pk=1).likes.all()
Forum.objects.get(pk=1).likes.count()

Django Queryset of related objects, after prefiltering on original model

Given a queryset for one model, I want to get a queryset of another model that is related by foreign key. Take the Django project docs' weblog schema:
class Blog(models.Model):
name = models.CharField(max_length=100)
tagline = models.TextField()
def __unicode__(self):
return self.name
class Author(models.Model):
name = models.CharField(max_length=50)
email = models.EmailField()
def __unicode__(self):
return self.name
class Entry(models.Model):
blog = models.ForeignKey(Blog)
headline = models.CharField(max_length=255)
body_text = models.TextField()
pub_date = models.DateField()
mod_date = models.DateField()
authors = models.ManyToManyField(Author)
n_comments = models.IntegerField()
n_pingbacks = models.IntegerField()
rating = models.IntegerField()
def __unicode__(self):
return self.headline
Suppose I have an author object, and I want to get every blog that author has written for, as a queryset. I do something like author_blogs = [entry.blog for entry in author.entry_set]. But I'm left with a list in this case, not a queryset. Is there a way I can do this directly with ORM queries, so I can set it up via a custom Entry manager with use_for_related_fields = True and do something like author_blogs = author.entry_set.blogs, and get the benefits of delayed evaluation, etc., of a queryset?
Edited scenario and solution
So, I realized after the fact that the application of my question is slightly different than how I posed it above, for which Daniel Roseman's situation makes a lot of sense. My situation is really more like author.entry_set.manager_method().blogs, where manager_method() returns a queryset of Entry objects. I accepted his answer because it inspired the solution I found which is to do:
author_blogs = Blog.objects.filter(entry__in=author.entry_set.manager_method())
The nice thing is that it only uses one DB query. It's a bit tricky and verbose, so I think it's best to define blogs() as an object method of Author, returning the above.
The trick for this is to remember that if you want a queryset of Blogs, you should start with the Blog model. Then, you can use the double-underscore syntax to follow relations. So:
author_blogs = Blog.objects.filter(entry__authors=author)

Django counting related objects in model layer

It is possible to do something like this working:
class Book(models.Model):
voters = models.ManyToManyField(User, blank=True)
vote = models.IntegerField() # summary of all votes
def average_vote(self):
return int(vote/self.annotate(Count('voters')))
Maybe something like this?
class Book(models.Model):
voters = models.ManyToManyField(User, blank=True)
vote = models.IntegerField() # summary of all votes
def average_vote(self):
return int(self.vote/self.voters.all().count())
Let me know if that works. I haven't tested it.
Just override the default manager to make it always return an annotated queryset:
class BookUserManager(models.Manager):
def get_query_set(self, *args, **kwargs):
return super(BookUserManager, self).get_query_set(*args, **kwargs).annotate(average_vote=models.Avg('books__vote'))
class BookUser(User):
objects = BookUserManager()
class Meta:
proxy = True
class Book(models.Model):
# Next line has been changed to use proxy model. This *will* affect the m2m table name.
voters = models.ManyToManyField(BookUser, blank=True, related_name='books')
vote = models.IntegerField() # summary of all votes
objects = BookManager()
Then, you can get at the value like any other attribute on your the user model:
user = BookUser.objects.get(username='joe')
print user.average_vote
Update: Sorry... got that all wrong. That's what I get for reading the question too quickly. You'd actually need to annotate User not Book, but since User is coming from django.contrib.auth (I'm assuming) that's not going to be possible, or at least it requires more steps. Code above has been updated.