from django.db import models class TimestampedModel(models.Model): created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) class Meta: abstract = True class Institution(TimestampedModel): id = models.CharField(max_length=20, primary_key=True) # e.g., I204778367 name = models.CharField(max_length=255) ror_id = models.CharField(max_length=100, unique=True) country_code = models.CharField(max_length=2) institution_type = models.CharField(max_length=50) # funder, company, etc. def __str__(self): return self.name class Author(TimestampedModel): id = models.CharField(max_length=20, primary_key=True) # e.g., A5006834808 name = models.CharField(max_length=255) orcid = models.CharField( max_length=100, unique=True, null=True, blank=True) h_index = models.IntegerField() i10_index = models.IntegerField() cited_by_count = models.IntegerField() works_count = models.IntegerField() mean_2yr_citedness = models.FloatField() def __str__(self): return self.name class Affiliation(TimestampedModel): author = models.ForeignKey( Author, on_delete=models.CASCADE, related_name='affiliations') institution = models.ForeignKey(Institution, on_delete=models.CASCADE) year = models.IntegerField() is_last_known = models.BooleanField(default=False) class Meta: unique_together = ('author', 'institution', 'year') class Domain(TimestampedModel): id = models.CharField(max_length=10, primary_key=True) # e.g., 3 name = models.CharField(max_length=255) def __str__(self): return self.name class Field(TimestampedModel): id = models.CharField(max_length=10, primary_key=True) # e.g., 23 name = models.CharField(max_length=255) domain = models.ForeignKey( Domain, on_delete=models.CASCADE, related_name='fields') def __str__(self): return self.name class Subfield(TimestampedModel): id = models.CharField(max_length=10, primary_key=True) # e.g., 2304 name = models.CharField(max_length=255) field = models.ForeignKey( Field, on_delete=models.CASCADE, related_name='subfields') def __str__(self): return self.name class Topic(TimestampedModel): id = models.CharField(max_length=20, primary_key=True) # e.g., T13180 name = models.CharField(max_length=255) subfield = models.ForeignKey( Subfield, on_delete=models.CASCADE, related_name='topics') def __str__(self): return self.name class AuthorTopic(TimestampedModel): author = models.ForeignKey( Author, on_delete=models.CASCADE, related_name='topics') topic = models.ForeignKey(Topic, on_delete=models.CASCADE) count = models.IntegerField() share_value = models.FloatField() class Meta: unique_together = ('author', 'topic') class Work(TimestampedModel): id = models.CharField(max_length=20, primary_key=True) # e.g., W123456789 author = models.ForeignKey( Author, on_delete=models.CASCADE, related_name='works') title = models.CharField(max_length=512) year = models.IntegerField() cited_by_count = models.IntegerField() def __str__(self): return self.title class AuthorYearlyStats(TimestampedModel): author = models.ForeignKey( Author, on_delete=models.CASCADE, related_name='yearly_stats') year = models.IntegerField() works_count = models.IntegerField() cited_by_count = models.IntegerField() class Meta: unique_together = ('author', 'year') class Concept(TimestampedModel): id = models.CharField(max_length=20, primary_key=True) # e.g., C41008148 name = models.CharField(max_length=255) wikidata_url = models.URLField(null=True, blank=True) level = models.IntegerField() score = models.FloatField() def __str__(self): return f"{self.name} ({self.id})" class AuthorConcept(models.Model): author = models.ForeignKey( Author, on_delete=models.CASCADE, related_name='concepts') concept = models.ForeignKey(Concept, on_delete=models.CASCADE) level = models.IntegerField(null=True, blank=True) score = models.FloatField(null=True, blank=True) class Meta: unique_together = ('author', 'concept')