Django ModelForm - Using ForeignKey for Choices - django

I'm attempting to build out a rather large "Patient Onboarding" form using ModelForms.
I'm having trouble getting the choices within the foreign keys to appear in the admin area or to the rendered form without manually adding them to the Postgres database.
There has got to be a more efficient way to be doing this...thanks in advance!
#models.py
from django.db import models
from django.forms import ModelForm
from django import forms
class Patient(models.Model):
first_name = models.CharField(max_length=30, verbose_name='First Name', blank=False)
middle_name = models.CharField(max_length=30, verbose_name='Middle Name', blank=False)
last_name = models.CharField(max_length=30, verbose_name='Last Name', blank=False)
gender = models.ForeignKey('GenderChoices', on_delete=models.CASCADE, verbose_name='Gender', blank=False)
date_of_birth = models.DateField(verbose_name='Date of Birth', blank=False)
medications = models.ForeignKey('MedicationsYesNo', on_delete=models.CASCADE, verbose_name='Do you currently take any medications?', blank=False)
class MedicationsYesNo(models.Model):
medications_yes_no = models.CharField(
max_length=100,
choices = [
('Yes', 'Yes'),
('No', 'No')
]
)
def __str__(self):
return self.medications_yes_no
class OnboardingForm(ModelForm):
class Meta:
model = Patient
fields = '__all__'

Related

Hi I'm having trouble customizing authentication in Django

