Adding security questions to my Django site - django

I need to ask the user for two security questions and their corresponding answers. The security questions will be provided by me, so it will be some kind of <select>. I created a model to store the user profile named UserProfile. It looks like:
class UserProfile(models.Model):
phone1 = models.CharField(help_text='Primary phone number')
phone2 = models.CharField(help_text='Secondary phone number', blank=True)
...
I could do something like:
SECURITY_QUESTIONS_CHOICES = (
('PN', 'What is your telephone number?'),
('BF', 'What is the full name of your best friend?'),
...
)
and add the following two fields to my model:
question1 = models.CharField(choices=SECURITY_QUESTIONS_CHOICES)
question2 = models.CharField(choices=SECURITY_QUESTIONS_CHOICES)
but I want to be able to modify the list of security questions, so I want it to be a model too.
My question is:
What is the best way of having two fields that point to the same model?
Having only one field (eg. questions) which is a ManyToMany relationship to SecurityQuestion, and restricting the number to 2 in the registration form?
Having two fields (question1 and question2) where each one is a ForeignKey to SecurityQuestion?

I would prefer create a separate model for all security questions. It gives you flexibility.
class SecurityQuestions(models.Model):
class Meta:
db_table = 'security_questions'
id = models.AutoField(primary_key=True)
question = models.CharField(max_length = 250, null=False)
class UserProfile(models.Model):
----
----
user_questions = models.ManyToManyField(SecurityQuestions, through='SecurityQuestionsInter')
class SecurityQuestionsInter(models.Model):
class Meta:
db_table = 'security_questions_inter'
profile = models.ForeignKey(Profile)
security_questions = models.ForeignKey(SecurityQuestions)
answer = models.CharField(max_length = 250, null=False)

Related

Is partial form a good practice in Django?

I'm new in Django and I try to find out if saving partial forms are a good practice or not. For example, I have Poll App and Candidate model with four fields: name, surname, targets andbiography. And I have a form where I have to fill all these fields. But if user only finished fill name, surname and targets, but even din't start filling biography field, how can I save his draft to user can finish it later and don't make any security mess?
models.py:
class Candidate(models.Model):
name = models.CharField(max_length=50)
surname = models.CharField(max_length=50)
biography = models.TextField()
targets = models.CharField(max_length=1000)
forms.py
class CandidateForm(ModelForm):
class Meta:
model = Candidate
fields = [
'name',
'surname',
'biography',
'targets',
]
widgets = {
'biography': forms.Textarea(attrs={'rows': 3})
}
I will be happy to see all ideas.
how can I save his draft to user can finish it later and don't make
any security mess?
You can either save the data to DB if you have designed the models to accept null or blank values, Or you can use Django sessions to temporarily store the form data until the form is completed...
In both case the security is not an issue since just like a DB access the django session data is also stored in a database and not in the browser... and so the end users cannot easily mess with the data...
check the following answer if you would like to know more...
Your problem is here :-
models.py:
class Candidate(models.Model):
name = models.CharField(max_length=50)
surname = models.CharField(max_length=50)
biography = models.TextField()
targets = models.CharField(max_length=1000)
If you put default='your default value':-
models.py:
class Candidate(models.Model):
name = models.CharField(max_length=50)
surname = models.CharField(max_length=50)
biography = models.TextField(default=' ')
targets = models.CharField(max_length=1000)
I think this is right what you need

Django ManyToMany Validation Constraint

