How do I make this serializer display correctly? - django

Django is giving me this error. The solution I've tried does not seem to work. It is asking me to make this an instance of Medication...Am I not already doing that? I'm trying to have two serializers cat and medication under the one careLogSerializer. Is that even possible? How can I best solve this error?
builtins.ValueError
ValueError: Cannot assign "OrderedDict([('name', 'carelog3'), ('duration', 'short'), ('frequency', '4')])": "CareLog.medication" must be a "Medication" instance.
Here is my serializer....
class CareLogSerializer(serializers.HyperlinkedModelSerializer):
cat = CatSerializer()
medication = MedicationSerializer()
# cat = CatSerializer(read_only=True) this allows put BUT TURNS OFF POST
class Meta:
model = CareLog
fields = (
'cat',
'slug',
'foster_manager',
'weight_unit_measure',
'weight_before_food',
'food_unit_measure',
'amount_of_food_taken',
'food_type',
'weight_after_food',
'stimulated',
'medication',
'medication_dosage_given',
'medication_dosage_unit',
'notes',
'created',
'photo',
)
extra_kwargs = {
'foster_manager': {
'read_only': True,
'required': False,
'lookup_field': 'id',
},
'medication': {
'read_only': True,
'required': False,
'lookup_field': 'slug',
},
'cat': {
'read_only': True,
'required': False,
'lookup_field': 'slug',
},
}
#staticmethod
def create(validated_data):
cat_data = validated_data.pop('cat')
cat_obj = Cat.objects.get(**cat_data)
return CareLog.objects.create(cat=cat_obj, **validated_data)
#staticmethod
def update(instance, validated_data):
instance.weight_unit_measure = validated_data['weight_unit_measure']
instance.weight_before_food = validated_data['weight_before_food']
instance.food_unit_measure = validated_data['food_unit_measure']
instance.amount_of_food_taken = validated_data['amount_of_food_taken']
instance.food_type = validated_data['food_type']
instance.weight_after_food = validated_data['weight_after_food']
instance.stimulated = validated_data['stimulated']
instance.stimulation_type = validated_data['stimulation_type']
instance.notes = validated_data['notes']
instance.save()
Here is my model
class CareLog(models.Model):
WEIGHT_MEASURE_CHOICES = (
('OZ', '(oz) Ounces'),
('LB', '(lb) Pounds'),
('G', '(G) Grams')
)
OUNCES = 'OZ'
POUNDS = 'LB'
GRAMS = 'G'
VOLUME_MEASURE_CHOICES = (
('ML', '(ml) Milliliters'),
('CC', '(cc) Cubic Centimeters'),
('OZ', '(oz) Ounces'),
('G', '(G) Grams')
)
MILLILITERS = 'ML'
CUBIC_CENTIMETERS = 'CC'
FOOD_TYPE_CHOICES = (
('MN', 'Mom (Nursing)'),
('BO', 'Bottle'),
('BS', 'Bottle / Syringe'),
('SG', 'Syringe Gruel'),
('GG', 'Syringe Gruel / Gruel'),
('G', 'Gruel')
)
BOTTLE = 'BO'
BOTTLE_SYRINGE = 'BS'
SYRINGE_GRUEL = 'SG'
SYRINGE_GRUEL_GRUEL = 'GG'
GRUEL = 'G'
STIMULATION_CHOICES = (
('UR', 'Urine'),
('FE', 'Feces'),
('UF', 'Urine / Feces'),
)
URINE = 'UR'
FECES = 'FE'
URINE_FECES = 'UF'
cat = models.ForeignKey(Cat)
slug = AutoSlugField(max_length=255, unique=True, blank=True, null=True)
foster_manager = models.ForeignKey(User, on_delete=models.CASCADE, blank=True, null=True)
weight_unit_measure = models.CharField(max_length=2, choices=WEIGHT_MEASURE_CHOICES, default=GRAMS)
weight_before_food = models.IntegerField(blank=True, null=True)
food_unit_measure = models.CharField(max_length=2, choices=WEIGHT_MEASURE_CHOICES, default=GRAMS)
amount_of_food_taken = models.IntegerField(blank=True, null=True)
food_type = models.CharField(max_length=2, choices=FOOD_TYPE_CHOICES, blank=True, null=True)
weight_after_food = models.IntegerField(blank=True, null=True)
stimulated = models.BooleanField(default=False)
stimulation_type = models.CharField(max_length=2, choices=STIMULATION_CHOICES, blank=True, null=True)
medication = models.ForeignKey(Medication, blank=True, null=True)
medication_dosage_given = models.FloatField(blank=True, null=True)
medication_dosage_unit = models.CharField(max_length=2, choices=VOLUME_MEASURE_CHOICES, blank=True, null=True,
help_text="If left blank this will default to "
"the default unit for the medication.")
notes = models.TextField(blank=True, null=True)
created = models.DateTimeField(auto_now_add=True)
photo = models.FileField(upload_to="kitty_photos", blank=True, null=True)
def save(self, *args, **kwargs):
# Update Cat's weight if 'Weight After Food' is updated
if self.weight_after_food:
self.cat.weight = self.weight_after_food
self.cat.save()
# Get all previous cat feedings
feedings = CareLog.objects.filter(cat=self.cat).order_by('-id')
if feedings:
# if the list of cat feedings contains the current, get rid of current from the list
if feedings[0] == self:
feedings = feedings[1:]
# TODO You broke it you fix it:
# If the feeding is a weight loss log it as the first/second/third
if self.weight_after_food < feedings[0].weight_after_food:
if self.cat.first_weight_loss:
self.cat.second_weight_loss = True
elif self.cat.second_weight_loss:
self.cat.third_weight_loss = True
elif self.cat.third_weight_loss:
self.cat.many_weight_losses = True
elif not self.cat.first_weight_loss:
self.cat.first_weight_loss = True
# Save Cat Object
self.cat.save()
if self.medication and not self.medication_dosage_unit:
self.medication_dosage_unit = self.medication.dosage_unit
super(CareLog, self).save(*args, **kwargs)
def __str__(self):
return "{cat}: {timestamp}".format(cat=self.cat.name, timestamp=self.created)

