Django ForeignKey created empty? - django

This seems very basic and I must be missing something, but here goes anyways...
With two models like so:
class School(models.Model):
name = models.CharField("Official School Name", max_length=128)
address = models.TextField("Address of the School", max_length=256)
mascot = models.CharField("Name of the School Mascot", max_length=128)
class StudentProfile(models.Model):
name = models.CharField(max_length=128)
school = models.ForeignKey(School)
If the student gets created before the school, how do I give 'school' a default empty value? Is it blank or null or what?
Thanks!

null if you want the database to allow the relationship to be null, blank if you don't want the Django admin site to complain about it being null.
From the documentation on "blank":
"Note that this is different than null. null is purely database-related, whereas blank is validation-related. If a field has blank=True, validation on Django’s admin site will allow entry of an empty value. If a field has blank=False, the field will be required."
In short, you probably want both.

Related

How to setup search in django-admin changelists in models related through ForeignKeys?

I have created the following four model classes:
class InfrastructureModel(models.Model):
ENTRY_ACTIVE_YES_NO_CHOICES = (
(True, 'Yes'),
(False, 'No'))
entryActiveYesNo = models.BooleanField(r"Is this database entry still active? (YES/NO)",
null=False,
blank=False,
unique=False,
choices=ENTRY_ACTIVE_YES_NO_CHOICES,
help_text=r"Is this database entry still active? If it's been changed/modified to something else, mark this as False.")
class AirportAdministrativeData(InfrastructureModel):
officialAirportName=models.CharField(r"Airport's Official Name",
max_length=100,
null=False,
blank=False,
unique=True,
help_text=r"Offical name of the Airport")
def __str__(self):
return self.officialAirportName
class AirportAlternateName(InfrastructureModel):
parentAirport=models.ForeignKey(AirportAdministrativeData,on_delete=models.RESTRICT,limit_choices_to={'entryActiveYesNo': True},verbose_name="Parent Airport",related_name='AirportOfficialName')
alternateAirportName=models.CharField(r"Airport's Alternate Name",
max_length=100,
null=False,
blank=False,
unique=True,
help_text=r"Alternate name of the Airport, if any.")
class AirportLocation(InfrastructureModel):
parentAirport=models.ForeignKey(AirportAdministrativeData,on_delete=models.RESTRICT,limit_choices_to={'entryActiveYesNo': True},verbose_name="Parent Airport")
latitude=models.DecimalField(max_digits=9, decimal_places=6)
longitude=models.DecimalField(max_digits=9, decimal_places=6)
airportAddress=models.CharField(r"Airport's Address",
max_length=200,
null=False,
blank=False,
unique=True,
help_text=r"Airport's Address")
airportState=models.ForeignKey(State,on_delete=models.RESTRICT,limit_choices_to={'entryActiveYesNo': True},verbose_name="State")
And their corresponding Admin classes are as follows:
class AirportAdministrativeDataAdmin(admin.ModelAdmin):
fields = ['officialAirportName', 'entryActiveYesNo']
list_display = ('officialAirportName', 'entryActiveYesNo')
search_fields = ['officialAirportName']
search_help_text="Seach here for offical/alternate name of any airport in the Database."
class AirportAlternateNameAdmin(admin.ModelAdmin):
fields = ['parentAirport', 'alternateAirportName', 'entryActiveYesNo']
list_display = ('parentAirport', 'alternateAirportName', 'entryActiveYesNo')
search_fields = ['alternateAirportName']
search_help_text="Seach here for offical/alternate name of any airport in the Database."
class AirportLocationAdmin(admin.ModelAdmin):
fields = ['parentAirport', 'latitude', 'longitude', 'airportAddress', 'airportState', 'entryActiveYesNo']
list_display = ('parentAirport', 'latitude', 'longitude', 'airportAddress', 'airportState', 'entryActiveYesNo')
#search_fields = ['parentAirport']
search_help_text="Seach here for offical/alternate name of any airport in the Database."
And their corresponding admin site registrations are as follows:
admin.site.register(AirportAdministrativeData,AirportAdministrativeDataAdmin)
admin.site.register(AirportAlternateName, AirportAlternateNameAdmin)
admin.site.register(AirportLocation, AirportLocationAdmin)
I want to be able to search in the change lists of these respective models using either of the following fields:
AirportAdministrativeData model’s officialAirportName field, or,
AirportAlternateName model’s alternateAirportName field.
and return the corresponding search entry.
I have read several articles such as django documentation on ForeignKey.related_name and this stackoverflow q&a. But my novice self is still struggling in being able to implement this feature. Please help!
To add a search field from a related model you need to use the same notation as with filter(), i.e. a path with names of the fields separated with double-underscores.
First search field
To add AirportAdministrativeData.officialAirportName as search field to the change list of AirportLocation you add this: 'parentAirport__officialAirportName.
Second search field
For the 2nd search field to the alternate name you need to go one level deeper and use the "related name", which is the reverse relation from AirportAdministrativeDataAdmin to AirportAlternateNameAdmin:
'parentAirport__AirportOfficialName__alternateAirportName'
Result
Search fields are combined with OR by default, so you can add the 2nd search field and it will filter objects which match one or the other:
class AirportLocationAdmin(admin.ModelAdmin):
...
search_fields = [
'parentAirport__officialAirportName',
'parentAirport__AirportOfficialName__alternateAirportName'
]
...
Two additional suggestions if I may:
In Python properties of a method are supposed to be in snake case, like you see in the Admin classes. So I would suggest to rename all field names of your models and also the "related_name" definitions. See PEP8 for more infos about the official coding style for Python
the "r" in front of your strings is obsolete. It means that you are defining regular expressions strings, which would not make sense here. Would suggest to remove the "r", you do not need it.

