Django: How to save data to ManyToManyField? - django

I have a question concerning the following model. I want to populate the ManyToManyField from views.py instead of doing it from the Admin.
But how do I add data to the genres field which is the ManyToManyField?
views.py
content = Movie_Info(id = m_id,
title = data[0].get('title'),
overview = data[0].get('overview'),
release_date = data[0].get('release_date'),
)
content.save()
models.py
class Movie_Info_genre(models.Model):
genre = models.CharField(max_length=100)
class Movie_Info(models.Model):
id = models.IntegerField(primary_key=True)
title = models.CharField(max_length=100, blank=True, null=True)
overview = models.TextField(blank=True, null=True)
release_date = models.CharField(max_length=10, blank=True, null=True)
genres = models.ManyToManyField(Movie_Info_genre)

Use the add method for related fields:
# using Model.object.create is a shortcut to instantiating, then calling save()
myMoveInfo = Movie_Info.objects.create(title='foo', overview='bar')
myMovieGenre = Movie_Info_genre.objects.create(genre='horror')
myMovieInfo.genres.add(myMoveGenre)
Unlike modifying other fields, both models must exist in the database prior to doing this, so you must call save before adding the many-to-many relationship. Since add immediately affects the database, you do not need to save afterwards.

Related

Add Queryset to django updateview

I have an updateview in which a manager can go and edit all the fields for the associate. Looks like this:(requirement is to add associate_mgr in the as a dropdown in the updateview)enter image description here
views.py
class ReallocationTeam(LoginRequiredMixin,UpdateView):
model = UserDetails
form_class = ViewEditSample
def get_success_url(self):
return reverse('UserProfile:index')
forms.py
class ViewEditSample(ModelForm):
class Meta:
model = UserDetails
fields = ['associate_name','client','lob','associate_mgr']
The manager should be able to edit the "assciate_mgr" of that associate too.
models.py
associate_name = models.CharField(max_length=200)
associate_nbr = models.CharField(max_length=8, primary_key=True)
associate_email = models.EmailField()
associate_department_id = models.CharField(max_length=50)
associate_mgr = models.CharField(max_length=100,blank=True, null=True)
associate_exec = models.CharField(max_length=100,blank=True, null=True)
associate_org = models.CharField(max_length=100,blank=True,null=True)
title = models.CharField(null=True, blank=True, max_length=100)
date_of_service = models.CharField(null=True,blank=True,max_length=11)
is_manager = models.BooleanField(default=False)
is_exec = models.BooleanField(default=False)
is_team_lead = models.BooleanField(default=False)
but associate_mgr is not a choice field in my db.
I need to add a dropdown that contains associate_mgr in my UpdateView. How do I go about implementing that?
Should I go about writing a query to get all managers and populate them i a dropdow: like this mgr = UserDetails.objects.filter(is_manager=True) But then how do i store the selected in associate_mgr field in db?
You can override your form field in your ModelForm to be a ChoiceField with a list of choices: UserDetails.objects.filter(is_manager=True).values_list('name').
associate_mgr = forms.ChoiceField(choices=
UserDetails.objects.filter(is_manager=True).values_list('associate_name', 'associate_name')
)
Then the choice will automatically be saved (the 'associate_name' field value).
But it would probably be a better idea to use a ForeignKey on your model, rather than a CharField. That would enforce the values to be other UserDetails rather than just a string.

Django Forms multiple foreignkey

I have four models, three of which have ‘independent’ fields but the fourth models has ForeignKey links to the other three.
class PreCheck(models.Model):
name = models.CharField(max_length=120)
time_in = models.DateTimeField(auto_now_add=True)
is_insured = models.BooleanField()
class MainCheck(models.Model):
height = models.FloatField()
weight = models.IntegerField()
class PostCheck(models.Model):
sickness = models.CharField(max_length=30)
medication = models.CharField(max_length=30)
class MedicalRecord(models.Model):
patient = models.ForeignKey(User)
next_check_date = models.DateTimeField()
payment_amount = models.IntegerField()
initial_check = models.ForeignKey(PreCheck)
main_check = models.ForeignKey(MainCheck)
post_check = models.ForeignKey(PostCheck)
Assume a patient goes in a room, a precheck is done and saved, then other checks are done and finally a final record is set.
Ideally, I would like to fill in forms for the different models at different times possibly in different pages/tabs.
The admin has popups for the MedicalRecord model but in the frontend its hard to write javascript for that.
Another option would be to fill in the modelforms separately and do a str return function then select that from dropdowns in the MedicalRecord form( which I’m trying to avoid)
Just add blank=True, null=True for each ForeignKey fields.
initial_check = models.ForeignKey(PreCheck, blank=True, null=True)
main_check = models.ForeignKey(MainCheck, blank=True, null=True)
post_check = models.ForeignKey(PostCheck, blank=True, null=True)
at the initial check, you can create MedicalRecord with help of MedicalRecord model-form, this time main_check and post_check record can be left blank.
after main check, you can update MedicalRecord with main_check details, this time left blank post_check record, and keep updating your MedicalRecord on different pages/tabs with available details.