In your create method you need to do for medication same operation as for cat. Create object first and assign it to CareLog:
#staticmethod
def create(validated_data):
cat_data = validated_data.pop('cat')
cat_obj = Cat.objects.get(**cat_data)
med_data = validated_data.pop('medication')
med_obj = Medication.objects.create(**med_data)
return CareLog.objects.create(cat=cat_obj, medication=med_obj, **validated_data)
Otherwise Django trying to set as foreignkey's value dict object and raise the error.

Related

association user with forms

I'm making something like this: admin creates form manually, and user is automatically created with this form.
But I need to add association that form to a new automatically created user, that's where I'm stuck. How can I make user auto registration to associate that form
I need this because I want to then to show 'filtered, created' form by user.
Views.py
def create_driver_view(request):
if request.method == "POST":
add_driver = DriverForm(request.POST)
add_driver_files = request.FILES.getlist("file")
if add_driver.is_valid():
email = request.POST['email']
usern = 'test'
passw = 'test'
user = User.objects.create_user(email = email, username = usern, password = passw)
user.save()
f = add_driver.save(commit=False)
f.user = request.user
f.save()
for i in add_driver_files:
DriversFiles.objects.create(driver_files=f, file=i)
return redirect('drivers:list_driver')
else:
print(add_driver.errors)
else:
add_driver = DriverForm()
add_driver_files = DriverFormUpload()
return render(request, "drivers/add.html", {"add_driver": add_driver, "add_driver_files": add_driver_files})
Forms.py
class DriverForm(forms.ModelForm):
class Meta:
model = Drivers
fields = [
'full_name',
'phone_number',
'email',
'address',
'country',
'state',
'city',
'zip',
'birth_date',
'license_no',
'license_exp_date',
'last_medical',
'next_medical',
'last_drug_test',
'next_drug_test',
'status',
]
class DriverFormUpload(forms.ModelForm):
class Meta:
model = DriversFiles
fields = [
'file',
]
widget = {
'file': forms.ClearableFileInput(attrs={'multiple': True}),
}
Models.py
STATUS = ((0, 'Inactive'), (1, 'Active'))
class Drivers(models.Model):
full_name = models.CharField(max_length=50, default=None)
phone_number = models.CharField(max_length=50, default=None)
email = models.EmailField(unique=True,max_length=255, default=None)
address = models.CharField(max_length=70, default=None)
country = models.CharField(max_length=50, default=None)
state = models.CharField(max_length=50, default=None)
city = models.CharField(max_length=50, default=None)
zip = models.CharField(max_length=50, default=None)
birth_date = models.DateField(default=None)
license_no = models.IntegerField(default=None)
license_exp_date = models.DateField(default=None)
last_medical = models.DateField(default='', blank=True, null=True)
next_medical = models.DateField(default='', blank=True, null=True)
last_drug_test = models.DateField(default='', blank=True, null=True)
next_drug_test = models.DateField(default='', blank=True, null=True)
date_created = models.DateTimeField(auto_now_add=True)
status = models.IntegerField(choices=STATUS, default=1)
class DriversFiles(models.Model):
file = models.FileField(upload_to="media/", blank=True, null=True)
driver_files = models.ForeignKey('Drivers', on_delete=models.CASCADE, default=None, null=True)

Django Forcing BigAutoField even though Default is set to AutoField

