Django project architecture guidance - django

I'm working on a project and I'm not sure what my next step is to be or how to best achieve the result that I want.
What I would like to do
Create a quiz-like app where I can add questions and answers, and have users select the right options either through multiple-choice or text input and have the answer validated against the correct question
What I currently have
I have a Django setup of the following
from django.db import models
class Exam(models.Model):
name = models.CharField(max_length=64)
def __str__(self):
return self.name
class Question(models.Model):
question_text = models.CharField(max_length=256)
exam = models.ForeignKey(Exam)
class Answer(models.Model):
text = models.CharField(max_length=128)
question = models.ForeignKey(Question)
def __str__(self):
return self.text
This is what I currently can do
I can use the admin panel to add new questions, answers and exams
I can pass the new data to render them on a template and therefore the website, so if I add a new question I can have it appear on the website
I also know how to create a form that passes data to the server and adds new data to the database without having to use the admin panel
I know how to pass data to a template from the database
What I don't know how to do
I don't know how to display the answers in a way that allows users to interact with them. For example, do I use HTML5 forms, do I have use JavaScript, do I use the Django forms, do I use the Django multipleChoice class?
For starters, if I am able to output the Answers to the Question in a multiple-choice like field that would be a nice start, where the server would return either "Correct" or incorrect based on whether the question is incorrect or not.
What I think might be related to what I need to know
Do I have to use the Django REST framework for this?
Django version: 1.11

If you just show the question and answers as a list and user(s) will answer it (without store the answers and result) ~> just show the list and when user click submit ~> use Ajax to send data (which one you save is as param or json) to server and check the answers in views.py then response the result content to user(s)
If you want to do more than that like:
Multi select answers, save answer as template, save answer in database, save the result, Re-use the answer (1 answer belong to many question)... You need to learn more think like:
Manytomany field, Data flow,... just all the basic thing in Django tutorial

Related

How to save a model record as a template for reuse later