I am working with Django, During inserting data into database i caught such error

I'm working with django, during inserting data into tables the error is generates as given below...
Error:
int() argument must be a string, a bytes-like object or a number, not 'Tbl_rule_category', How can we solve such error?
view.py
dataToRuleCtgry = Tbl_rule_category(category=category, created_by="XYZ",created_date=datetime.date.today())
dataToRuleCtgry.save()
dataToRule = Tbl_rule(rule_name=rule_name, closure=closure,category_id=Tbl_rule_category.objects.latest('category_id'), created_by="XYZ",created_date=datetime.date.today(), updated_by="XYZ", updated_date=datetime.date.today(), rule_type=rule_type, fk_tbl_rule_tbl_rule_category_id=Tbl_rule_category.objects.latest('category_id'))
dataToRule.save()
models.py
class Tbl_rule_category(models.Model):
category_id = models.AutoField(primary_key=True)
category = models.CharField(max_length=50)
created_by = models.CharField(max_length=50)
created_date = models.DateField(auto_now_add=True)
def __str__(self):
pass # return self.category, self.created_by
class Tbl_rule(models.Model):
rule_id = models.AutoField(primary_key=True)
rule_name = models.CharField(max_length=50)
closure = models.CharField(max_length=50)
category_id = models.IntegerField()
created_by = models.CharField(max_length=50)
created_date = models.DateField(auto_now_add=True)
updated_by = models.CharField(max_length=50)
updated_date = models.DateField(auto_now=True)
rule_type = models.CharField(max_length=50)
fk_tbl_rule_tbl_rule_category_id = models.ForeignKey(Tbl_rule_category,on_delete=models.CASCADE, related_name='fk_tbl_rule_tbl_rule_category_id_r')
def __str__(self):
return self.rule_name, self.closure, self.created_by, self.updated_by, self.rule_type
The error is occurring because the following is trying to add an object into an integer field: category_id=Tbl_rule_category.objects.latest('category_id')
You could just add: category_id=dataToRuleCtgry.get('category_id') or category_id=dataToRuleCtgry.category_id which will solve the error.
You also don't need to add: created_date=datetime.date.today() because your model defines auto_now=true.
As mentioned you should also amend the def __str__(self): to return a string.
https://docs.djangoproject.com/en/2.0/ref/models/instances/#django.db.models.Model.str
Alternatively
You could just add the object link directly to your foreign key for the category model.fk_tbl_rule_tbl_rule_category_id=dataToRuleCtgry. You would no longer need the integer field category_id.
It would be better practice to use the model field name category_id instead of fk_tbl_rule_tbl_rule_category_id. This would mean deleting category_id and then rename fk_tbl_rule_tbl_rule_category_id to category_id.
In Django, the ORM takes care of the basic database details for you; which means in your code you really don't have to worry about individual row ids for maintaining foreign key relationships.
In fact, Django automatically assigns primary keys to all your objects so you should concentrate on fields that are relevant to your application.
You also don't have to worry about naming fields in the database, again Django will take care of that for you - you should create objects that have fields that are meaningful to users (that includes you as a programmer of the system) and not designed for databases.
Each Django model class represents a object in your system. So you should name the classes as you would name the objects. User and not tbl_user. The best practice is to use singular names. Django already knows how to create plural names, so if you create a model class User, django will automatically display Users wherever it makes sense. You can, of course, customize this behavior.
Here is how you should create your models (we will define __str__ later):
class RuleCategory(models.Model):
name = models.CharField(max_length=50)
created_by = models.CharField(max_length=50)
created_date = models.DateField(auto_now_add=True)
class Rule(models.Model):
name = models.CharField(max_length=50)
closure = models.CharField(max_length=50)
created_by = models.CharField(max_length=50)
created_date = models.DateField(auto_now_add=True)
updated_by = models.CharField(max_length=50)
updated_date = models.DateField(auto_now=True)
rule_type = models.CharField(max_length=50)
category = models.ForeignKey(RuleCategory,on_delete=models.CASCADE)
Django will automatically create any primary or foreign key fields, and any intermediary tables required to manage the relationship between the two models.
Now, to add some records:
new_category = RuleCategory(name='My Category', created_by='XYZ')
new_category.save()
# Another way to set values
new_rule = Rule()
new_rule.name = 'Sample Rule'
new_rule.closure = closure
new_rule.created_by = 'XYZ'
new_rule.updated_by = 'XYZ'
new_rule.rule_type = rule_type
new_rule.category = new_category
new_rule.save()
Note this line new_rule.category = new_category - this is how we link two objects. Django knows that the primary key should go in the table and will take care of that automatically.
The final item is customizing the models by creating your own __str__ method - this should return some meaningful string that is meant for humans.
class RuleCategory(models.Model):
name = models.CharField(max_length=50)
created_by = models.CharField(max_length=50)
created_date = models.DateField(auto_now_add=True)
def __str__(self):
return '{}'.format(self.name)
class Rule(models.Model):
name = models.CharField(max_length=50)
closure = models.CharField(max_length=50)
created_by = models.CharField(max_length=50)
created_date = models.DateField(auto_now_add=True)
updated_by = models.CharField(max_length=50)
updated_date = models.DateField(auto_now=True)
rule_type = models.CharField(max_length=50)
category = models.ForeignKey(RuleCategory,on_delete=models.CASCADE)
def __str__(self):
return '{} for category {}'.format(self.name, self.category)
If you notice something, I just put self.category in the __str__ for the Rule model. This is because we have already defined a __str__ for the RuleCategory model, which just returns the category name; so now when we print our Rule we created, we will get Sample Rule for category My Category as a result.