How i can create a muti value filed without manytomany field in django?

I have a model:
class People(models.Model):
family = models.CharField(null=True)
phone_numbers = ?
How i can implement phone_numbers for some phone numbers. I think ManyToManyField is not a good idea for doing this.
What is best practice for this?
admin.py
class PhonesInline(admin.TabularInline):
model = models.Phones
class PeopleAdmin(admin.ModelAdmin):
inlines = [
PhonesInline,
]
admin.site.register(models.People, PeopleAdmin)
What you can do is create a Phone model and create a Many-to-one relationship between Phone and People using ForeignKey. With this you can associate various phone numbers to a single person.
class People(models.Model):
family = models.CharField(null=True)
class Phone(models.Model):
number = models.CharField(max_length=15, unique=True)
person = models.ForeignKey(People, on_delete=models.CASCADE)
Now, for example, if you have a People instance in a variable called people, you can access its related phone numbers with values_list:
people.phone_set.values_list('number', flat=True)
As a note for your model, it's not recommended to use null=True to a CharField/TextField. The official Django documentation states the following:
Avoid using null on string-based fields such as CharField and TextField. If a string-based field has null=True, that means it has two possible values for “no data”: NULL, and the empty string. In most cases, it’s redundant to have two possible values for “no data;” the Django convention is to use the empty string, not NULL. One exception is when a CharField has both unique=True and blank=True set. In this situation, null=True is required to avoid unique constraint violations when saving multiple objects with blank values.
You can also take a look at this question, which tackles my last point.
Also I don't know which logic you want to apply to your project, but I think a better way to organize your models and their relationships is to create a Family class to deal with families like:
class Family(models.Model):
name = models.CharField(max_length=100)
class People(models.Model):
family = models.ForeignKey(Family, blank=True, null=True)
class Phone(models.Model):
number = models.CharField(max_length=15, unique=True)
person = models.ForeignKey(People, on_delete=models.CASCADE)
With this extra model you will be able to create another Many-to-one relationship between People and Family. Depending on your needs, you should adapt the arguments when creating the fields, the ones I provided are just an example.

How to make a model parameter unique by a other parameter in Django?

I want my id field to be unique per each customer field. Just like the option unique_for_date from Django (https://docs.djangoproject.com/en/1.11/ref/models/fields/#unique) but in this case, not date but customer.
class Sample(NGObject):
id = models.CharField(max_length=128, null=True, blank=False)
customer = models.ForeignKey(Customer, related_name="blood_samples", on_delete=models.SET(get_default_customer))
I believe this should be done, before the save() method?
When a User writes the wrong ID (that already exists) I would also like to present the information in the Admin Form just like it would for normal unique error.
class Meta:
unique_together = ('sample_id', 'customer',)
This has done the trick :)

OneToOne field in django default

Please help. I have a model:
class Book(core.BaseModel):
book_link = models.OneToOneField('self', default = "", on_delete=models.CASCADE)
book_name = models.CharField('Name', max_length=250)
I want to set 'self' in field book_link that will return in this field - book_name or Book Model object.
But when I create new Book object - Django shows me in column "book_link" all book names which I can choose and save new object. I want that when I created new object it will authomatically save for this object this name!
If I have understood your question, you want to create something like a linked list of books. To do so, first do not use one to one field unless each book is only and only linked to one book. To link one object to itself, you can use the name of model in string format.
And also note the way you had provided default was faulty, It is better to make it nullable with null=True.
My recommended model will be this:
class Book(models.Model):
book_link = models.ForeignKey(to='Book', null=True, on_delete=models.CASCADE, related_name="linked_books")
book_name = models.CharField('Name', max_length=250)

Blank field not working correctly in Django model

I have a Django model described as follows-
class Building(models.Model):
name = models.CharField(max_length=25,unique=True,blank=False)
country = models.CharField(max_length=20,blank=False)
city = models.CharField(max_length=20,blank=False)
def __str__(self):
return self.name
All of the fields are required as blank is set to False in each of them but still, I am able to save objects for this model by leaving city and country as blank.
blank=True is enforced at the ModelForm layer, as is specified in the documentation on the blank=… parameter [Django-doc]:
Note that this is different than null. null is purely database-related, whereas blank is validation-related. If a field has blank=True, form validation will allow entry of an empty value. If a field has blank=False, the field will be required.
So a ModelForm that uses this model will raise errors when you do not enter a value for name, city, and country. But not the model layer. In fact the model layer does not validate any constraints, unless you call .clean(), or the database rejects the values.