I am a newbie and I am designing Django authentication software
My problem is that I have to check four separate levels for which there are predefined codes in the permission check.
A model class named province and a model class named city and a model named Student
My review model is such that I should be able to give a user the membership of the central office or the membership of a province or the membership of a city in a province.
The user can only be for one of these situations
My models is like this
class Province(models.Model):
province_id = models.IntegerField(primary_key=True, serialize=True, verbose_name='ID')
province_title = models.CharField(max_length=30, verbose_name=_('Province'))
class Meta:
ordering = ['province_id']
def __str__(self):
return self.province_title
class Center(models.Model):
id = models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')
center_title = models.CharField(max_length=150, verbose_name=_('Name of the training center'), null=True)
center_title_id = models.CharField(max_length=64, verbose_name=_('Code of the training center'), null=True)
province = models.ForeignKey(Province, on_delete=models.CASCADE, verbose_name=_('Province'))
class Meta:
verbose_name = _("center")
verbose_name_plural = _("centers")
def __str__(self):
return self.center_title`
class CulturalUser(AbstractUser):
pass
class UserPositions(models.Model):
class Position(models.TextChoices):
UNIVERSITY_STUDENT = '1', _('University student')
TRAINING_CENTER = '2', _('Training center')
PROVINCE = '3', _('Province')
CENTRAL_OFFICE = '4', _('Central office')
user = models.ForeignKey(CulturalUser, on_delete=models.CASCADE, verbose_name=_('User'))
position = models.CharField(max_length=2, verbose_name=_('Access level'), choices=Position.choices,
default=Position.UNIVERSITY_STUDENT)
province = models.ForeignKey(Province, on_delete=models.SET_NULL, blank=True, null=True)
center = models.ForeignKey(Center, on_delete=models.SET_NULL, blank=True, null=True)
def __str__(self):
return self.position
please direct me
According to the search I did, I could not find the right sources in my question mode
You can either extend or substitute an user model. Quotting the documentation:
If you’re starting a new project, it’s highly recommended to set up a custom user model, even if the default User model is sufficient for you. This model behaves identically to the default user model, but you’ll be able to customize it in the future if the need arises:
A full example
Django's user models counts with permissions and authorization and groups out of the box. So, instead of choices fields you would have four groups, for which you would handle access with permissions.
University student
Training center
Province
Central office
Here is one version of your model:
from django.utils.translation import gettext_lazy as _
from django.db import models
from django.contrib.auth.models import AbstractUser
class Province(models.Model):
name = models.CharField(
max_length=30,
verbose_name=_('Province')
)
class Meta:
ordering = ['id']
def __str__(self):
return self.title
class Center(models.Model):
name = models.CharField(
max_length=150,
verbose_name=_('Name of the training center'),
null=True,
)
code = models.CharField(
max_length=64,
verbose_name=_('Code of the training center'),
null=True,
)
province = models.ForeignKey(
Province,
on_delete=models.CASCADE,
verbose_name=_('Province')
)
class Meta:
verbose_name = _("center")
verbose_name_plural = _("centers")
def __str__(self):
return self.name
class User(AbstractUser):
province = models.ForeignKey(
Province,
on_delete=models.SET_NULL,
blank=True, null=True,
)
center = models.ForeignKey(
Center,
on_delete=models.SET_NULL,
blank=True, null=True,
)
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
Note that I used AbstractUser, like you did, but you can do an even deeper customization with AbstractBaseUser, as shown in the example I linked above.

Recording user activity in django?

I have a project in which some user can perform CRUD activities. I want to record who did what and when. Currently, I am thinking of making a model
class UserAction(models.Model):
user_id = models.CharField(max_length=100)
action_flag = models.CharField(max_length=100)
class_id = models.CharField(max_length=100)
action_taken_at = models.DateTimeField(default=datetime.now())
and making a function that fills my UserAction table. Is there any better way to do this?
app/models.py:
from django.db import models
from django.contrib.auth.models import User
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes.fields import GenericForeignKey
class Action(models.Model):
sender = models.ForeignKey(User,related_name='user',on_delete=models.CASCADE)
verb = models.CharField(max_length=255)
target_ct = models.ForeignKey(ContentType, blank=True, null=True,
related_name='target_obj', on_delete=models.CASCADE)
target_id = models.PositiveIntegerField(null=True, blank=True)
target = GenericForeignKey('target_ct', 'target_id')
created = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ('-created',)
def __str__(self):
return self.pk
app/admin.py
from .models import Action
admin.site.register(Action)
How you can use it ?
you can now import this models(Action) inside any of yours views.py.
Example if you have a post and a user likes it.you can just write
Action.objects.create(sender=request.user,verb="likes this post",target=post)
and now when you look at your admin you will see that tartget_id=post.pk
Here I assume that a user is authenticated and you can change it for your own.Happy coding!!!
You can do it by creating a model in
Models.py
class Auditable(models.Model):
ip = models.GenericIPAddressField(null=True)
user_agent = models.CharField(max_length=255, blank=True)
remote_host = models.CharField(max_length=255, blank=True)
created_at = models.DateTimeField(auto_now_add=True, blank=True, null=True)
created_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.DO_NOTHING, related_name="%(app_label)s_%(class)s_created_by", null=True, blank=True) # this is for web user
modified_at = models.DateTimeField(auto_now=True, blank=True, null=True)
modified_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.DO_NOTHING, related_name="%(app_label)s_%(class)s_modified_by", null=True, blank=True) # this is for web user
class Meta:
abstract = True
def get_fields(self):
list_fields = ['ip', 'user_agent',
'remote_host', 'created_by', 'modified_by']
return [(field.verbose_name, field._get_val_from_obj(self)) for field in self.__class__._meta.fields if field.name not in list_fields and not
(field.get_internal_type() == "DateTimeField" and
(field.auto_now is True or field.auto_now_add is True)) and
field.concrete and (not field.is_relation or field.one_to_one or
(field.many_to_one and field.related_model))]
You can give any class name (i have given auditable). So all you have to do is pass this class (auditable) in your every model instead of models.Model
For Eg:
class Student(Auditable):
By doing this it will add all the auditable fields records in every table you have created.
Hope you may get your answer by doing this.

Separate Django model field to another fields

I have a field called fullname that has data something like this:
first_name:Gholi;last_name:Sezavar Poor Asl Esfahani
I want to separate it as two separate fields name first_name & last_name.
My models.py is:
from django.db import models
class Person(models.Model):
fullname = models.CharField(max_length=250, null=True)
information = models.CharField(max_length=350, null=True)
first_name = models.CharField(max_length=30, null=True)
last_name = models.CharField(max_length=50, null=True)
id_code = models.CharField(max_length=10, null=True)
born_in = models.CharField(max_length=30, null=True)
birth_year = models.PositiveIntegerField(null=True)
and I want to make custom migration for it and using annotate method.
How can I do this ???
EDIT:
I want to do this in custom migration and use annotate method like I have done it right now, but now with my code it just stores firstname and last name in first_name field :
def organize_person_schema(apps, schema_editor):
# Person = apps.get_model('people', 'Person')
Person.objects.annotate(
first_name_change=Replace(
F('fullname'), text=Value("first_name:"),
replacement=Value(''),
output_field=CharField()
)
).update(first_name=F('first_name_change'))
Person.objects.annotate(
last_name_change=Replace(
F('first_name'), text=Value(";last_name:"),
replacement=Value(' '),
output_field=CharField()
)
).update(first_name=F('last_name_change'))
Person.objects.annotate(
last_name_last=Concat(
F('first_name'), Value(""),
output_field=CharField()
)
).update(last_name=F('last_name_last'))
You can have a custom save method to do some update:
from django.db import models
class Person(models.Model):
fullname = models.CharField(max_length=250, null=True)
information = models.CharField(max_length=350, null=True)
first_name = models.CharField(max_length=30, null=True)
last_name = models.CharField(max_length=50, null=True)
id_code = models.CharField(max_length=10, null=True)
born_in = models.CharField(max_length=30, null=True)
birth_year = models.PositiveIntegerField(null=True)
def save(self, *args, **kwargs):
if not self.pk:
# logic to separate full name into first and last
# Split by (";")
first_name, last_name = self.fullname.split(";")
self.first_name = first_name.split(":")[1]
self.last_name = last_name.split(":")[1]
super(Person, self).save(*args, **kwargs)

Django one parent and two children relationship

I am new in Django and Django-Rest-framework. I am following one Youtube Tutorial. He used static Django Template but I want to use React as my frontend. So I have create multiple api endpoints. In this particular Youtube episode I am stuck to display what kind of products specific customer bought. Short summary of my project is: I have four models: order, customer, product and tags(Product and tags have many to many relationships). In the order model I have two foreign key one is product and another one is customer. This is my order models [Looks like]. I don't know how to query and display what kind of products specific customer(by using id) bought.
This is my models
from __future__ import unicode_literals
from django.db import models
class Tag(models.Model):
name= models.CharField(max_length=200, null=True)
def __str__(self):
return self.name
class Product(models.Model):
CATEGORY=(
('Indoor', 'Indoor'),
('Outdoor', 'Outdoor'),
)
name= models.CharField(max_length=200, null=True)
price= models.FloatField(null=True)
category=models.CharField(max_length=200,null=True, choices=CATEGORY)
description= models.CharField(max_length=200,null=True, blank= True)
date_created=models.DateTimeField(auto_now_add=True, null=True)
tags= models.ManyToManyField(Tag)
def __str__(self):
return self.name
class Customer(models.Model):
name = models.CharField(max_length=200, null= True)
email = models.CharField(max_length=20, null=True)
phone = models.CharField(max_length=20, null=True)
date_created= models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.name
class Order(models.Model):
STATUS =(
('Pending', 'Pending'),
('Out of delivery', 'Out of delivery'),
('Delivered', 'Delivered'),
)
status= models.CharField(max_length=200, null=True,choices= STATUS)
date_created=models.DateTimeField(auto_now_add=True, null=True)
customer= models.ForeignKey(Customer, null= True, on_delete= models.SET_NULL)
product= models.ForeignKey(Product, null= True, on_delete= models.SET_NULL)
This is serializes
from rest_framework import serializers
from .models import *
class TagSerializer(serializers.ModelSerializer):
class Meta:
model = Tag
fields = ["name"]
class ProductSerializer(serializers.ModelSerializer):
tags = TagSerializer(many=True)
class Meta:
model = Product
fields = '__all__'
class CustomerSerializer(serializers.ModelSerializer):
products: ProductSerializer(many=True)
class Meta:
model = Customer
fields = '__all__'
class OrderSerializer(serializers.ModelSerializer):
customer = CustomerSerializer()
product = ProductSerializer()
class Meta:
model = Order
fields = '__all__'
class CustomerSerializer(serializers.ModelSerializer):
products: ProductSerializer(many=True)
orders: OrderSerializer(many=True)
class Meta:
model = Customer
fields = '__all__'

How to save two forms in one view with a foreignkey relationship?

I have the following models with foreignkey relation.
class UserProfile(models.Model):
profile_id = models.CharField(
('Profile id'), max_length=30, default='', blank=True)
first_name = models.CharField(
('first name'), max_length=30, default='', blank=True)
last_name = models.CharField(
('last name'), default='', max_length=30, blank=True)
Profile Image model has a foreignkey relation to UserProfile model:
class UserProfileImage(models.Model):
userprofile = models.ForeignKey(UserProfile)
image = models.ImageField(upload_to='profile_pic/images',blank=True,null=True)
def __unicode__(self):
return self.userprofile.profile_id
I want to save both forms in one view and for edit also it should pass both form instances.How will I save both forms in one view?