django get associated data one to one field

I'm working in Django 2.0
I have a model Note to save note and two another models to add color labels to the note.
class Note(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
title = models.CharField(max_length=250, blank=True, default='Untitled')
content = models.TextField(blank=True)
class ColorLabels(models.Model):
title = models.CharField(max_length=100, unique=True)
value = models.CharField(max_length=100)
default = models.BooleanField(default=False)
class NoteLabel(models.Model):
note = models.OneToOneField(Note, on_delete=models.CASCADE)
color_label = models.OneToOneField(ColorLabels, on_delete=models.CASCADE)
with the object of Note
note = Note.objects.get(pk=1)
I want to access associated ColorLabels's title and value fields or the NoteLabel object.
since they are one to one field. I tried doing
note.note_label
note.NoteLabel
note.note_label_set
But all returns error as
AttributeError: 'Note' object has no attribute 'note_label_set'
Unless you define related_name in your OneToOneField, Django will use lowercased model name to access related object. So, note.notelabel should work.

Django: Converting a GenericForeignKey Relationship to a ForeignKey Relationship

I'm working to remove an existing GenericForeignKey relationship from some models. Id like to change it to the Reformatted Model below. Does migrations provide a way to convert the existing content_type and object_ids to the respective new ForeignKey's? (to keep existing data). Basically brand new at programming, so pardon me if I'm asking a stupid question.
class Donation(models.Model):
amount_id = models.CharField(max_length=12, unique=True, editable=False)
date_issued=models.DateField(auto_now_add=True)
description=models.TextField(blank=True, null=True)
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey('content_type','object_id')
class Individual(BaseModel):
first_name = models.CharField(max_length=50)
middle_name = models.CharField(max_length=50, blank=True,
null=True)
last_name = models.CharField(max_length=50)
suffix = models.CharField(max_length=50, blank=True, null=True)
contributor = generic.GenericRelation(Donation, related_query_name='individual')
class Organization(models.Model):
name = models.CharField(max_length=100)
contributor = generic.GenericRelation(Donation, related_query_name='organization')
Reformatted Model
class Donation(models.Model):
amount_id = models.CharField(max_length=12, unique=True, editable=False)
date_issued=models.DateField(auto_now_add=True)
description=models.TextField(blank=True, null=True)
contributor_group = models.ForeignKey(Organization, null=True, blank=True, on_delete=models.CASCADE)
contributor_individual = models.ForeignKey(Individual, null=True, blank=True, on_delete=models
Based on your model definition of Donation Model, one of fields contributor_group , contributor_model will always be Null post migration.
I hope you have taken that into you consideration.
Just to be safe Do this in two phases.
1. Keep the content_type and object_id and add the two new fields.
2. Next step remove the generic fields post data population.
There are two ways to populate those new fields
Django migrations provides you a way to populate new fields with values during the migrations. You can look it up. I haven't done that before either.
For more control and some learning as well. You can populate that via scripting as well. You can setup django-extensions module in your project. And write a script to do that population for you as well. A sample script would look like.
from myproject.models import Donation, Individual, Organization
from django.contrib.contenttypes.models import ContentType
def run():
organization_content_type = ContentType.objects.get_for_model(Organization)
individual_content_type = ContentType.obejcts.get_for_model(Individual)
donations = Donation.objects.all()
for donation in donations:
if donation.content_type_id == organization_content_type.id:
donation.contributor_group = donation.object_id
elif donation.content_type_id == individual_content_type.id:
donation.contributor_individual = donation.object_id
else:
print "Can't identify content type for donation id {}".format(donation.id)
donation.save()
Check the values are correct and then remove the generic fields.
Facing some issues with formatting here.