so I upgraded from django 3.1 to 3.2 and on two of my models when I make migrations it keeps forcing me to change the auto id to BigAutoField even though I have (and had) DEFAULT_AUTO_FIELD = 'django.db.models.AutoField' in my settings file before I updated.
operations = [
migrations.AlterField(
model_name='device',
name='id',
field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
)
What is strange is that it is only affecting a couple models, but the rest are fine and they all use AutoField as well.
I am not against using BigAutoField but the migration fails because of foreignkey constraints.
I have deleted the migrations in question and also scrubbed them from the applied migrations table in the database. How can I stop Django from forcing this migration? I am at a loss right now.
Here is my Device Model. As you can see I have not specifically set the primary key, which I have not done on any other model either and those are fine.
from django.db import models
from company.models import Company
from django.db.models.signals import pre_save, post_save
from main.models import uuid_pre_save_generator
from django.conf import settings
from asgiref.sync import async_to_sync
from channels.layers import get_channel_layer
import json
from django.urls import reverse
from django.utils.html import escape
from django.core.validators import RegexValidator, FileExtensionValidator
class UploadedImage(models.Model):
uuid = models.CharField(max_length=7, blank=True, unique=True, verbose_name='Image ID')
image = models.ImageField(null=True, blank=True, upload_to="images/",
validators=[FileExtensionValidator(['jpg', 'png', 'jpeg'], 'Only .jpg files allowed')])
objects = models.Manager()
class Meta:
verbose_name = "Uploaded Image"
verbose_name_plural = "Uploaded Images"
def __str__(self):
return self.uuid
pre_save.connect(uuid_pre_save_generator, sender=UploadedImage)
def update_device_theme(sender, instance, *args, **kwargs):
related_devices = instance.devices.all()
if related_devices:
for d in related_devices:
d.save()
def alert_device_update(sender, instance, *args, **kwargs):
device = Device.objects.get(uuid=instance.uuid)
channel_layer = get_channel_layer()
group_name = 'connect_{}'.format(instance.uuid)
data = json.dumps({
'message': {
'type': 'device_update',
'text': '',
'data': {
'device': device.connect,
},
'sender': {
'type': 'server',
'uuid': '',
'first_name': '',
'last_name': '',
'company': '',
'initial': '',
'display_name': 'Server',
},
},
})
async_to_sync(channel_layer.group_send)(
group_name,
{
'type': 'chatroom.message',
'text': data
}
)
class DeviceDisplayTheme(models.Model):
uuid = models.CharField(max_length=7, blank=True, unique=True, verbose_name='Theme ID')
name = models.CharField(max_length=30, blank=False, null=False, verbose_name='Theme Name')
show_header = models.BooleanField(default=True, verbose_name='Show Header')
show_footer = models.BooleanField(default=True, verbose_name='Show Footer')
header_bg_color = models.CharField(max_length=30, blank=False, null=False,
verbose_name='Header Background Color',
default='rgba(255,255,255,.1)',
validators=[
RegexValidator(
regex=r"^^rgba[(](?:\s*0*(?:\d\d?(?:\.\d+)?(?:\s*%)?|"
r"\.\d+\s*%|100(?:\.0*)?\s*%|(?:1\d\d|2[0-4]\d|"
r"25[0-5])(?:\.\d+)?)\s*,){3}\s*0*(?:\.\d+|1(?:\.0*)?)\s*[)]$",
message='The header background color you have chosen is not formatted'
' correctly',
),
])
badge_bg_color = models.CharField(max_length=30, blank=False, null=False,
verbose_name='Device ID Badge Background Color',
default='rgba(255,255,255,.2)',
validators=[
RegexValidator(
regex=r"^^rgba[(](?:\s*0*(?:\d\d?(?:\.\d+)?(?:\s*%)?|"
r"\.\d+\s*%|100(?:\.0*)?\s*%|(?:1\d\d|2[0-4]\d|"
r"25[0-5])(?:\.\d+)?)\s*,){3}\s*0*(?:\.\d+|1(?:\.0*)?)\s*[)]$",
message='The badge background color you have chosen is not formatted'
' correctly',
),
])
bg_color = models.CharField(max_length=30, blank=False, null=False,
verbose_name='Background Color',
default='rgba(35,35,35,1)',
validators=[
RegexValidator(
regex=r"^^rgba[(](?:\s*0*(?:\d\d?(?:\.\d+)?(?:\s*%)?|"
r"\.\d+\s*%|100(?:\.0*)?\s*%|(?:1\d\d|2[0-4]\d|"
r"25[0-5])(?:\.\d+)?)\s*,){3}\s*0*(?:\.\d+|1(?:\.0*)?)\s*[)]$",
message='The background color you have chosen is not formatted correctly',
),
])
font_color = models.CharField(max_length=30, blank=False, null=False,
verbose_name='Font Color',
default='rgba(255,255,255,1)',
validators=[
RegexValidator(
regex=r"^^rgba[(](?:\s*0*(?:\d\d?(?:\.\d+)?(?:\s*%)?|"
r"\.\d+\s*%|100(?:\.0*)?\s*%|(?:1\d\d|2[0-4]\d|"
r"25[0-5])(?:\.\d+)?)\s*,){3}\s*0*(?:\.\d+|1(?:\.0*)?)\s*[)]$",
message='The font color you have chosen is not formatted correctly',
),
])
idle_text = models.CharField(max_length=50, blank=True, null=True,
verbose_name="Idle Text",
default='Press Help Button In Case of Emergency')
help_requested_text = models.CharField(max_length=50, blank=True, null=True,
verbose_name="Help Requested Text",
default='Emergency Help Requested')
active_text = models.CharField(max_length=50, blank=True, null=True,
verbose_name="Active Call Text",
default='Emergency Call Accepted')
response_prompt_text = models.CharField(max_length=50, blank=True, null=True,
verbose_name="Response Prompt Text",
default='Press Yes/No Buttons to Respond')
company = models.ForeignKey(Company, related_name='themes', verbose_name='Company',
blank=True, null=True, on_delete=models.CASCADE)
date_updated = models.DateTimeField(auto_now=True)
source_date_updated = models.DateTimeField(blank=True, null=True)
source_uuid = models.CharField(max_length=7, blank=True, null=True, verbose_name='Source ID')
objects = models.Manager()
class Meta:
verbose_name = "Device Display Theme"
verbose_name_plural = "Device Display Themes"
def __str__(self):
return self.name
#property
def settings(self):
idle_text = '' if not self.idle_text else self.idle_text
help_requested_text = '' if not self.help_requested_text else self.help_requested_text
active_text = '' if not self.active_text else self.active_text
response_prompt_text = '' if not self.response_prompt_text else self.response_prompt_text
return {
'pk': self.pk,
'name': escape(self.name),
'show_header': self.show_header,
'show_footer': self.show_footer,
'header_bg_color': self.header_bg_color,
'bg_color': self.bg_color,
'badge_bg_color': self.badge_bg_color,
'font_color': self.font_color,
'idle_text': escape(idle_text),
'help_requested_text': escape(help_requested_text),
'active_text': escape(active_text),
'response_prompt_text': escape(response_prompt_text),
}
#property
def settings_json(self):
return json.dumps(self.settings)
pre_save.connect(uuid_pre_save_generator, sender=DeviceDisplayTheme)
post_save.connect(update_device_theme, sender=DeviceDisplayTheme)
class Device(models.Model):
UUID_CREATED = 0
PROGRAMMED = 1
ASSIGNED = 2
lifecycle_stages = [
(UUID_CREATED, 'Unique ID Created'),
(PROGRAMMED, 'Memory Card Programmed'),
(ASSIGNED, 'Owner Assigned'),
]
statuses = [
('idle', 'Idle'),
('requested', 'Incoming Call Requested'),
('active', 'Live Call'),
]
uuid = models.CharField(max_length=6, blank=True, unique=True, verbose_name='Device ID')
# Call Status [ Idle, Requested, Active ]
state = models.CharField(max_length=10, choices=statuses, blank=False, default='idle', verbose_name="Call Status")
active = models.BooleanField(default=False, verbose_name='Active')
self_monitored = models.BooleanField(default=False, verbose_name='Self Monitored')
# Display Theme
theme = models.ForeignKey(DeviceDisplayTheme, related_name='devices', verbose_name='Display Theme',
blank=False, null=False, default=1, on_delete=models.SET_DEFAULT)
# Programming & Assignment
initialized = models.BooleanField(default=False, verbose_name='Initialized')
lifecycle = models.IntegerField(choices=lifecycle_stages, default=0, verbose_name="Lifecycle Stage")
software_version = models.CharField(max_length=12, blank=True, null=True, verbose_name='Software Version')
model_number = models.CharField(max_length=12, blank=True, null=True, verbose_name='Model Number')
activation_code = models.CharField(max_length=5, blank=True, null=True, verbose_name='Activation Code')
# Relationships
owner = models.ForeignKey(Company, related_name='devices', verbose_name='Device Owner',
blank=True, null=True, on_delete=models.SET_NULL)
callcenter = models.ForeignKey(Company, related_name='monitored_devices', verbose_name='Call Center',
on_delete=models.CASCADE, blank=True, null=True)
# Location & Address Details
location = models.CharField(max_length=255, blank=True, verbose_name='Device Identifier')
address = models.CharField(max_length=255, verbose_name="Street Address", blank=True)
address2 = models.CharField(max_length=255, verbose_name="Apartment, Unit, Suite, or Floor", blank=True)
address_locality = models.CharField(max_length=255, verbose_name="City/Town", blank=True)
address_state = models.CharField(max_length=255, verbose_name="State", blank=True)
address_postcode = models.CharField(max_length=55, verbose_name="Zip Code", blank=True)
address_country = models.CharField(max_length=55, verbose_name="Country", blank=True)
# Call-in Phone Number
phone_number = models.CharField(max_length=14, blank=True, null=True, verbose_name="Call-in Phone Number",
validators=[
RegexValidator(
regex=r"^\(\d{3}\)\s\d{3}-\d{4}$",
message='Phone number format is not valid, try (000) 000-0000',
),
])
# Timestamps
date_created = models.DateTimeField(auto_now_add=True)
date_updated = models.DateTimeField(auto_now=True)
date_last_online = models.DateTimeField(blank=True, null=True)
objects = models.Manager()
class Meta:
verbose_name = "Device"
verbose_name_plural = "Devices"
ordering = ['uuid']
def __str__(self):
return self.uuid
def set_idle_state(self):
self.state = 'idle'
def set_requested_state(self):
self.state = 'requested'
def set_active_state(self):
self.state = 'active'
#property
def full_address(self):
def check_address_parts(value):
if value == '' or value == ',':
return False
else:
return True
address_parts = [
"%s," % self.address,
"%s," % self.address2,
"%s" % self.address_locality,
"%s," % self.address_state,
"%s" % self.address_postcode,
]
return ' '.join(filter(check_address_parts, address_parts))
#property
def location_and_full_address(self):
if self.location:
if self.full_address:
return '{} - {}'.format(self.full_address, self.location)
return self.location
return self.full_address
#property
def entry(self):
address = '<div class="fs-6">{}</div>'.format(escape(self.full_address)) if self.full_address else ''
location = '<div class="fs-6">{}</div>'.format(escape(self.location)) if self.location else ''
return ' '.join((address, location))
#property
def connect(self):
owner = '' if not self.owner else self.owner.connect
callcenter = '' if not self.callcenter else self.callcenter.connect
return {
'type': 'device',
'pk': self.pk,
'uuid': self.uuid,
'state': self.state,
'first_name': '',
'last_name': '',
'owner': owner,
'callcenter': callcenter,
'initial': 'D',
'display_name': 'Device {}'.format(self.uuid),
'location': escape(self.location),
'address': escape(self.full_address),
'connect_version': settings.CONNECT_VERSION,
'url_live_call': reverse('device_live_call', args=[self.uuid]),
'theme': self.theme.settings,
}
#property
def connect_json(self):
return json.dumps(self.connect)
#property
def connect_version(self):
return settings.CONNECT_VERSION
pre_save.connect(uuid_pre_save_generator, sender=Device)
post_save.connect(alert_device_update, sender=Device)
class DeviceId(models.Model):
STAGED = 0
REQUESTED = 1
CAPTURED = 2
EXPIRED = 3
device_uuid_status = [
(STAGED, 'Staged'),
(REQUESTED, 'Requested'),
(CAPTURED, 'Captured'),
(EXPIRED, 'Expired'),
]
uuid = models.CharField(max_length=7, blank=True, unique=True, verbose_name='Device ID')
status = models.IntegerField(choices=device_uuid_status, default=0, verbose_name="ID Status")
programmer = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='programmer', null=True,
on_delete=models.PROTECT, verbose_name='Programmer')
# Timestamps
date_created = models.DateTimeField(auto_now_add=True)
date_requested = models.DateTimeField(blank=True, null=True)
date_captured = models.DateTimeField(blank=True, null=True)
date_expired = models.DateTimeField(blank=True, null=True)
objects = models.Manager()
class Meta:
verbose_name = "Device Id"
verbose_name_plural = "Device Ids"
ordering = ['date_created']
pre_save.connect(uuid_pre_save_generator, sender=DeviceId)
Well, I figured it out. For some reason the BigAutoField was set in the apps.py file in the app
from django.apps import AppConfig
class DeviceConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'device'