I have a ManyToMany link, and a Foreign key which links three objects.
[A]>--<[B]>---[C]
A can belong to many of B, and vice versa. However, A can only belong to B objects with the same parent C.
I'm trying to do something in the clean() method of the model. I'm using Django Rest Framework and no ModelForms or anything like that. I haven't been able to figure it out yet
Simplified Sample Code
class Device(models.Model):
name = models.CharField(max_length=20)
projects = models.ManyToManyField(Project, 'devices')
details = models.CharField(max_length=200)
serial = models.CharField(max_length=20)
address models.GenericIPAddressField(default="0.0.0.0")
port = models.IntegerField(default=3000)
jumpers = models.IntegerField(default=0)
install_date = models.DateField(blank=True, null=True)
class Project(models.Model):
name = models.CharField(max_length=20)
description = models.CharField(max_length=250)
area = models.ForeignKey(Area)
class Area(models.Model):
name = models.CharField(max_length=20)
description = models.CharField(max_length=250)
owner = models.CharField(max_length=20) # microservice doesn't have owner group - field in JWT
Serializers
class AreaSerializer(serializers.ModelSerializer):
class Meta:
model = Area
fields = ('name', 'description', 'owner')
class ProjectSerializer(serializers.ModelSerializer):
class Meta:
model = Project
fields = ('id', 'name', 'description', 'area')
class DeviceSerializer(serializers.ModelSerializer):
class Meta:
model = Device
fields = ('id', 'name', 'projects', 'details', 'serial',
'address', 'port', 'jumpers', 'install_date')
I am not sure where and how do you want to validate your data. So I am just posting the method which can validate if a project can be linked to a device or not based on your specific check.
def validate_project(device, project):
projects = device.projects.all()
areas = set(projects.values_list('area', flat=True))
if len(areas) > 1:
raise serializers.ValidationError('projects are not valid')
return areas.pop() == project.area_id
EDIT:
You have to use a intermediate model for storing the relationship between device and project.
class Membership(models.Model):
device = models.ForeignKey(Device, on_delete=models.CASCADE)
project = models.ForeignKey(Project, on_delete=models.CASCADE)
area = models.ForeignKey(Area, on_delete=models.CASCADE)
use the above membership model to store the many to many relations.
On your device model use this field to define the many to many relation.
projects = models.ManyToManyField(Project, through='Membership')
checkout the docs
Now when you link a device and project you will have explicitly add the area id as well. Before adding now you can check if the project is valid or not based on the area associated.
(ignore the wonky field types, cba)
What it boils down to is: you need a table BC that stores relations between B and C. Table A would then select only from those relations through the intermediary m2m table ABC (or ditch ABC, couldn't figure out how to draw m2m with the online tool). I think I mixed up B and C in this picture, swap them around depending on whether B or C holds the ForeignKey.
Please correct if I'm wrong!

Is it possible to have a class as your model field in Django?

I am currently trying to create a health network website in Django.
The idea is that there will be a class called User inside my registration application. One of the states stored inside User is which hospital the user is registered into.
I created another Hospital within the registration app. I want to user that model Hospital as one of the model field for the hospital_used state. How do I do that? Below is a portion of my UML that illustrates the relationship
UML Diagram
Below is a portion of my UML that illustrates the relationship
png
Here is the code I have for it so far. The code where it is encapsulated with an asterisk is what I need help with.
class Hospital(models.Model):
hospital_Name = models.CharField(max_length=150)
def __str__(self):
return "Hospital Name: " + str(self.hospital_Name)
class User(models.Model):
PATIENT = 'Pat'
DOCTOR = 'Doc'
NURSE = 'Nurse'
ADMINISTRATOR = 'Admin'
user_type_choice = {
(PATIENT, 'Patient'),
(DOCTOR, 'Doctor'),
(NURSE, 'Nurse'),
(ADMINISTRATOR, 'Administrator'),
}
name = models.CharField(max_length=50)
dob = models.DateField(auto_now=False)
username = models.CharField(max_length=50)
*preferred_hospital = Hospital(models.CharField(max_length=50))*
patient_type = models.CharField(
max_length=5,
choices=user_type_choice,
)
Thank you StackOverflow Buddies
I would advise you to read this material on tutorials on how to create simple models.
What you want here is to use the ForeignKey method.
name = models.CharField(max_length=50)
dob = models.DateField(auto_now=False)
username = models.CharField(max_length=50)
preferred_hospital = models.ForeignKey(Hospital, on_delete = models.CASCADE)
patient_type = models.CharField(
max_length=5,
choices=user_type_choice,
)
You do not have to use on_delete = models.CASCADE but it is best that you handle what should happen when you delete an Hospital.
Know that you can also have OneToOne, ManyToOne, or ManyToMany fields, that are all described here.

Store List(s) in a database

My Users has phone contact LIST(s) - [3121234567,2121234567,6601234567]
Now, I want each user to be able to store as many LIST as possible. Each List must have a name(or description) attached to them under each USER account. Note: the number of LIST is dependent on Users needs. Example:
Students
[3121234567,2121234567,6601234567]
Club Member
[8101234567,8151234567,8171234567]
Now, how do I store it in a database.
Django User Model
class CustomUser(AbstractBaseUser):
username = models.CharField(max_length=254, unique=True)
first_name = models.CharField(max_length=24)
last_name = models.CharField(max_length=30)
phone = models.CharField(max_length=10)
email = models.EmailField(max_length=128)
street = models.CharField(max_length=128)
city = models.CharField(max_length=128)
state = models.CharField(max_length=2, choices=STATE_CHOICES, default=STATE)
zip_code = models.IntegerField(max_length=5, null=True, blank=True
USERNAME_FIELD = 'email'
REQUIRED_FIELD = ['username', 'first_name', 'last_name', 'phone', 'street', 'city', 'state']
objects = CustomUserManager()
Edit(Added):
I am not looking to create Student or ClubMember models. This name is use to identify the python phone contact list. PhoneAddress one can be labelled(named) as Student for one user but called "Conference Attendant" for another. Each user have different # of Lists.
PhoneAdress PhoneAdress2 PhoneAdress3
[3121234567,2121234567,6601234567] [4121234567,3121234567,6601234567] [7121234567,8121234567,9601234567]
Lemme guess, you're coming from a NoSQL background where the database is a document in a JSON form?
If so, I am sorry, in a Relational Database, used by Django in the likes of PostgreSQL or MySQL, they call something Foreign Keys, and that is your way of storing multiple "Lists" related to a particular field.
If you want many users to store as many lists as possible, you're looking at something like this, roughly speaking:
class myUserModel(models.Model):
# your arbitrary fields here
# then you do something like this:
class Student(models.Model):
user = models.ForeignKey(User)
class clubMember(models.Model):
user = models.ForeignKey(User)
With the above setup, you can add as many Student objects associated to the myUserModel class, so as the clubMember
However, if you wish to use PostgreSQL specifically, as your backend (perhaps as perpetual storage backend), you might find some sense in using Django's support for the ArrayField
And ooh, you might need to extend the Django User Model to add any extra fields easily, unless you're willing to go down the road of a custom User Model.
More info:
Django ForeignKey
This SO answer on 'OneToManyFields', similar to adding multiple items to a single field.
I hope the above helps
Create some models:
class Club(models.Model):
name = models.CharField(max_length=256,blank=True,null=True)
date_open = models.DateField()
class Institution(models.Model):
name = models.CharField(max_length=256,blank=True,null=True)
address = models.CharField(max_length=256,blank=True,null=True)
type = models.CharField(max_length=256,blank=True,null=True) #university, college
Rather than using
class CustomUser(AbstractBaseUser):
username = models.CharField(max_length=254, unique=True)
first_name = models.CharField(max_length=24)
last_name = models.CharField(max_length=30)
use composition in the form of OneOnOneField
class UserProfile(models.Model):
user = models.OneOnOneField(User,blank=True,null=True)
club_member = models.ManyToManyField(Club,blank=True, null=True)
institutions = models.ManyToManyField(Institution,blank=True, null=True) # student in
Once you have this, you will be able to get and add as many institutions and clubs to the lists:
user = User.objects.get(id=user_id)
club = Club.objects.get(id=club_id)
institution = Institution.objects.get(id=institution_id)
user.profile.clubs.add(club)
user.profile.institutions.add(institution)
So to verify if the user is a member of a club
club = user.proile.clubs.get(id=club_id)
and to verify the user is a student in an institution use
institution = user.profile.institutions.get(id=institution_id)

Django Multiple User Profiles with Class based views (Best Practices)

I have a website where there are two kinds of users (say) : students and tutors.
Both types have common login functionality, age, gender etc but have distinct attributes such as report cards for students and degree certificates for tutors.
I read this question : Django - Multiple User Profiles and setup my profiles as shown below:
class UserProfile(models.Model):
user = models.OneToOneField(User, primary_key=True, related_name='profile')
mobile = models.CharField(max_length=10, blank=False, null=True)
picture = models.ImageField(
upload_to='images/', default='images/newuser.png')
age = models.IntegerField(null=True)
slug = models.SlugField()
...
And two other models that link to the above. Eg:
class StudentProfile(models.Model):
profile = models.ForeignKey(UserProfile, related_name="user_profile")
#more custom attributes
class TutorProfile(models.Model):
profile = models.ForeignKey(UserProfile, related_name="doctor_profile")
#more custom attributes
Now my questions:
1) SlugField is defined on the UserProfile attribute but will ideally use the User.username field. This means a join between these two tables will happen each time. Is this to be expected?
2) Assuming I am using class based views, editing/viewing the profile will depend on the UserProfile in question. But I want the user to be able to edit/view all his details on the same page. Thus, I will have to fetch TutorProfile / StudentProfile too and add custom logic to ensure updates happen to them too.
It seems to me that there should be a proper way of handling these situations (Since a lot of websites have similar requirements). What are the best practices to be followed in such a situation?
While searching for answers, I came across a solution which I think might suit my needs (posting here to welcome critique and help out others who might be looking for answers).
Taken from Django Design patterns and Best Practices
class UserProfile(models.Model):
user = models.OneToOneField(User, primary_key=True, related_name='profile')
mobile = models.CharField(max_length=10, blank=False, null=True)
picture = models.ImageField(
upload_to='images/', default='images/newuser.png')
age = models.IntegerField(null=True)
gender = models.IntegerField(null=True)
user_type = models.CharField(max_length=20, choices=UserTypes.CHOICES)
slg = models.SlugField()
class Meta(object):
abstract = True
class StudentProfile(models.Model):
report_card = models.FileField(upload_to="/temp")
house = models.CharField()
class Meta(object):
abstract = True
class TutorProfile(models.Model):
performance = models.IntegerField(default=0)
salary = models.IntegerField(default=0)
class Meta(object):
abstract = True
One base abstract class and two specific classes which cover the various user profiles. Keeping them separate like this makes it easy for us to reason about the various fields present in each user type.
Finally,
class Profile(UserProfile, StudentProfile, TutorProfile):
pass
This is the model used as the settings.AUTH_USER_MODEL.
Overall, the advantages I see:
Single DB call on user edit/view page.
Easier to think about overall.
Disadvantage : Lots of wasted space.
Anyone has any better suggestions?