I have a basic blog app that has a Post model:
class Post(models.Model):
author = models.ForeignKey(
get_user_model(), null=True, on_delete=models.SET_NULL)
title = models.CharField(max_length=30)
content = models.CharField(max_length=30)
template_specific_entry = models.CharField(max_length=30)
I need users to be able to create a Post template with template_specific_entry field values, and then other users to use these templates to create new post records, updating title and content but not template_specific_entry.
See the example use case below:
I would like to retain the original Post templates in their original form, so multiple versions of that template can be used.
My question is: what's the most efficient way to go about creating this structure?
Should I create two models, PostTemplate and Post and somehow link the template_specific_values between them?
Since this is 'row level' functionality, is it better to do this via model methods, so templates and posts are stored in the same model? E.g. def createTemplate(self): and def createPost(self): referencing the same model?
In each case how would I actually implement this?
Your drawing is a very good way to understand the problem you're trying to solve. And in fact, it's also clearly showing how your models should be constructed. You have templates and posts and each post needs to be linked to one and only one template.
You can almost see your drawing as the blueprint for your models:
PostTemplate has a ForeignKey to User (since there's an author, in your example "Author1") and has some specific characteristics (template_specific_values although I would try to name this field differently). Note that you use plural here, so I'm wondering if this should be a CharField and not something else, like an ArrayField.
Post has a ForeignKey to User (the author) and to PostTemplate, so that one template can "have" many posts, but each posts only one template.
When the user has selected a template, and then writes the post, the fk of the post gets set to the chosen template.

How to save user query terms from a search navbar in database that can be acessed after user sessions?

I have a search navbar and I want to save search queries so I can improve the navbar and the autocomplete api, but I'm not sure how. sessions variables seem to only work when user is online and it's difficult to save many users. Should I create my own user model and then write data to it. Can you give me a simple example of how to do this?
I've tried using sessions.request to save variables and then access them after a session and have been unable.
You question is a bit unclear but why not create a table for search terms and foreign key to user model if that's what you need. For example:
class SearchTerm(models.Model):
keywords = models.TextField()
user = models.ForeignKey(User)
Naturally, this will work for logged in users only where you can do something like this in your view:
def search(request):
keywords = request.get('keywords')
user = request.user
st, created = SearchTerm.objects.get_or_create(keywords=keywords, user=user)
Look, this is a very simplistic example to illustrate what I think you want to do, but I'm not sure if I have fully understood your question.

Django api calculate count of responses

I am trying to do a survey application in django. My model is as follows:
class mymodel(models.Model):
resptype = models.ForeignKey(Response)
ques = models.ForeignKey(Question)
response = models.CharField(max_length=5, blank=True)
Here i am using rest framework to send data to my front end. Right now i have my api defined as follows:
class mymodelList(APIView):
def get(self, request, format=None):
surveydata = mymodel.objects.all()
serialized_surveydata = mymodelSerializer(surveydata, many=True)
return Response(serialized_surveydata.data)
In my app, I have a standard set of 16 questions with multiple choice responses and the choice is saved in the response column in the model.
Now what I am trying to achieve is to calculate the count of responses for each question . ie. For question 1, what is the count that a person responded with 1 or 2 or etc.
Also i would like to know how to send the calculated counts through another json field from the rest framework because I don't have any model defined separately for this data.
EDIT:
This command did the trick for my query but i still not able to figure out how to send it to the front end as a serialized object.
x = mymodel.objects.values('ques','response').order_by().annotate(number_of_responses=Count('response'))
That's not really a great structure for your model, it would probably be easier to create separate Question and Choice classes. The Django tutorial actually uses this type of application as an example... take a look at that for some guidance
Check #detail_route or #list_route from viewsets depending on if you want to show this info per question o for all questions at once.
This will allow you to define a custom endpoint to request the information you are asking for. To do so, you may also need to define a custom serializer to pass extra data or a filter if you want to filter by question, user, etc.

MongoEngine query to get Post's author and Comments authors for Posts (at the same time)

I'm working on a web project with Django and MongoDB as my database (using MongoEngine to connect them).
I have to create Celery task to cleanup old user accounts. I need to only clean lazy users accounts without any content after one month (lazy users are automatically created users when they first connect to the website). What count as content? Any posts from the user or comments on any of the posts.
I did it like this, but I want to transform this into query if possible:
def clean_inactive_lazy_users():
users_with_content = []
for post in api_models.Post.objects:
users_with_content.append(post.author)
for comment in post.comments:
users_with_content.append(comment.author)
users_with_content = list(set(users_with_content))
for user in account_models.User.objects:
if not user.is_authenticated() and (timezone.now() - user.connection_last_unsubscribe).days >= settings.DELETE_LAZY_USER_AFTER_DAYS and user not in users_with_content:
user.delete()
The models look like this:
base.py
class AuthoredEmbeddedDocument(mongoengine.EmbeddedDocument):
author = mongoengine.ReferenceField(models.User, required=True)
class AuthoredDocument(mongoengine.Document):
author = mongoengine.ReferenceField(models.User, required=True)
api_models:
from . import base
class Comment(base.AuthoredEmbeddedDocument):
"""
This class defines document type for comments on posts.
"""
class Post(base.AuthoredDocument):
"""
This class defines document type for posts.
"""
account_models:
class User(auth.User):
def is_authenticated(self):
return self.has_usable_password()
Hopefully I provided enough information so you can help me with the problem. Thanks!
I think there are a couple ways for you to clean this up.
You could get all author unique ids of posts with something like:
user_ids_with_posts_list = Posts.objects.scalar('author.id', flat=True).distinct('author.id')
scalar should give you a list of author ids instead of document objects and distinct
should make sure they are unique. This pushes what you are doing in python to mongodb
You could then construct a query for Users. You would hvae to change your days ago into a date. What condition is has_usable_password checking for?
start_time = timezone.now() - timedelta(days=DAYS_AGO_CONSTANT)
invalid_users = User.objects.filter(connection_last_unsubscribe__lte=start_time,
password__isnull=True).exclude(pk__in=user_ids_with_posts_list)
invalid_users.delete()

Looking for proper behavior

my models:
class Question(models.Model):
content = models.CharField(max_length=160)
class Answer(models.Model):
content = models.CharField(max_length=260)
question = models.ForeignKey(Question)
And if i want all answers related to particular question, but hiting database as little as possible, should i use select_related like that:
q = Question.objects.select_related(depth=1).get(id=id)
answers = q.answer_set.all()
or just:
q = Question.objects.get(id=id)
answers = q.answer_set.all()
?
For answering this type of question, consider installing the Django Debug Toolbar. It provides information on all DB queries performed to process a request, including the amount of time each query takes.
So install the toolbar in your project, and browse to a page on your site that performs the query. Click on the toolbar to see query information. Try it both ways to see which is better.