How do I get the id of a Foreign Key - python

I am trying to autofill these fields if the foreign key is selected
The Base Class:
class ScreeningCamp(models.Model):
beneficiary=models.ForeignKey(Beneficiary,on_delete=models.CASCADE)
name=models.CharField(max_length=200,default=Beneficiary.objects.get(id=beneficiary.id).name,blank=True)
dob=models.DateField(default=Beneficiary.objects.get(id=beneficiary.id).dob,blank=True)
gender=models.CharField(max_length=200,choices=GENDER_CHOICES,default=Beneficiary.objects.get(beneficiary.id).gender,blank=True)
The Parent Class:
class Beneficiary(models.Model):
image=models.ImageField(upload_to='home/images/',blank=True,null=True)
name = models.CharField(max_length=200)
gender=models.CharField(max_length=6,choices=GENDER_CHOICES,default='male')
dob=models.DateField()
I just want to autofill name, dob etc from the beneficiary class when the foreign key is selected
When it is not selected we have to manually do it
I think just getting the id of the selected object will help
Can anyone please tell me how to do that?

So basically, You want to create a ScreeningCamp record with the data that is being used while creating the Beneficiary record.
example:
let's only take name and dob fields.
beneficiary_1 = Beneficary(name='test1',dob=2006-10-02)
then a row on the ScreeningCamp Table will be created with the same name, dob, and a foreign key relationship to the beneficary_1.
You can achieve this by using Django signals.
models.py Let's only take name and dob for now.
Models on the models.py
class Beneficiary(models.Model):
name = models.CharField(max_length=200)
dob = models.DateField()
class ScreeningCamp(models.Model):
beneficiary = models.ForeignKey(Beneficiary, on_delete=models.CASCADE)
name = models.CharField(max_length=200, blank=True)
dob = models.DateField(blank=True)
Assuming the models are declared on the same app's models.py. Create a signals.py file in the app that receives the post_save signal when a Beneficiary record is created. Let's call the app Post.
from django.db.models.signals import post_save
from django.dispatch import receiver
from . import models
#receiver(post_save, sender=models.Beneficiary)
def create_screening_camp(sender, instance, created, **kwargs):
if not created:
return
# Create the ScreeningCamp object, only if it is newly created
screening_camp = models.ScreeningCamp(name=instance.name, beneficiary=instance, dob=instance.dob)
screening_camp.save()
on your apps.py
from django.apps import AppConfig
class PostConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'Post'
def ready(self):
from . import signals
in settings.py installed_apps, include
INSTALLED_APPS = [
...
'Post.apps.PostConfig',
]

If you're calling ScreeningCamp, Django can lookup the Foreignkey. Here is an example:
screening_camp = ScreeningCamp.objects.get(pk=1)
name = screening_camp.beneficiary.name
gender = screening_camp.beneficiary.gender
dob = screening_camp.beneficiary.dob
# populating form
form = ScreeningCampForm(initial={"name": name, "gender": gender, "dob":dob}, instance=screening_camp)
return render(request, "form.html", {"form": form})

Related

AttributeError at /admin/student/student_record/