Django: how to define form in class based views? -> error Cannot assign '..' '..' must be a "Utilisateur" instance

I have already posted (see link below) to 'valid' my ER diagram.
I try to develop a form based on 'trought' model with nested inlineformset.
It works when I define fields in the UtilisateurCreateView class but I want to customize the 'trought' parent's form to be able to:
set initial pro_ide value with value send by GET
hidden this pro_ide field
customize uti_ide field label
So I define a UtilisateurProjetCreateForm based on the 'throught' model like I'm used to do but I got an error:
Cannot assign "'Slater, Kelly (k.slater#surf.com)'": "UtilisateurProjet.uti_ide" must be a "Utilisateur" instance.
moreover, as this form is based on 'throught' model, I am not sure I should define forms.ChoiceField...
models.py
class Projet(SafeDeleteModel):
_safedelete_policy = SOFT_DELETE_CASCADE
pro_ide = models.AutoField(primary_key = True)
# utilisateurs = models.ManyToManyField(Utilisateur, through='UtilisateurProjet')
pro_nom = models.IntegerField("Nom du projet")
pro_log = models.CharField("Log utiisateur", max_length=20, null=True, blank=True)
pro_dat = models.DateTimeField("Date log",auto_now_add=True)
pro_act = models.IntegerField("Projet en cours ?", null=True, blank=True)
class Meta:
db_table = 'tbl_pro'
verbose_name_plural = 'Projets'
ordering = ['pro_ide']
permissions = [
('can_add_project','Can add project'),
]
def __str__(self):
return f"{self.pro_nom}"
class Utilisateur(SafeDeleteModel):
_safedelete_policy = SOFT_DELETE_CASCADE
uti_ide = models.AutoField(primary_key = True)
# pro_ide = models.ForeignKey(Projet, on_delete = models.CASCADE) # related project
projets = models.ManyToManyField(Projet, through='UtilisateurProjet')
uti_nom = models.CharField("Nom", max_length=20)
uti_pre = models.CharField("Prénom", max_length=20)
uti_mai = models.CharField("Email", max_length=40)
uti_sit = models.CharField("Equipe", max_length=20, null=True, blank=True)
uti_pro = models.CharField("Fonction/profil", max_length=200, null=True, blank=True)
uti_dem_dat = models.DateTimeField("Date demande",auto_now_add=True, null=True, blank=True)
uti_val = models.IntegerField("Demande validée ?", null=True, blank=True)
uti_val_dat = models.DateTimeField("Date validation",null=True, blank=True)
uti_log = models.CharField("Log utilisateur", max_length=20, null=True, blank=True)
uti_dat = models.DateTimeField("Date log",auto_now_add=True, null=True, blank=True)
class Meta:
db_table = 'tbl_uti'
verbose_name_plural = 'Utilisateurs'
ordering = ['uti_ide']
def __str__(self):
return f"{self.uti_nom}, {self.uti_pre} ({self.uti_mai})"
class UtilisateurProjet(models.Model):
_safedelete_policy = SOFT_DELETE_CASCADE
pro_uti_ide = models.AutoField(primary_key = True)
uti_ide = models.ForeignKey(Utilisateur, on_delete=models.CASCADE)
pro_ide = models.ForeignKey(Projet, on_delete=models.CASCADE)
class Meta:
db_table = 'tbl_pro_uti'
class Application(SafeDeleteModel):
_safedelete_policy = SOFT_DELETE_CASCADE
app_ide = models.AutoField(primary_key = True)
# uti_ide = models.ForeignKey(Utilisateur, on_delete = models.CASCADE) # related utilisateur
pro_uti_ide = models.ForeignKey(UtilisateurProjet, on_delete = models.CASCADE) # related utilisateur-projet
app_app_nom = models.IntegerField("Nom application", null=True, blank=True)
app_dro = models.IntegerField("Droit sur application", null=True, blank=True)
app_sta = models.IntegerField("Statut (création/Modification/Suppression", null=True, blank=True)
app_log = models.CharField("Log utilisateur", max_length=20, null=True, blank=True)
app_dat = models.DateTimeField("Date log",auto_now_add=True, null=True, blank=True)
class Meta:
db_table = 'tbl_app'
verbose_name_plural = 'Applications'
ordering = ['app_ide']
views.py
# https://stackoverflow.com/questions/29981690/django-form-validation-on-class-based-view
class UtilisateurCreateView(FormView):
template_name = 'project/utilisateurprojet_form.html'
form_class = UtilisateurProjetCreateForm
def get_context_data(self, **kwargs):
data = super().get_context_data(**kwargs)
if self.request.POST:
data["utilisateur"] = self.request.user.username # nom de l'utilisateur connecté
data["projet"] = get_object_or_404(Projet, pro_ide = self.request.GET['projet'])
data["application"] = ApplicationFormset(self.request.POST)
else:
data["application"] = ApplicationFormset()
return data
def form_valid(self, form):
context = self.get_context_data()
application = context["application"]
self.object = form.save(commit=False)
self.object.uti_log = context["utilisateur"]
self.object.save()
if application.is_valid():
application.instance = self.object
application.save()
return super().form_valid(form)
def get_success_url(self):
return reverse("project:index")
forms.py
ApplicationFormset = inlineformset_factory(
UtilisateurProjet, Application,
fields=('app_app_nom','app_dro'),
widgets={
'app_app_nom': forms.Select(choices=NAME),
'app_dro': forms.Select(choices=ACCESS)
},
extra=3,
can_delete=True,
)
class UtilisateurProjetCreateForm(forms.ModelForm):
PROJETS = [(Projet.objects.get(pro_ide=1),'Coverage Africa'),]
UTILISATEURS = [(Utilisateur.objects.get(uti_ide=1),'Slater'),]
pro_ide = forms.ChoiceField(label = "Nom projet", widget = forms.Select, choices = PROJETS, initial = Projet.objects.get(pro_ide=1), disabled=True)
uti_ide = forms.ChoiceField(label = "Nom, prénom de l'utilisateur", widget = forms.Select, choices = UTILISATEURS)
class Meta:
model = UtilisateurProjet
fields = ('pro_ide','uti_ide')
related post
I had to use ModelChoiceFiled in my ModelForm:
class UtilisateurProjetCreateForm(forms.ModelForm):
PROJETS = Projet.objects.all()
UTILISATEURS = Utilisateur.objects.all()
pro_ide = forms.ModelChoiceField(queryset = PROJETS, label = "Nom projet", widget = forms.Select, initial = Projet.objects.get(pro_ide=1))
uti_ide = forms.ModelChoiceField(queryset = UTILISATEURS, label = "Nom, prénom de l'utilisateur", widget = forms.Select)
class Meta:
model = UtilisateurProjet
fields = ('pro_ide','uti_ide')