I updated my django model, for my student app, it now looks like this
from django.db import models
class Student_Record(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
email = models.CharField(max_length=50)
address = models.CharField(max_length=500)
gpa = models.FloatField()
def __str__(self):
return str(self.student_id) + ", " + self.first_name
there used to be an IntegerField, student_id but I removed it. I made the migrations, and everything runs fine, but when I visit the django admin panel, to manually update the database records, I get the following error
does anyone know what's going on?
I registered the model, in admin.py
from django.contrib import admin
from .models import Student_Record
admin.site.register(Student_Record)
Look at your __str__ method it still references student_id.
You should search for the field name in your whole project, there might be other occurrences elsewhere.

the model field's form disappears in django admin

I have two models, which are User and Record. Each has several fields.
from django.db import models
class User(models.Model):
openid = models.CharField(max_length=20)
nickname = models.CharField(max_length=20,null=True)
def __str__(self):
return self.nickname
class Record(models.Model):
expression = models.CharField(max_length=100)
user = models.ForeignKey(User)
time = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.expression
I register them in admin.py
from django.contrib import admin
from .models import User,Record
class RecordAdmin(admin.ModelAdmin):
list_display = ('expression','user','time')
class UserAdmin(admin.ModelAdmin):
empty_value_display = "çİş"
list_display = ('openid','nickname')
admin.site.register(User,UserAdmin)
admin.site.register(Record,RecordAdmin)
it works well in django admin initially. but one day, the fields of the Record model disppeared. It looks like
.
No field displays. It makes me unable to modify or add the values of the Record model. The other model User works well and all data exists in database. So why?
I think you just have to add on_delete=models.CASCADE in your ForeignKey Field. When you are using this kind of field, you have to specify the comportment when you make an update, a delete or anything else on this field.
So your script should be like this :
class Record(models.Model):
expression = models.CharField(max_length=100)
user = models.ForeignKey(User, on_delete=models.CASCADE)
time = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.expression
This is the result :
Edit :
You can also modify null=True by default=null
class User(models.Model):
openid = models.CharField(max_length=20)
nickname = models.CharField(max_length=20,default=null)
def __str__(self):
return self.nickname

How to access a ManyToManyField between two apps using ContentTypes for Django admin?

Say I have this app named Pantry that is to connect to any other app I may come along. To keep the app decoupled, generic relations are used through the model LinkedItem which connects the Ingredients model to apps outside Pantry.
I can make a filter_horizontal show up for the LinkedItem's admin in Django. Now I would like the content on the other end of the generic relation, say an app named Bakery, to be able to do a filter_horizontal with ingredients.
Pantry
models.py
from django.db import models
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes import fields
class Ingredient(models.Model):
'''
Model containing all the ingredients, their slugs, and their descriptions
'''
name = models.CharField(unique=True, max_length=100)
slug = models.SlugField(unique=True, max_length=100)
description = models.CharField(max_length=300)
# method to return the name of the db entry
def __str__(self):
return self.name
class LinkedItem(models.Model):
'''
Model that links ingredients to various other content models
'''
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = fields.GenericForeignKey('content_type', 'object_id')
ingredient = models.ManyToManyField(Ingredient)
# method to return the name of the db entry
def __str__(self):
return self.ingredient.name
# defines options for the model itself
class Meta:
unique_together = (('content_type','object_id')) # prevents duplicates
Bakery
admin.py
from django.contrib import admin
from bakery.models import Cake
class CakeAdmin(admin.ModelAdmin):
filter_horizontal = ('') # what to put here so ingredients show up?
Any ideas?
A solution is to create a GenericTabularInline for LinkedItem and putting some restrictions on the display to avoid duplicates like below:
from django.contrib.contenttypes.admin import GenericTabularInline
class LinkedItemAdmin(GenericTabularInline):
model = LinkedItem
# choosing the field and display
field = ['ingredient']
filter_horizontal = ['ingredient']
# These help with removing some potential issues in the admin
extra = 0
min_num = 1
max_num = 1
can_delete = False
Then in the CakeAdmin I can do this to make the ingredients show up.
class CakeAdmin(admin.ModelAdmin):
inlines = [LinkedItemAdmin]

Create model after group has been created django

I need to create an instance of my model every time a new group has been created in the admin panel.
I read some information about signals, but i can't figured it out at all.
Thank you very much
models.py with your model:
from django.db import models
from django.contrib.auth.models import Group
from django.db.models.signals import post_save
class YourModel(models.Model):
name = models.CharField('name', max_length=50)
group = models.ForeignKey(Group)
# ...
#classmethod
def create_after_group(cls, sender, instance, created, **kwargs):
if created:
group_created = instance
m = cls(name="Some name", group=group_created)
m.save()
post_save.connect(YourModel.create_after_group, sender=Group)

Why doesn't self.object in a CreateView have an id after saving to the database?

Following the comment on the accepted answer on django createview how to get the object that is created, I am attempting to use the id from a user created by a CreateView in its get_success_url method. However, even though it is definitely being saved to MySQL and receiving an id, when I access self.object, it doesn't have an id to use. The model does have an id property. Why wouldn't I be able to access the id? If I'm being led astray by the linked comment, what is the right way to get the id?
Reference code:
models.py
from django.db import models
class User(models.Model):
id = models.IntegerField(primary_key=True)
name = models.CharField(max_length=128)
active = models.BooleanField(blank=True)
created_date = models.DateTimeField()
class Meta:
managed = False
db_table = 'user'
def __unicode__(self):
return self.name
views.py
from django.views.generic import CreateView
from django.core.urlresolvers import reverse
from forms import AddUserForm
class AddUserView(CreateView):
form_class = AddUserForm
fields = ['name', 'active'] # id and created_date are auto-filled upon save
template_name = 'webApp/add_user_form.html'
def get_success_url(self):
print self.object # Prints the name of the submitted user
print self.object.id # Prints None
return reverse("webApp:user:stepTwo", args=(self.object.id,))
It's blank because the object is not actually receiving an id. That's because the id field should be an AutoField, not IntegerField, so that it is declared as auto-incrementing.
Actually though you should not declare it at all: an primary key AutoField named id is the default, so you should leave it out.
Note you'll need to migrate your database table, or drop and recreate it, after you make this change.

Categories