Django inlineformset: PK missing in subform -> form_set.is_valid() = False

I have followed this tutorial to implement inlneformset.
CreateView works (data is registered in database) but UpdateView doesn't.
UpdateView is correctly displayed with correct data.
But it seems like subform (application inlineformset) is never valid and I don't understand why?
forms.py:
NAME = Thesaurus.options_list(2,'fr')
ACCESS = Thesaurus.options_list(3,'fr')
ApplicationFormset = inlineformset_factory(
Utilisateur, Application,
fields=('app_app_nom','app_dro'),
widgets={
'app_app_nom': forms.Select(choices=NAME),
'app_dro': forms.Select(choices=ACCESS)
},
extra=3,
can_delete=True,
)
models.py:
class Projet(SafeDeleteModel):
_safedelete_policy = SOFT_DELETE_CASCADE
pro_ide = models.AutoField(primary_key = True)
pro_nom = models.IntegerField("Nom du projet", null=True, blank=True)
pro_log = models.CharField("Log utiisateur", max_length=20, null=True, blank=True)
pro_dat = models.DateTimeField("Date log",auto_now_add=True)
pro_act = models.IntegerField("Projet en cours ?", null=True, blank=True)
log = HistoricalRecords()
class Meta:
db_table = 'tbl_pro'
verbose_name_plural = 'Projets'
ordering = ['pro_ide']
permissions = [
('can_add_project','Can add project'),
]
class Utilisateur(SafeDeleteModel):
_safedelete_policy = SOFT_DELETE_CASCADE
uti_ide = models.AutoField(primary_key = True)
pro_ide = models.ForeignKey(Projet, on_delete = models.CASCADE) # related project
uti_nom = models.CharField("Nom", max_length=20, null=True, blank=True)
uti_pre = models.CharField("Prénom", max_length=20, null=True, blank=True)
uti_mai = models.CharField("Email", max_length=40, null=True, blank=True)
uti_sit = models.CharField("Equipe", max_length=20, null=True, blank=True)
uti_pro = models.CharField("Fonction/profil", max_length=200, null=True, blank=True)
uti_dem_dat = models.DateTimeField("Date demande",auto_now_add=True, null=True, blank=True)
uti_val = models.IntegerField("Demande validée ?", null=True, blank=True)
uti_val_dat = models.DateTimeField("Date validation",auto_now_add=True, null=True, blank=True)
uti_log = models.CharField("Log utilisateur", max_length=20, null=True, blank=True)
uti_dat = models.DateTimeField("Date log",auto_now_add=True, null=True, blank=True)
log = HistoricalRecords()
#classmethod
def options_list(cls,pro_ide):
projet = Projet.objects.get(pro_ide=pro_ide)
utilisateurs = Utilisateur.objects.filter(pro_ide=projet.pro_ide)
the_opts_list = [(utilisateur.uti_ide, utilisateur.uti_nom+', '+utilisateur.uti_pre) for utilisateur in utilisateurs]
the_opts_list.insert(0, (None, ''))
return the_opts_list
class Meta:
db_table = 'tbl_uti'
verbose_name_plural = 'Utilisateurs'
ordering = ['uti_ide']
class Application(SafeDeleteModel):
_safedelete_policy = SOFT_DELETE_CASCADE
app_ide = models.AutoField(primary_key = True)
uti_ide = models.ForeignKey(Utilisateur, on_delete = models.CASCADE) # related utilisateur
app_app_nom = models.IntegerField("Nom application", null=True, blank=True)
app_dro = models.IntegerField("Droit sur application", null=True, blank=True)
app_sta = models.IntegerField("Statut (création/Modification/Suppression", null=True, blank=True)
app_log = models.CharField("Log utilisateur", max_length=20, null=True, blank=True)
app_dat = models.DateTimeField("Date log",auto_now_add=True, null=True, blank=True)
log = HistoricalRecords()
class Meta:
db_table = 'tbl_app'
verbose_name_plural = 'Applications'
ordering = ['app_ide']
class Administration(SafeDeleteModel):
_safedelete_policy = SOFT_DELETE_CASCADE
adm_ide = models.AutoField(primary_key = True)
app_ide = models.ForeignKey(Application, on_delete = models.CASCADE) # related application
adm_nom = models.CharField("Nom d'utilisateur dans l'application", max_length=20, null=True, blank=True)
adm_dem = models.IntegerField("Demande traitée ?", null=True, blank=True)
adm_dem_dat = models.DateTimeField("Date traitement de la demande",auto_now_add=True)
adm_log = models.CharField("Log utilisateur", max_length=20, null=True, blank=True)
adm_dat = models.DateTimeField("Date log",auto_now_add=True)
log = HistoricalRecords()
class Meta:
db_table = 'tbl_adm'
verbose_name_plural = 'Adminitrations'
ordering = ['adm_ide']
permissions = [
('can_manage_project','Can manage project'),
]
UpdateView:
class UtilisateurUpdateView(UpdateView):
model = Utilisateur
fields = ['uti_nom','uti_pre','uti_mai','uti_sit','uti_pro']
def get_context_data(self, **kwargs):
data = super().get_context_data(**kwargs)
if self.request.POST:
data["utilisateur"] = self.request.user.username
data["application"] = ApplicationFormset(self.request.POST, instance=self.object)
else:
data["application"] = ApplicationFormset(instance=self.object)
return data
def form_valid(self, form):
context = self.get_context_data()
application = context["application"]
self.object = form.save()
self.object.save()
if application.is_valid(): # ***** NEVER VALID *****
application.instance = self.object
print('application.instance',application.instance)
application.app_app_nom = application.instance.cleaned_data['app_app_nom']
application.app_dro = application.instance.cleaned_data['app_dro']
application.app_log = context["utilisateur"]
application.uti_ide = 1
application.save()
return super().form_valid(form)
def get_success_url(self):
return reverse("project:index")
I have resolve my problem: I forget to insert form_set id in my html template (app_ide in my case)

Django-Admin Change form load quite slow while using one to one mapping field

In my case change form load very slow In Admin interface because a one_to_one field "disk" in SeverHasDisk Model in models.py. There is a disk field in ServerHasDiskInLine in admin.py. It works fine when I exclude "Disk" field from ServerHasDiskInLine in admin.py.
Is there a way to increase the performance by using a form class for ServerHasDiskInLine(admin.TabularInline)
or something else?
Models.py
#Models.py
class Server(models.Model):
hostname = models.CharField(max_length=64, unique=True, db_index=True)
description = models.TextField(max_length=255, blank=True, null=True)
note = models.TextField(max_length=255, blank=True, null=True)
numberOfCpu = models.IntegerField(default=1) # vCPU or HThread core
cpuClockRate = models.CharField(max_length=255) # Mhz
virtualization = models.CharField(max_length=255, blank=True, null=True)
ram = models.FloatField() # Go
vnc = models.IntegerField(blank=True, null=True, unique=True)
monitored = models.BooleanField(default=True)
dns = models.CharField(max_length = 255, blank=True, verbose_name= "DNS")
ansible = models.CharField(max_length = 255, blank=True, verbose_name= "Ansible")
# --------------Relations -----------------
# backup = models.ForeignKey('self', name='server_backup', related_name='backup', blank=True, null=True)
hypervisor = models.ForeignKey('self', name='server_hypervisor', related_name='hypervisor', blank=True, null=True)
operatingSystem = models.ForeignKey(OperatingSystem)
module = models.ForeignKey(Module, blank=True, null=True)
project = models.ForeignKey(Project, blank=True, null=True)
customer = models.ForeignKey(Customer, blank=True, null=True)
environment = models.ForeignKey(Environment, blank=True, null=True)
site = models.ForeignKey(Site, blank=True, null=True)
status = models.ForeignKey(ServerStatus, blank=True, null=True )
class Meta:
ordering = ('hostname',)
unique_together = ('hostname', 'site',)
class VolumeGroup(models.Model):
name = models.CharField(max_length=64, unique=True, db_index=True)
size = models.IntegerField() # Go
class Meta:
ordering = ('name',)
def __unicode__(self):
return "%s (%s Go)" % (self.name, self.size)
class LogicalVolume(models.Model):
# ------------------ Fields ---------------
name = models.CharField(max_length=64, unique=True, db_index=True)
size = models.IntegerField() # Go
note = models.TextField(max_length=255, blank=True, null=True)
# --------------Relations -----------------
volumeGroup = models.ForeignKey(VolumeGroup)
class Meta:
ordering = ('name',)
unique_together = ('volumeGroup', 'name')
def __unicode__(self):
return "%s (%s Go) on VG <%s>" % (self.name, self.size, self.volumeGroup.name)
class ServerHasDisk(models.Model):
# ------------------ Fields ---------------
mountPoint = models.CharField(max_length=255)
# --------------Relations -----------------
server = models.ForeignKey(Server, related_name='serverDisks')
disk = models.OneToOneField(LogicalVolume)
class Meta:
ordering = ('mountPoint',)
unique_together = ('server', 'disk')
def __unicode__(self):
return "Srv [%s]: %s ==> <%s> on VG <%s>" % (self.server.hostname, self.mountPoint, self.disk.name, self.disk.volumeGroup.name)
Admin.py
class ServerHasDiskInline(admin.TabularInline):
model = ServerHasDisk
extra = 0
# formset = MyFormSet
classes = ('grp-collapse grp-open',)
#exclude = ['disk']
class ServerHasRoleInline(admin.TabularInline):
model = ServerHasRole
extra = 0
fk_name = 'server'
classes = ('grp-collapse grp-open',)
class IpInline(admin.TabularInline):
model = IP
extra = 0
classes = ('grp-collapse grp-open',)
class BkSrvInline(admin.TabularInline):
model = ServerIsBackupedOn
fk_name = 'server'
extra = 0
classes = ('grp-collapse grp-open',)
class ServerAdmin(admin.ModelAdmin):
change_list_template = "admin/change_list_filter_sidebar.html"
list_display = ('hostname', 'get_project_name', 'get_module_name', 'get_environment_name', 'get_customer_name', 'get_os_name', 'get_site_name', 'get_ip_name', 'get_bk_hostname', 'get_role_name', 'description','note','get_dns','get_status','get_ansible')
list_filter = ('project__name', 'module__name', 'environment__name', 'customer__name', 'site__name', 'operatingSystem__name', 'serverRoles__role__name', 'serverIps__address')
list_per_page = 25
search_fields = ('hostname', 'project__name', 'module__name', 'environment__name', 'serverIps__address', 'serverRoles__role__name', 'note')
inlines = (ServerHasDiskInline,ServerHasVolumeGroupInline,ServerHasRoleInline, IpInline, BkSrvInline)
#related_search_fields={
#'disk': ( 'name', ),
#}
def get_project_name(self, o):
if o.project is None:
return "N/A"
else:
return o.project.name
get_project_name.admin_order_field = 'project'
get_project_name.short_description = 'Project'
def get_dns(self, o):
if o.dns is None:
return "N/A"
else:
return o.dns
get_dns.admin_order_field = 'dns'
get_dns.short_description = 'DNS'
def get_ansible(self, o):
if o.ansible is None:
return "N/A"
else:
return o.ansible
get_ansible.admin_order_field = 'ansible'
get_ansible.short_description = 'Ansible'
def get_module_name(self, o):
if o.module is None:
return "N/A"
else:
return o.module.name
get_module_name.admin_order_field = 'module'
get_module_name.short_description = 'Module'
def get_customer_name(self, o):
if o.customer is None:
return "N/A"
else:
return o.customer.name
get_customer_name.admin_order_field = 'customer'
get_customer_name.short_description = 'Customer'
def get_os_name(self, o):
if o.operatingSystem is None:
return "N/A"
else:
return o.operatingSystem.name
get_os_name.admin_order_field = 'operatingsystem'
get_os_name.short_description = 'OS'
def get_environment_name(self, o):
if o.environment is None:
return "N/A"
else:
return o.environment.name
get_environment_name.admin_order_field = 'environment'
get_environment_name.short_description = 'Environment'
def get_status(self, o):
if o.status is None:
return "N/A"
else:
return o.status.status
get_status.admin_order_field = 'status'
get_status.short_description = 'Status'
def get_site_name(self, o):
if o.site is None:
return "N/A"
else:
return o.site.name
get_site_name.admin_order_field = 'site'
get_site_name.short_description = 'Site'
def get_ip_name(self, o):
return ", ".join([
'%s' % ('../ip', k.id, k.address)
for k in o.serverIps.all()
])
# return ", ".join([k.address for k in o.serverIps.all()])
get_ip_name.admin_order_field = 'serverIps'
get_ip_name.short_description = 'IP'
get_ip_name.allow_tags = True
def get_bk_hostname(self, o):
return ", ".join([
'%s' % ('../server', k.backupServer.id, k.backupServer.hostname)
for k in o.serverBackuped.all()
])
# return '%s' % ('../project', o.project.id, o.project.name)
get_bk_hostname.admin_order_field = 'serverBackuped'
get_bk_hostname.short_description = 'Bk Srv'
get_bk_hostname.allow_tags = True
def get_role_name(self, o):
return ", ".join([k.role.name for k in o.serverRoles.all()])
get_role_name.admin_order_field = 'serverRoles'
get_role_name.short_description = 'Role'
Here is quick solution.
I have just added an attribute to ServerHasDiskInLine class in Admin.py
raw_id_fields = ("disk",) so New class is
class ServerHasDiskInline(admin.TabularInline):
model = ServerHasDisk
raw_id_fields = ("disk",)
extra = 0
classes = ('grp-collapse grp-open',)
#exclude = ['disk']